From a463f9a9e04385f0729f7435a0a6dff7d89b25de Mon Sep 17 00:00:00 2001 From: Glenn Elliott Date: Sat, 26 May 2012 17:29:58 -0400 Subject: GPUSync patch for Litmus 2012.1. --- litmus/litmus.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 3 deletions(-) (limited to 'litmus/litmus.c') diff --git a/litmus/litmus.c b/litmus/litmus.c index 301390148d02..d1f836c8af6e 100644 --- a/litmus/litmus.c +++ b/litmus/litmus.c @@ -21,6 +21,10 @@ #include #endif +#ifdef CONFIG_LITMUS_NVIDIA +#include +#endif + /* Number of RT tasks that exist in the system */ atomic_t rt_task_count = ATOMIC_INIT(0); static DEFINE_RAW_SPINLOCK(task_transition_lock); @@ -51,6 +55,28 @@ void bheap_node_free(struct bheap_node* hn) struct release_heap* release_heap_alloc(int gfp_flags); void release_heap_free(struct release_heap* rh); +#ifdef CONFIG_LITMUS_NVIDIA +/* + * sys_register_nv_device + * @nv_device_id: The Nvidia device id that the task want to register + * @reg_action: set to '1' to register the specified device. zero otherwise. + * Syscall for register task's designated nvidia device into NV_DEVICE_REG array + * Returns EFAULT if nv_device_id is out of range. + * 0 if success + */ +asmlinkage long sys_register_nv_device(int nv_device_id, int reg_action) +{ + /* register the device to caller (aka 'current') */ + return(reg_nv_device(nv_device_id, reg_action, current)); +} +#else +asmlinkage long sys_register_nv_device(int nv_device_id, int reg_action) +{ + return(-EINVAL); +} +#endif + + /* * sys_set_task_rt_param * @pid: Pid of the task which scheduling parameters must be changed @@ -269,6 +295,7 @@ asmlinkage long sys_query_job_no(unsigned int __user *job) return retval; } + /* sys_null_call() is only used for determining raw system call * overheads (kernel entry, kernel exit). It has no useful side effects. * If ts is non-NULL, then the current Feather-Trace time is recorded. @@ -286,12 +313,42 @@ asmlinkage long sys_null_call(cycles_t __user *ts) return ret; } + +#if defined(CONFIG_LITMUS_NVIDIA) && defined(CONFIG_LITMUS_AFFINITY_LOCKING) +void init_gpu_affinity_state(struct task_struct* p) +{ + // under-damped + //p->rt_param.gpu_fb_param_a = _frac(14008, 10000); + //p->rt_param.gpu_fb_param_b = _frac(16024, 10000); + + // emperical; + p->rt_param.gpu_fb_param_a[0] = _frac(7550, 10000); + p->rt_param.gpu_fb_param_b[0] = _frac(45800, 10000); + + p->rt_param.gpu_fb_param_a[1] = _frac(8600, 10000); + p->rt_param.gpu_fb_param_b[1] = _frac(40000, 10000); + + p->rt_param.gpu_fb_param_a[2] = _frac(6890, 10000); + p->rt_param.gpu_fb_param_b[2] = _frac(40000, 10000); + + p->rt_param.gpu_fb_param_a[3] = _frac(7580, 10000); + p->rt_param.gpu_fb_param_b[3] = _frac(34590, 10000); + + p->rt_param.gpu_migration = MIG_NONE; + p->rt_param.last_gpu = -1; +} +#endif + /* p is a real-time task. Re-init its state as a best-effort task. */ static void reinit_litmus_state(struct task_struct* p, int restore) { struct rt_task user_config = {}; void* ctrl_page = NULL; +#ifdef CONFIG_LITMUS_NESTED_LOCKING + binheap_order_t prio_order = NULL; +#endif + if (restore) { /* Safe user-space provided configuration data. * and allocated page. */ @@ -299,11 +356,38 @@ static void reinit_litmus_state(struct task_struct* p, int restore) ctrl_page = p->rt_param.ctrl_page; } +#ifdef CONFIG_LITMUS_NESTED_LOCKING + prio_order = p->rt_param.hp_blocked_tasks.compare; +#endif + /* We probably should not be inheriting any task's priority * at this point in time. */ WARN_ON(p->rt_param.inh_task); +#ifdef CONFIG_LITMUS_NESTED_LOCKING + WARN_ON(p->rt_param.blocked_lock); + WARN_ON(!binheap_empty(&p->rt_param.hp_blocked_tasks)); +#endif + +#ifdef CONFIG_LITMUS_SOFTIRQD + /* We probably should not have any tasklets executing for + * us at this time. + */ + WARN_ON(p->rt_param.cur_klitirqd); + WARN_ON(atomic_read(&p->rt_param.klitirqd_sem_stat) == HELD); + + if(p->rt_param.cur_klitirqd) + flush_pending(p->rt_param.cur_klitirqd, p); + + if(atomic_read(&p->rt_param.klitirqd_sem_stat) == HELD) + up_and_set_stat(p, NOT_HELD, &p->rt_param.klitirqd_sem); +#endif + +#ifdef CONFIG_LITMUS_NVIDIA + WARN_ON(p->rt_param.held_gpus != 0); +#endif + /* Cleanup everything else. */ memset(&p->rt_param, 0, sizeof(p->rt_param)); @@ -312,6 +396,15 @@ static void reinit_litmus_state(struct task_struct* p, int restore) p->rt_param.task_params = user_config; p->rt_param.ctrl_page = ctrl_page; } + +#if defined(CONFIG_LITMUS_NVIDIA) && defined(CONFIG_LITMUS_AFFINITY_LOCKING) + init_gpu_affinity_state(p); +#endif + +#ifdef CONFIG_LITMUS_NESTED_LOCKING + INIT_BINHEAP_HANDLE(&p->rt_param.hp_blocked_tasks, prio_order); + raw_spin_lock_init(&p->rt_param.hp_blocked_tasks_lock); +#endif } long litmus_admit_task(struct task_struct* tsk) @@ -358,6 +451,26 @@ long litmus_admit_task(struct task_struct* tsk) bheap_node_init(&tsk_rt(tsk)->heap_node, tsk); } + +#ifdef CONFIG_LITMUS_NVIDIA + atomic_set(&tsk_rt(tsk)->nv_int_count, 0); +#endif +#if defined(CONFIG_LITMUS_NVIDIA) && defined(CONFIG_LITMUS_AFFINITY_LOCKING) + init_gpu_affinity_state(tsk); +#endif +#ifdef CONFIG_LITMUS_NESTED_LOCKING + tsk_rt(tsk)->blocked_lock = NULL; + raw_spin_lock_init(&tsk_rt(tsk)->hp_blocked_tasks_lock); + //INIT_BINHEAP_HANDLE(&tsk_rt(tsk)->hp_blocked_tasks, prio_order); // done by scheduler +#endif +#ifdef CONFIG_LITMUS_SOFTIRQD + /* proxy thread off by default */ + tsk_rt(tsk)is_proxy_thread = 0; + tsk_rt(tsk)cur_klitirqd = NULL; + mutex_init(&tsk_rt(tsk)->klitirqd_sem); + atomic_set(&tsk_rt(tsk)->klitirqd_sem_stat, NOT_HELD); +#endif + retval = litmus->admit_task(tsk); if (!retval) { @@ -403,7 +516,7 @@ static void synch_on_plugin_switch(void* info) */ int switch_sched_plugin(struct sched_plugin* plugin) { - unsigned long flags; + //unsigned long flags; int ret = 0; BUG_ON(!plugin); @@ -417,8 +530,15 @@ int switch_sched_plugin(struct sched_plugin* plugin) while (atomic_read(&cannot_use_plugin) < num_online_cpus()) cpu_relax(); +#ifdef CONFIG_LITMUS_SOFTIRQD + if(!klitirqd_is_dead()) + { + kill_klitirqd(); + } +#endif + /* stop task transitions */ - raw_spin_lock_irqsave(&task_transition_lock, flags); + //raw_spin_lock_irqsave(&task_transition_lock, flags); /* don't switch if there are active real-time tasks */ if (atomic_read(&rt_task_count) == 0) { @@ -436,7 +556,7 @@ int switch_sched_plugin(struct sched_plugin* plugin) } else ret = -EBUSY; out: - raw_spin_unlock_irqrestore(&task_transition_lock, flags); + //raw_spin_unlock_irqrestore(&task_transition_lock, flags); atomic_set(&cannot_use_plugin, 0); return ret; } -- cgit v1.2.2