/*
 * Real-Time and Multimedia Systems Laboratory
 * Copyright (c) 2000 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Real-Time and Multimedia Systems Laboratory
 *  Attn: Prof. Raj Rajkumar
 *  Electrical and Computer Engineering, and Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 *  or via email to raj@ece.cmu.edu
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */


#ifndef	RK_RK_H
#define	RK_RK_H

#define ENFORCE_SIGNAL 10  /* This means: the enforcement signal is the 10th
				Linux RT signal */
#undef	DEBUG_RK  	/* enable debug code */
#undef	EVAL_RK		/* enable evaluation code */
#undef	UPERF_RK	/* enable micro benchmark code */

#ifdef	UPERF_RK
/**/
#undef	EVAL_RK		/* disable evaluation code */
#undef	DEBUG_RK	/* disable debug code */
/**/
extern	int	uperf_rk_isa_timer_programmed;
#endif

#ifdef DEBUG_RK
/**/
#if 1
#undef	DEBUG_RK_ENFORCE
#undef	DEBUG_RK_ENFORCE_NOT
#else
#define	DEBUG_RK_ENFORCE	if (debug_rk_enforce_flag)
#define	DEBUG_RK_ENFORCE_NOT	if (!debug_rk_enforce_flag)
extern	int	debug_rk_enforce_flag;
#endif
/**/
#endif /*DEBUG_RK*/

/*
 * types and defines
 */
typedef	unsigned long long *	cpu_tick_t;
typedef	unsigned long long	cpu_tick_data_t;

#define DEFAULT_PERIOD_SEC      10 /* 10 sec */
#define IDLE_PERIOD_SEC         10 /* 10 sec */
#define	NANOSEC			1000000000L
#define	MICROSEC		1000000L

#define RK_NAME_LEN		16
#define RSET_NAME_LEN		RK_NAME_LEN

#ifndef FALSE
#define FALSE			0
#define TRUE			1
#endif FALSE

//Sourav
#define RK_HISTORY_SIZE 64

#define CEILING_VECTOR_SIZE 10

#ifdef __i386__
static inline void
rk_rdtsc(cpu_tick_t data_p)
{
	__asm __volatile(
		"rdtsc"
		:"=a"(*(int *)(data_p)), "=d"(*(((int *)data_p)+1)));
}
#elif defined(__powerpc__)
static inline void
rk_rdtsc(cpu_tick_t data_p)
{
	asm volatile ("0:mftbu 4;mftb %1;mftbu %0;cmpw 4,%0;bne 0b":"=r" (*(int*)(data_p)),
		 "=r" (*(((int*)data_p)+1)): :"r4");
}
#else
#error I do not know how to read timestamps on this architecture.
#endif

/*
 * CPU reserve argument parameter
 */
enum rt_process_type
{
	APERIODIC	=0x1,
	PERIODIC	=0x2,
	SPORADIC	=0x4,
};
typedef enum rt_process_type	rt_process_type_t;

/*
 * CPU reserve argument parameter
 */
enum rk_reserve_mode
{
	RSV_HARD	=0x1,
	RSV_FIRM	=0x2,
	RSV_SOFT	=0x4,
};
typedef enum rk_reserve_mode	rk_reserve_mode_t;

struct rk_reserve_param {
	rk_reserve_mode_t	sch_mode;	/* scheduling */
	rk_reserve_mode_t	enf_mode;	/* enforcement */
	rk_reserve_mode_t	rep_mode;	/* replenishment */
};
typedef	struct rk_reserve_param	rk_reserve_param_data_t;
typedef	struct rk_reserve_param	*rk_reserve_param_t;


//Sourav...
struct rk_reserve_history{
  cpu_tick_data_t c_ticks;
  unsigned long count;
};
typedef struct rk_reserve_history rk_reserve_history_data_t;
typedef struct rk_reserve_history *rk_reserve_history_t;

struct rk_net_reserve_history{
  unsigned long amount;
  unsigned long count;
};
typedef struct rk_net_reserve_history rk_net_reserve_history_data_t;
typedef struct rk_net_reserve_history *rk_net_reserve_history_t;

#ifndef _LINUX_TIME_H
#include <time.h>	 /* for struct timespec */
#endif _LINUX_TIME_H

/* 
 * ticket issue enable 
 */
enum ticket_type
{ 
  DISABLE =0x0, 
  CONSTANT,  /* constant number of tickets are issued no matter what
		the replenish mode is (SOFT/HARD/FIRM) */
  ADAPTIVE,  /* Not implemented yet */
};
typedef enum ticket_type ticket_type_t;

struct cpu_reserve_attr {
  struct timespec compute_time;
  struct timespec period;
  struct timespec deadline;
  struct timespec blocking_time;
  struct timespec start_time;
  rk_reserve_param_data_t reserve_type;
  ticket_type_t           ticket_type;
  unsigned long           quota_tickets;
  cpu_tick_data_t         ticket_age;
};

typedef struct cpu_reserve_attr cpu_reserve_attr_data_t;
typedef struct cpu_reserve_attr *cpu_reserve_attr_t;

struct net_reserve_attr {
  size_t amount;
  struct timespec net_time;
  struct timespec period;
  struct timespec deadline;
  struct timespec blocking_time;
  struct timespec start_time;
  rk_reserve_param_data_t reserve_type;
  int socket_fd;
  size_t buffer_space;
  char dev_name[16];
};

struct disk_reserve_attr {
  unsigned long  size;  /* size of reserve in Kbytes */
  struct timespec period;
  struct timespec deadline;
  struct timespec blocking_time;
  struct timespec start_time;
  rk_reserve_param_data_t reserve_type;
};

typedef struct net_reserve_attr net_reserve_attr_data_t;
typedef struct net_reserve_attr *net_reserve_attr_t;
typedef struct disk_reserve_attr disk_reserve_attr_data_t;
typedef struct disk_reserve_attr *disk_reserve_attr_t;

/*
 * resource and reserve types
 */
enum rk_reserve_type
{
	RSV_NULL	=0x0,
	RSV_CPU		=0x1,
	RSV_NET		=0x2,
	RSV_RCV         =0x3,
	RSV_MEM,
	RSV_DEV,
	RSV_DISK,
};
typedef	enum rk_reserve_type	rk_reserve_type_t;

#ifdef __KERNEL__
/*
 *	NULL			not running and 
 *                              haven't started yet
 *      START                   not running but started already
 *	RUNNING			running
 *	DEPLETED		not running and depleted
 *	RUNNING|DEPLETED	running but depleted
 */
enum rk_reserve_state
{
	RSV_IS_NULL	=0x0,	/* not running */
	RSV_IS_RUNNING	=0x1,	/* actually running */
	RSV_IS_DEPLETED	=0x10,	/* it's empty */
	RSV_IS_STARTED    =0x100, /* start ? (after cpu_reserve->start_time)*/
};
typedef	enum rk_reserve_state	rk_reserve_state_t;

enum rk_timer_type
{
	TMR_NULL	=0x0,
	TMR_REPLENISH_RSV,	/* used for replenishing reserves  */
	TMR_PERIOD_START,	/* a periodic process's start time */
	TMR_NEXT_PERIOD,	/* periodic timer for processes    */
	TMR_POSIX,		/* used for POSIX timers */
	TMR_JIFFY,		/* Linux timer interrupt */
	TMR_ENFORCE,		/* used for enforcement of CPU reserves */
	TMR_BUFF_PERIOD
};
typedef	enum rk_timer_type	rk_timer_type_t;

/*
 * Typedefs
 */
typedef struct rk_resource_set	*rk_resource_set_t;
typedef struct rk_reserve	*rk_reserve_t;
typedef	struct rk_timer		*rk_timer_t;

/*
 * struct rk_resource_set
 */
struct rk_resource_set {
	char rs_name[RSET_NAME_LEN];            /* name of resource set */
	/* */
	rk_reserve_t		rs_cpu;		/* cpu */
	rk_reserve_t		rs_net;		/* Network */

	rk_reserve_t            rs_rcv;         /* Received network */

	struct list_head	rs_devices;	/* list of device resources */
	/* */
	struct list_head	rs_rs;		/* list of resource_sets */
	/* */
#ifdef	linux
	struct list_head	rs_proc_list;	/* list of processes */
#ifdef RK_NET_RSV
	struct list_head        rs_sock_list;   /*list of sockets */
#endif
	struct proc_dir_entry	*rs_proc_dir;	/* dir entry under /proc/rk */
#endif
	struct list_head        rs_cpu_list;    /* list of cpu reserves */
	rk_reserve_mode_t	sch_mode;	/* scheduling determine by sch_mode of all cpu reserves */
        rk_reserve_t            rs_disk;        /* disk reserve */

  cpu_tick_data_t sched_ovhd; /* check (hack??) to see if this resource set (particularly for a CPu reserve gets charged for wrong the kernel activities; it should not be necessary in future */
  
};


extern	int		rk_resource_set_attach_reserve(rk_resource_set_t, rk_reserve_t);
extern	void		rk_resource_set_detach_reserve(rk_resource_set_t, rk_reserve_t);
/*
 * The following functions are defined as "inline" below.
 *	rk_resource_set_start_account
 *	rk_resource_set_stop_account
 */

/*
 * struct rk_reserve
 */
struct rk_reserve {
	/* */
	struct list_head	rsv_tmr_link;	/* link in timer */
	/* */
	struct list_head	rsv_rs_link;	/* link in resource set    */
	rk_resource_set_t	rsv_rs;         /* parent resource set     */
	rk_reserve_type_t	rsv_type;	/* type                    */
	rk_reserve_state_t	rsv_state;	/* state                   */
	struct rk_reserve_ops	*rsv_ops;	/* rsv operation functions */
	void			*rsv_rsv;	/* link to real one        */
	rk_timer_t		rsv_replenish_tmr;  /* replenishment timer */
	rk_reserve_param_data_t	rsv_reserve_param;  /* soft, firm, hard    */
	/* */
#ifdef	linux
	struct proc_dir_entry	*rsv_proc_entry;/* entry under /proc/rk/<rs_id>/ */
#endif
};

struct rs_proc_list;
#ifdef RK_NET_RSV
struct rs_sock_list;
#endif

struct rk_reserve_ops {
	int			(*destroy) (rk_reserve_t);
	void			(*start_account) (rk_reserve_t);
	void			(*stop_account) (rk_reserve_t, cpu_tick_t);
	void			(*replenish) (rk_reserve_t, cpu_tick_t, cpu_tick_t);
	void			(*enforce) (rk_reserve_t);
	void			(*attach)(rk_reserve_t, struct rs_proc_list *);
	void			(*detach)(rk_reserve_t, struct rs_proc_list *);
#ifdef	linux
	void			(*sleep_on) (rk_reserve_t);
	int			(*read_proc) (rk_reserve_t, char *);
#endif
	void                    (*update_account)(rk_reserve_t, unsigned long);
        void                    (*quota_query)(rk_reserve_t,unsigned long *); 
        void                    (*wait_on_quota)(rk_reserve_t);
};

extern	rk_reserve_t	rk_reserve_create(rk_resource_set_t, rk_reserve_type_t);
extern	int		rk_reserve_destroy(rk_reserve_t);

/*
 * timer for reserves:
 *	replenishment	... periodic
 *	expiration	... aperiodic
 *
 *   - tmr_expire:	holds an absolute time in CPU tick when its timer expires.
 *   - tmr_handler:	keeps the pointer to a handler funcion which is called 
 *			when its timer expires.
 *
 */
struct rk_timer {
	struct list_head	tmr_tmr;	/* list of timers */
	cpu_tick_data_t		tmr_expire;	/* in CPU cycles or ... */
	rk_timer_type_t		tmr_type;	/* timer type */
	/* */
	void			(*tmr_handler)(struct rk_timer*);
						/* handler */
	rk_reserve_t			tmr_rsv;		/* associated reserves */
	cpu_tick_data_t		period;		/* period for periodic timers */
	struct posix_timer	*pt;			/* associated POSIX timer */
	struct wait_queue		*wq;			/* queue to wake up upon signal,
													for period/start timers */
};

#define	NULL_RK_TIMER		((rk_timer_t)0)
#define	NULL_RESOURCE_SET	((rk_resource_set_t)0)
#define	NULL_RESOURCE_SET	((rk_resource_set_t)0)

extern	void	rk_replenish_timer_create(rk_reserve_t, struct timespec);
extern	void	rk_replenish_timer_destroy(rk_reserve_t);

extern	void	rk_enforce_timer_start(rk_reserve_t, cpu_tick_t, cpu_tick_t);
extern	void	rk_enforce_timer_cancel(void);

extern	void	rk_update_hw_timer(struct rk_timer *tmr);
extern	void	rk_hw_timer_set_periodic(void);
extern	void	rk_release_hw_timer(void);
extern	void	rk_update_hw_timer(rk_timer_t tmr);

extern void rt_adjbaseprio(struct task_struct *proc, int policy ,int newbase);

extern rk_resource_set_t ceiling_rs_from_pid(int srv_pid, int clt_pid);

rk_timer_t rk_timer_create(void);
void	rk_timer_add(rk_timer_t tmr);
struct timespec *rk_cur_time(struct timespec *ts);

/* Internal data structure to keep track of tickets.
 * This is for CSS (Cooperative Scheduling Server.
 */
struct ticket{
  unsigned long                 quota_tickets; /* full quota tickets */
  cpu_tick_data_t               ticket_age; /* age of the ticket */
  unsigned long                 available_tickets; /* tickets left */
  cpu_tick_data_t               expiration; /* in CPU ticks units */
};

typedef struct ticket ticket_data_t;
typedef struct ticket *ticket_t;

/*
 * Internal data structure to keep track of cpu capacity usage
 *	99.99% is represented as 9999
 */
typedef	unsigned long		cpu_capacity_t;
typedef	unsigned long long	cpu_capacity_quad_t;

struct cpu_reserve {
	/* current period */
	cpu_tick_data_t	cpu_period_used_ticks;		/* CPU ticks already used 
							   in the current period */
	cpu_tick_data_t	cpu_period_start_ticks;		/* remember start ticks for 
							   the current invocation */
	cpu_tick_data_t	cpu_period_available_ticks;	/* CPU ticks that can be used 
							   for this period */
	struct wait_queue 	*depleted_wait;		/* for enforcement */
	/* execution statistics */
	cpu_tick_data_t		cpu_period_prev_used_ticks;
	cpu_capacity_t		cpu_max_utilization;
	cpu_capacity_t		cpu_min_utilization;
	
	struct timespec absdl;
	
	struct {
		unsigned long		total_count;	/* total count of replenishment */
		cpu_capacity_quad_t	total_utils;	/* summation of utilizations */
	}			cpu_average;
	/* static data */
	struct list_head	cpu_link;		/* link all cpu reserves */
	cpu_reserve_attr_data_t cpu_res_attr;           /* reserve attributes */
	cpu_tick_data_t		cpu_time_ticks;		/* ticks for cpu_time */
	unsigned int            cpu_priority_index;     /* reserve priority index */
	cpu_tick_data_t		cpu_period_ticks;	/* ticks for cpu_period */
	cpu_capacity_t		cpu_capacity;		/* requested capacity */
	rk_reserve_t            rsv;                    /* abstract reserve   */
#if	defined(EVAL_RK)
	unsigned long		cpu_eval_data_count;
	struct cpu_eval_data	*cpu_eval_datap;
#endif
        /* This is for offset_reserve */
        cpu_tick_data_t         cpu_deadline_ticks;     /* ticks for cpu_deadline */
        cpu_tick_data_t         cpu_eligible_deadline_ticks; /* the deadline of the eligible reserve */
        unsigned long           scheduling_policy;      /* use w/ cpu_priority_index  SCHED_FIFO for normal reserves and SCHED_OTHER for reserves in default and idle resource set */
        ticket_data_t           tickets;  /* tickets for this cpu reserve */
	struct wait_queue 	*ticket_wait;		/* for ticket  */

  //Sourav
  rk_reserve_history_data_t   cpu_period_buff_used_ticks[RK_HISTORY_SIZE];
  

};
typedef	struct cpu_reserve	*cpu_reserve_t;

typedef	unsigned long		net_capacity_t;
typedef	unsigned long long	net_capacity_quad_t;


/* Sourav: 
 * Receiving network reserve
 */

#ifdef linux
#include <linux/skbuff.h>
#endif

/**********Thread for receiving side protocol processing ***************/
typedef struct
{
        /* Linux task structure of thread */
        struct task_struct *thread;
        /* semaphore needed on start and creation of thread */
        struct semaphore   startstop_sem;
        /* flag to tell thread whether to die or not */
        int terminate;
        /* queue thread is waiting on */
        struct wait_queue *queue;
                /* process id of the thread */
                pid_t pid;
  rk_resource_set_t rs;
  struct sock *sk;
  unsigned char thread_active;
  int net_queue_empty;
} network_thread;


/**************Receiving network architecture *****************/

/**************Receiving network architecture *****************/

struct rcv_net_reserve {

  /* Following data structures are applicable to receiving side reservation only */
  
  rk_reserve_t rsv;
  
  cpu_tick_data_t start_ticks;
  
  size_t used_amount;

  size_t available_amount;

  size_t prev_used_amount;

  net_capacity_t max_utilization;

  net_capacity_t min_utilization;

  struct {

    unsigned long total_count;

    net_capacity_quad_t total_utils;
    
  } average;

  struct list_head rcv_net_link;

  net_reserve_attr_data_t net_res_attr;
  
  cpu_tick_data_t period_ticks;

  net_capacity_t capacity;

  size_t amount;	

  struct timespec period;

  //#ifdef	linux
  struct sk_buff_head queue; //applicable under receiver reservation only..

  network_thread proto_thread;


	/* <socket> */
	struct sock		*sk;
  //#endif	/* linux */

};

typedef struct rcv_net_reserve *rcv_net_reserve_t;


/*
 * net_reserve structure
 */
struct net_reserve {
	/*current period */
	cpu_tick_data_t	start_ticks;		/* remember start ticks for 
					   	   the current invocation */
	size_t used_amount;			/* used amount
						   in the current period */
	size_t available_amount;		/* available amount
						   for this period */
	struct wait_queue *depleted_wait;	/* for enforcement */
	/* classifier & queueing discipline */
						/* sk_buff queue head */
         /* execution statistics */
        size_t prev_used_amount;
	net_capacity_t max_utilization;
	net_capacity_t min_utilization;
	struct {
		unsigned long total_count; /* total count of replenishment */
		net_capacity_quad_t total_utils; /* summation of utilizations */
	} average;
	/* static data */
	struct list_head net_link;		/* link all net reserves */
	net_reserve_attr_data_t net_res_attr;	/*reserve attributes */

	cpu_tick_data_t	period_ticks;		/* CPU ticks for period */
	net_capacity_t capacity;		/* requested capacity */
	size_t amount;				/* B/W per period */
	rk_reserve_t rsv;			/* abstract reserve   */
	struct timespec period;

	struct timespec deadline;
	struct timespec eligibility_time;
	int queue_number;

	size_t buffer_space;
	size_t consumed_buffer;

#ifdef EVAL_RK_NET
  unsigned long net_eval_data_count;
  struct net_eval_data *net_eval_datap;
#endif

#ifdef	linux
	/* <socket, device> */
	struct sock		*sk;
	struct device		*netdev;
#endif	/* linux */

//Sourav
  rk_net_reserve_history_data_t   net_period_buff_used_bw[RK_HISTORY_SIZE];

};
typedef	struct net_reserve	*net_reserve_t;

/*
 * Internal data structure to keep track of disk reserve 
 * in unit of blocks
 * 
 */
typedef	unsigned long		disk_block_t;
typedef unsigned int            disk_capacity_t;  /* percent */
typedef unsigned long           disk_capacity_quad_t;


struct disk_reserve {
  disk_block_t             used_blocks;
  disk_block_t             available_blocks;
  disk_block_t		   prev_used_blocks;
  disk_capacity_t          disk_capacity;
  struct list_head	   disk_link;           /* link of disk reserves*/
  disk_reserve_attr_data_t disk_res_attr;       /* reserve attributes */
  rk_reserve_t             rsv;                 /* abstract reserve   */
  cpu_tick_data_t	   disk_period_ticks;   /* ticks for period */
  cpu_tick_data_t          disk_deadline_ticks; /* ticks for deadline */
  cpu_tick_data_t          disk_current_deadline_ticks; /*ticks for current deadline; for EDF scheduling */ 
};

typedef	struct disk_reserve	*disk_reserve_t;

/*
 * Global Variables and params
 */
extern	rk_resource_set_t	rk_current_resource_set;
extern  rk_reserve_t            rk_current_cpu_reserve;

extern	cpu_tick_data_t		rk_cpu_ticks_per_second;
extern	cpu_tick_data_t		rk_cpu_ticks_per_jiffy;
extern	cpu_tick_data_t	rk_cpu_tick_at_boot;		/* cpu tick when jiffies == 0 */
extern	cpu_tick_data_t	rk_cpu_tick_at_last_jiffy;	/* cpu tick at the last jiffy*/

#define RK_USECS_PER_JIFFY	(1000016L/HZ)		/* 10000 (HZ=100) */
#define RK_NANOSECS_PER_JIFFY	(1000016762L/HZ)	/* 10000167 (HZ=100) */
/*
 * There are the following conversion inline functions.
 * I don't know why, but MACROs didn't work for those purposes.
 */

#ifdef __RK__ /* Keeps other things that include this from needing __udivdi3 */

/*
 * Conversions between tick and nanosec
 * rk_cpu_ticks_per_second:NANOSEC = ticks:nanosec
 */
static inline void
nanosec2tick(cpu_tick_t ns, cpu_tick_t tick)
{
	cpu_tick_data_t	nanosec = NANOSEC;
	/* *tick = (((*ns)*rk_cpu_ticks_per_second)+(nanosec/2))/nanosec;*/
	*tick = ((*ns)*rk_cpu_ticks_per_second)/nanosec;
}

/* 
 * Conversion between tick and usec
 * rk_cpu_ticks_per_second:MICROSEC = ticks:usec
 */
static inline void
tick2usec(cpu_tick_t tick, cpu_tick_t us)
{
	cpu_tick_data_t	msec = MICROSEC;
	/* *us = (((*tick)*msec)+(rk_cpu_ticks_per_second/2))/rk_cpu_ticks_per_second;*/
	*us = ((*tick)*msec)/rk_cpu_ticks_per_second;
}

static inline unsigned long
TICK2USEC(cpu_tick_t tick)
{
	cpu_tick_data_t	us;
	tick2usec(tick, &us);
	return (unsigned long)us;
}

static inline void
tick2nanosec(cpu_tick_t tick, cpu_tick_t ns)
{
	/* *tick = (((*ns)*rk_cpu_ticks_per_second)+(nanosec/2))/nanosec;*/
	*tick = ((*tick)*NANOSEC)/rk_cpu_ticks_per_second;
}

static inline unsigned long
tick2jiffies(cpu_tick_t tick, cpu_tick_t last_tick)
{
	cpu_tick_data_t	d = (*tick)-(*last_tick);
	unsigned long	j;
	j = (d+rk_cpu_ticks_per_jiffy-1)/rk_cpu_ticks_per_jiffy;
#if 0
	printk("tick2jiffies: tick(%lu usec) last_tick(%lu usec) -> (%lu)\n",
	       TICK2USEC(tick), TICK2USEC(last_tick), j);
#endif
	j += jiffies;
	return j;
}

#endif __RK__


#define	TICK2JIFFIES(tick)	tick2jiffies(tick, &rk_cpu_tick_at_last_jiffy)
#define	TICK2JIFFIES2(tick,last)	tick2jiffies(tick,last)

extern int rk_count;

/*
 * Enable/Disable RK hooks
 */
void rk_inc_use_count(void);
void rk_dec_use_count(void);

static void inline
rk_enable(void)
{
	rk_inc_use_count();
}

static void inline
rk_disable(void)
{
	rk_dec_use_count();
}

/*
 * Start/Stop accounting
 */
static inline void
rk_resource_set_start_account(rk_resource_set_t rs)
{
	rk_reserve_t	cpu = rs->rs_cpu;
	if (cpu) {
		cpu->rsv_ops->start_account(cpu);
	}
}

static inline void
rk_resource_set_stop_account(rk_resource_set_t rs, cpu_tick_t now)
{
	rk_reserve_t	cpu = rs->rs_cpu;
	if (cpu) {
		cpu->rsv_ops->stop_account(cpu, now);
	}
}

static inline void
rk_resource_set_do_enforcement(rk_resource_set_t rs)
{
	rk_reserve_t	cpu = rs->rs_cpu;
	if (cpu) {
		cpu->rsv_ops->enforce(cpu);
	}
}

static inline int
rk_resource_set_depleted(rk_resource_set_t rs)
{
	rk_reserve_t	cpu = rs->rs_cpu;
	if (cpu) {
		return (cpu->rsv_state & RSV_IS_DEPLETED);
	}
	return 0;
}

/* kernel function prototypes */
int rk_valid_rset(rk_resource_set_t);
int rk_valid_rsv(rk_reserve_t);

int		resource_set_attach_process(rk_resource_set_t,struct task_struct *);

int   resource_set_attach_socket(rk_resource_set_t, struct socket *, rk_reserve_type_t);

int resource_set_detach_socket(rk_resource_set_t, struct socket *, rk_reserve_type_t);




void disk_server_wait_for_ticket(void);

#else	/* __KERNEL__ */

/*
 * types for user programs
 */
typedef	void *			rk_resource_set_t;
typedef	void *			rk_reserve_t;

#ifndef __pid_t_defined
#ifndef pid_t
typedef int pid_t;
#define pid_t pid_t
#endif pid_t
#define __pid_t_defined
#endif __pid_t_defined

#endif	/* __KERNEL__ */

#define	NULL_RESERVE		((rk_reserve_t)0)
#define	NULL_RK_TIMER		((rk_timer_t)0)
#define	NULL_RESOURCE_SET	((rk_resource_set_t)0)

/*
 * function prototypes
 */
extern	rk_resource_set_t	rk_resource_set_create(char *);
extern	int		rk_resource_set_destroy(rk_resource_set_t);
extern  int		rk_resource_sets_get_num(void);
extern  int		rk_resource_set_set_name(rk_resource_set_t, char *);
extern  int		rk_resource_set_get_name(rk_resource_set_t, char *);
extern  rk_reserve_t	rk_resource_set_get_cpu_rsv(rk_resource_set_t);
extern  rk_reserve_t	rk_proc_get_resource_set(pid_t pid);
extern  int		rk_resource_sets_get_list(rk_resource_set_t *, int);

extern	rk_reserve_t	rk_cpu_reserve_create(rk_resource_set_t,
					      cpu_reserve_attr_t);

extern	int		rk_cpu_reserve_ctl(rk_reserve_t rsv, 
					   cpu_reserve_attr_t cpu_attr);
extern  int		rk_cpu_reserve_delete(rk_resource_set_t);

extern  int 		rk_cpu_reserves_set_scheduling_policy(int);
extern  int		rk_cpu_reserves_get_scheduling_policy(void);
extern  int		rk_cpu_reserves_get_num(void);
extern  int		rk_cpu_reserves_get_list(rk_reserve_t *rsv, int count);
extern  int		rk_cpu_reserve_get_attr(rk_reserve_t,
						  cpu_reserve_attr_t);

extern void             cpu_reserve_start(rk_reserve_t, cpu_tick_t); 
extern	rk_reserve_t	rk_net_reserve_create(rk_resource_set_t,
					      net_reserve_attr_t);
extern  int             rk_net_reserve_ctl(rk_reserve_t rsv, 
					   net_reserve_attr_t net_attr); 
extern rk_reserve_t     rk_rnet_reserve_create(rk_resource_set_t, net_reserve_attr_t);
extern  int             rk_rnet_reserve_ctl(rk_reserve_t rsv, 
					   net_reserve_attr_t net_attr); 
extern int              rk_disk_set_css(int);
extern rk_reserve_t     rk_disk_reserve_create(rk_resource_set_t, 
					       disk_reserve_attr_t);
extern int              rk_disk_reserve_delete(rk_resource_set_t);
extern int              disk_reserve_delete(rk_resource_set_t, 
					     rk_reserve_t);

extern int              rk_reserve_update_account(rk_reserve_t, unsigned long);
extern int              rk_reserve_quota_query(rk_reserve_t, unsigned long *);
extern void             rk_reserve_wait_on_quota(rk_reserve_t);
extern int              disk_higher_prio(rk_reserve_t, rk_reserve_t);
extern rk_reserve_t     rk_cpu_reserve_dummy_create(rk_resource_set_t,
                                                    time_t);

//Sourav additional system call
extern int             rk_cpu_reserve_get_history(rk_reserve_t rsv, rk_reserve_history_t data);
//rk_reserve_t sys_rk_resource_set_get_cpu_rsv(rk_resource_set_t rs);
//int sys_rk_resource_set_get_name(rk_resource_set_t rs, char *name);

#ifdef	linux
extern	int		rk_resource_set_attach_process(rk_resource_set_t,pid_t);
extern int              rk_resource_set_attach_socket(rk_resource_set_t, int, rk_reserve_type_t);
extern	int		rk_resource_set_detach_process(rk_resource_set_t,pid_t);
extern int              rk_resource_set_detach_socket(rk_resource_set_t, int, rk_reserve_type_t);
extern	void		rk_proc_rs_create(rk_resource_set_t);
extern	void		rk_proc_rs_destroy(rk_resource_set_t);
extern	void		rk_proc_reserve_create(rk_reserve_t);
extern	void		rk_proc_reserve_destroy(rk_reserve_t);

extern unsigned long    rt_get_clock_frequency(void);
extern int              cpu_reserve_delete(rk_resource_set_t rs);
extern int		rk_resource_set_get_proclist(rk_resource_set_t rs, 
						     pid_t *procs);
extern int 		rk_resource_set_get_num_procs(rk_resource_set_t rs);

extern rk_reserve_t     rk_cpu_ceiling_reserve_create(rk_reserve_t brs,rk_resource_set_t nrs, cpu_reserve_attr_t a);
extern int              rk_attach_ceiling_rs(rk_resource_set_t rs,pid_t s, pid_t c);
extern int              rk_detach_ceiling_rs(rk_resource_set_t rs,pid_t s, pid_t c);

#endif	/* linux */

/* system calls for POSIX timers */

/* system calls for periodic tasks       */
int rt_make_periodic(struct timespec *period, struct timespec *start);
int rt_wait_for_start_time(void);
int rt_wait_for_next_period(void);
int rt_process_get_period(pid_t pid, struct timespec *period);
int rt_process_set_period(pid_t pid, struct timespec *period);

long int rt_get_scheduling_error(void);

/* system calls for priority inheritance */

#define PTHREAD_PRIO_NONE	0
#define PTHREAD_PRIO_INHERIT 1

#ifndef __KERNEL__
int rt_mutex_create(int proto, int gid);
int rt_mutex_destroy(int mutex_id);
int rt_mutex_lock(int mutex_id);
int rt_mutex_trylock(int mutex_id);
int rt_mutex_unlock(int mutex_id);
#endif

/* Miscellaneous system calls */
void rk_inherit_mode(int mode);


#ifdef APPLE_DEBUG
int rk_cleanup(void);
#endif APPLE_DEBUG

#endif	/* RK_RK_H */

