/* 
 * 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_LINUX_H
#define	RK_RK_LINUX_H

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/param.h>
#include <asm/spinlock.h>

#ifndef	RK_RK_H
#include <rk/rk.h>
#endif RK_RK_H
/*
 * Spin Lock & Unlock
 * Usage:
 *	{
 *		unsigned long flags;
 *
 *		rk_spin_lock(flags);
 *		<CRITICAL SECTION>
 *		rk_spin_unlock(flags);
 *	}
 */
extern	spinlock_t	rk_lock;
extern volatile int rk_in_intr;
#define	rk_spin_lock(flags)	spin_lock_irqsave(&rk_lock, flags)
#define	rk_spin_unlock(flags)	spin_unlock_irqrestore(&rk_lock, flags)

/*
 *
 */
asmlinkage int sys_sched_setscheduler(pid_t, int, struct sched_param*);

struct rs_proc_list {
	struct list_head	rs_proc_list;
	pid_t			rs_proc_pid;
	struct task_struct	*rs_proc_task;
};

#ifdef RK_NET_RSV
struct rs_sock_list {
  struct list_head rs_sock_list;
  struct sock * sk;
};
#endif

static inline void
rs_proc_list_apply(struct list_head *proc_list_head, void (*func)(struct rs_proc_list *, unsigned int), unsigned int arg)
{
	struct list_head	*proc_list;
	struct rs_proc_list	*rs_proc;

	proc_list = proc_list_head->next;
	while (proc_list != proc_list_head) {
		/* get a rs_proc */
		rs_proc = list_entry(proc_list, struct rs_proc_list, rs_proc_list);
		/* do it */
		func(rs_proc, arg);

		/* next process */
		proc_list = proc_list->next;
	}
}

static inline void
rs_proc_list_apply_rs(struct list_head *proc_list_head, void (*func)(struct rs_proc_list *, rk_resource_set_t), rk_resource_set_t rs)
{
	struct list_head	*proc_list;
	struct rs_proc_list	*rs_proc;

	proc_list = proc_list_head->next;
	while (proc_list != proc_list_head) {
		/* get a rs_proc */
		rs_proc = list_entry(proc_list, struct rs_proc_list, rs_proc_list);
		/* find next process; 
		 * do this first before invoking function to play safe if
		 * func delete the current process from the proc_list */
		proc_list = proc_list->next;

		/* do it */
		func(rs_proc, rs);

	}
}

/* conditional apply */
static inline void
rs_proc_list_condition_rs_apply(struct list_head *proc_list_head, rk_resource_set_t rs, void (*func)(struct rs_proc_list *, cpu_reserve_t), cpu_reserve_t arg)
{
	struct list_head	*proc_list;
	struct rs_proc_list	*rs_proc;

	proc_list = proc_list_head->next;
	while (proc_list != proc_list_head) {
		/* get a rs_proc */
		rs_proc = list_entry(proc_list, struct rs_proc_list, rs_proc_list);
		/* find next process; 
		 * do this first before invoking function to play safe if
		 * func delete the current process from the proc_list */
		proc_list = proc_list->next;

		/* do it if its current resource set is rs*/
		if (rs_proc->rs_proc_task->rk_resource_set == rs)
		  func(rs_proc, arg);

	}
}

/*
 *
 */
#define	malloc(s)	kmalloc(s, SLAB_KERNEL)
#define	free(p)		kfree(p)
#define	bzero(p, s)	memset(p, 0, s)

/*
 *
 */
static inline
struct task_struct *
__rk_find_process_by_pid(pid_t pid)
{
	struct task_struct *tsk = current;

	if (pid)
		tsk = find_task_by_pid(pid);
	return tsk;
}

#if 0
/*
 * suspend & resume a task
 *		
 */
static inline void
rk_suspend_thread(struct task_struct *tsk)
{
#ifdef	DEBUG_RK
	printk("rk_suspend_thread: process(0x%x)\n", (int)tsk);
#endif

	tsk->state = TASK_STOPPED;
	tsk->need_resched = 1;
}

static inline void
rk_resume_thread(struct task_struct *tsk)
{
#ifdef	DEBUG_RK
	printk("rk_resume_thread: process(0x%x)\n", (int)tsk);
#endif

	tsk->need_resched = 0;
	wake_up_process(tsk);
}
#endif

/*
 * Hooks
 */
struct task_struct;

/* arch/ppc/kernel/time.c */
extern int	(*rk_timer_interrupt_hook)(void);
/* arch/i386/kernel/irq.h */
extern void	(*rk_kernel_intr_in_hook)(void);
/* arch/i386/kernel/entry.S */
extern void	(*rk_restore_all_hook)(struct pt_regs regs);
extern int	(*rk_ret_with_reschedule_hook)(struct pt_regs regs);
/* kernel/sched.c */
extern void	(*rk_schedule_hook)(struct task_struct *, struct task_struct *);
extern void (*rt_adjbaseprio_hook)(struct task_struct *, int , int);
/* kernel/exit.c */
extern void (*rk_task_cleanup_hook)(struct task_struct *);
/* kernel/fork.c */
extern void (*rk_fork_hook)(struct task_struct *);
/* fs/buffer.c */
extern void (*rk_disk_reserve_hook)(struct task_struct *, struct buffer_head *);

#endif	/* RK_RK_LINUX_H */
