Index: guest-sched-2.6.11/arch/um/kernel/skas/process_kern.c =================================================================== --- guest-sched-2.6.11.orig/arch/um/kernel/skas/process_kern.c 2005-04-20 16:51:13.000000000 -0400 +++ guest-sched-2.6.11/arch/um/kernel/skas/process_kern.c 2005-04-20 16:59:13.000000000 -0400 @@ -47,8 +47,6 @@ return(current->thread.prev_sched); } -extern void schedule_tail(struct task_struct *prev); - void new_thread_handler(int sig) { int (*fn)(void *), n; Index: guest-sched-2.6.11/arch/um/kernel/tt/process_kern.c =================================================================== --- guest-sched-2.6.11.orig/arch/um/kernel/tt/process_kern.c 2005-04-20 16:51:13.000000000 -0400 +++ guest-sched-2.6.11/arch/um/kernel/tt/process_kern.c 2005-04-20 16:59:00.000000000 -0400 @@ -123,8 +123,6 @@ panic("read failed in suspend_new_thread, err = %d", -err); } -void schedule_tail(task_t *prev); - static void new_thread_handler(int sig) { unsigned long disable; Index: guest-sched-2.6.11/fs/proc/base.c =================================================================== --- guest-sched-2.6.11.orig/fs/proc/base.c 2005-04-19 18:46:19.000000000 -0400 +++ guest-sched-2.6.11/fs/proc/base.c 2005-04-19 18:47:19.000000000 -0400 @@ -119,6 +119,7 @@ #ifdef CONFIG_AUDITSYSCALL PROC_TID_LOGINUID, #endif + PROC_TID_SCHED_GROUP, PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */ PROC_TID_OOM_SCORE, PROC_TID_OOM_ADJUST, @@ -1699,6 +1700,67 @@ .follow_link = proc_self_follow_link, }; +static int sched_group(int pid) +{ + struct task_struct *task; + + read_lock(&tasklist_lock); + task = find_task_by_pid(pid); + if (task) + get_task_struct(task); + read_unlock(&tasklist_lock); + pid = -ENOENT; + if (!task) + goto out; + + pid = task_sched_pid(task); + out: + put_task_struct(task); + return pid; +} + +static int sched_group_str(const char *name) +{ + char *end; + int pid = simple_strtol(name, &end, 10); + + if(*end != '\0') + return -EINVAL; + + return sched_group(pid); +} + +static int proc_pid_sched_readlink(struct dentry *dentry, char __user *buffer, + int buflen) +{ + char tmp[sizeof("sched-groups/12345/12345")]; + int group = sched_group_str(dentry->d_name.name); + + if(group < 0) + return group; + + sprintf(tmp, "sched-groups/%d/%s", group, dentry->d_name.name); + return vfs_readlink(dentry,buffer,buflen,tmp); +} + +static int proc_pid_sched_follow_link(struct dentry *dentry, + struct nameidata *nd) +{ + char tmp[sizeof("sched-groups/12345/12345")]; + int group = sched_group_str(dentry->d_name.name); + + if(group < 0) + return group; + + sprintf(tmp, "sched-groups/%d/%s", group, dentry->d_name.name); + return vfs_follow_link(nd,tmp); +} + +static struct inode_operations proc_pid_inode_operations = { + .readlink = proc_pid_sched_readlink, + .follow_link = proc_pid_sched_follow_link, +}; + /** * proc_pid_unhash - Unhash /proc/ entry from the dcache. * @p: task that should be flushed. @@ -1753,6 +1815,63 @@ } } +struct dentry *sched_group_lookup(struct inode *dir, struct dentry * dentry, + struct nameidata *nd) +{ + struct proc_dir_entry *entry = PDE(dir); + struct task_struct *task; + struct inode *inode; + unsigned tgid; + int died = 0; + + tgid = name_to_int(dentry); + if (tgid == ~0U) + goto out; + + read_lock(&tasklist_lock); + task = find_task_by_pid(tgid); + if (task) + get_task_struct(task); + read_unlock(&tasklist_lock); + if (!task) + goto out; + + if(sched_group(tgid) != sched_pid(entry->data)) + goto out_put; + + inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_SCHED_GROUP); + + if (!inode) { + put_task_struct(task); + goto out; + } + inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; + inode->i_op = &proc_tgid_base_inode_operations; + inode->i_fop = &proc_tgid_base_operations; + inode->i_nlink = 3; + + dentry->d_op = &pid_base_dentry_operations; + + d_add(dentry, inode); + spin_lock(&task->proc_lock); + task->proc_dentry = dentry; + if (!pid_alive(task)) { + dentry = proc_pid_unhash(task); + died = 1; + } + spin_unlock(&task->proc_lock); + + out_put: + put_task_struct(task); + if (died) { + proc_pid_flush(dentry); + goto out; + } + return NULL; +out: + return ERR_PTR(-ENOENT); +} + /* SMP-safe */ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) { @@ -1791,18 +1910,14 @@ inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO); - if (!inode) { put_task_struct(task); goto out; } - inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; - inode->i_op = &proc_tgid_base_inode_operations; - inode->i_fop = &proc_tgid_base_operations; - inode->i_nlink = 3; - inode->i_flags|=S_IMMUTABLE; - dentry->d_op = &pid_base_dentry_operations; + inode->i_mode = S_IFLNK|S_IRWXUGO; + inode->i_size = 64; + inode->i_op = &proc_pid_inode_operations; died = 0; d_add(dentry, inode); @@ -1943,6 +2058,76 @@ return nr_tids; } +int sched_group_readdir(struct file * filp, void * dirent, filldir_t filldir) +{ + unsigned int tgid_array[PROC_MAXPIDS]; + char buf[PROC_NUMBUF]; + unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; + unsigned int nr_tgids, i; + int next_tgid; + struct proc_dir_entry *entry; + + if (filp->f_pos < FIRST_PROCESS_ENTRY){ + filp->f_pos = FIRST_PROCESS_ENTRY; + nr = filp->f_pos - FIRST_PROCESS_ENTRY; + } + + /* The remnants of /proc/self */ + if (!nr) { + filp->f_pos++; + nr++; + } + + entry = PDE(filp->f_dentry->d_inode); + + /* f_version caches the tgid value that the last readdir call couldn't + * return. lseek aka telldir automagically resets f_version to 0. + */ + next_tgid = filp->f_version; + filp->f_version = 0; + for (;;) { + nr_tgids = get_tgid_list(nr, next_tgid, tgid_array); + if (!nr_tgids) { + /* no more entries ! */ + break; + } + next_tgid = 0; + + /* do not use the last found pid, reserve it for next_tgid */ + if (nr_tgids == PROC_MAXPIDS) { + nr_tgids--; + next_tgid = tgid_array[nr_tgids]; + } + + for (i=0;idata)){ + filp->f_pos++; + nr++; + continue; + } + + do + buf[--j] = '0' + (tgid % 10); + while ((tgid /= 10) != 0); + + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) { + /* returning this tgid failed, save it as the first + * pid for the next readir call */ + filp->f_version = tgid_array[i]; + goto out; + } + filp->f_pos++; + nr++; + } + } +out: + return 0; +} + /* for the /proc/ directory itself, after non-process stuff has been done */ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { @@ -1988,7 +2173,7 @@ buf[--j] = '0' + (tgid % 10); while ((tgid /= 10) != 0); - if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) { + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_LNK) < 0) { /* returning this tgid failed, save it as the first * pid for the next readir call */ filp->f_version = tgid_array[i]; Index: guest-sched-2.6.11/include/linux/init_task.h =================================================================== --- guest-sched-2.6.11.orig/include/linux/init_task.h 2005-04-19 18:46:19.000000000 -0400 +++ guest-sched-2.6.11/include/linux/init_task.h 2005-04-19 18:47:19.000000000 -0400 @@ -111,6 +111,7 @@ .switch_lock = SPIN_LOCK_UNLOCKED, \ .journal_info = NULL, \ .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ + .scheduler = &o1_scheduler, \ } Index: guest-sched-2.6.11/include/linux/kernel_stat.h =================================================================== --- guest-sched-2.6.11.orig/include/linux/kernel_stat.h 2005-04-19 18:46:19.000000000 -0400 +++ guest-sched-2.6.11/include/linux/kernel_stat.h 2005-04-19 18:47:19.000000000 -0400 @@ -36,7 +36,7 @@ /* Must have preemption disabled for this to be meaningful. */ #define kstat_this_cpu __get_cpu_var(kstat) -extern unsigned long long nr_context_switches(void); +#define nr_context_switches() current->scheduler->task_ops.nr_context_switches() /* * Number of interrupts per specific IRQ source, since bootup @@ -52,8 +52,11 @@ return sum; } -extern void account_user_time(struct task_struct *, cputime_t); -extern void account_system_time(struct task_struct *, int, cputime_t); -extern void account_steal_time(struct task_struct *, cputime_t); +#define account_user_time(task, t) \ + (task)->scheduler->task_ops.account_user_time(task, t) +#define account_system_time(task, o, t) \ + (task)->scheduler->task_ops.account_system_time(task, o, t) +#define account_steal_time(task, t) \ + (task)->scheduler->task_ops.account_steal_time(task, t) #endif /* _LINUX_KERNEL_STAT_H */ Index: guest-sched-2.6.11/include/linux/sched.h =================================================================== --- guest-sched-2.6.11.orig/include/linux/sched.h 2005-04-19 18:46:19.000000000 -0400 +++ guest-sched-2.6.11/include/linux/sched.h 2005-04-20 20:58:20.000000000 -0400 @@ -35,6 +35,15 @@ #include #include +/* + * Convert user-nice values [ -20 ... 0 ... 19 ] + * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], + * and back. + */ +#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20) +#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) +#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio) + struct exec_domain; /* @@ -94,9 +103,9 @@ extern int last_pid; DECLARE_PER_CPU(unsigned long, process_counts); extern int nr_processes(void); -extern unsigned long nr_running(void); -extern unsigned long nr_uninterruptible(void); -extern unsigned long nr_iowait(void); +#define nr_running() current->scheduler->task_ops.nr_running() +#define nr_uninterruptible() current->scheduler->task_ops.nr_uninterruptible() +#define nr_iowait() current->scheduler->task_ops.nr_iowait() #include #include @@ -152,9 +161,16 @@ typedef struct task_struct task_t; -extern void sched_init(void); +#define task_timeslice(p) (p)->scheduler->task_ops.task_timeslice(p) +#define try_to_wake_up(p, state, sync) \ + (p)->scheduler->task_ops.try_to_wake_up(p, state, sync) + +#define sched_init() current->scheduler->task_ops.sched_init_fn() +#define init_idle(t, cpu) (t)->scheduler->task_ops.init_idle(t, cpu) + +#define schedule_tail(p) (p)->scheduler->task_ops.schedule_tail(p) + extern void sched_init_smp(void); -extern void init_idle(task_t *idle, int cpu); extern cpumask_t nohz_cpu_mask; @@ -168,13 +184,15 @@ */ extern void show_stack(struct task_struct *task, unsigned long *sp); -void io_schedule(void); -long io_schedule_timeout(long timeout); +#define io_schedule() current->scheduler->task_ops.io_schedule() +#define io_schedule_timeout(timeout) \ + current->scheduler->task_ops.io_schedule_timeout(timeout) +#define do_sched_yield() current->scheduler->task_ops.sched_yield() extern void cpu_init (void); extern void trap_init(void); extern void update_process_times(int user); -extern void scheduler_tick(void); +#define scheduler_tick() current->scheduler->task_ops.scheduler_tick() extern unsigned long cache_decay_ticks; /* Attach to any functions which should be ignored in wchan output. */ @@ -184,7 +202,7 @@ #define MAX_SCHEDULE_TIMEOUT LONG_MAX extern signed long FASTCALL(schedule_timeout(signed long timeout)); -asmlinkage void schedule(void); +#define schedule() current->scheduler->task_ops.schedule() struct namespace; @@ -205,6 +223,72 @@ extern void arch_unmap_area(struct vm_area_struct *area); extern void arch_unmap_area_topdown(struct vm_area_struct *area); +struct sched_task_ops { + /* Sleep */ + asmlinkage void (*schedule)(void); + void (*io_schedule)(void); + long (*io_schedule_timeout)(long timeout); + + /* Wake-up */ +#ifdef CONFIG_SMP + void (*wait_task_inactive)(task_t * p); +#endif + void fastcall (*wake_up_new_task)(task_t * p, + unsigned long clone_flags); + void fastcall (*sched_exit)(task_t * p); + asmlinkage void (*schedule_tail)(task_t *prev); + + /* Policy */ + void (*set_user_nice)(task_t *p, long nice); + int (*sched_setscheduler)(struct task_struct *p, int policy, + struct sched_param *param); +#ifdef CONFIG_SMP + int (*set_cpus_allowed)(task_t *p, cpumask_t new_mask); +#endif + long (*sched_yield)(void); + unsigned long (*nr_running)(void); + unsigned long (*nr_uninterruptible)(void); + unsigned long long (*nr_context_switches)(void); + unsigned long (*nr_iowait)(void); + unsigned long long (*current_sched_time)(const task_t *tsk); + void (*account_user_time)(struct task_struct *p, cputime_t cputime); + void (*account_system_time)(struct task_struct *p, int hardirq_offset, + cputime_t cputime); + void (*account_steal_time)(struct task_struct *p, cputime_t steal); + void (*scheduler_tick)(void); + int (*idle_cpu)(int cpu); + task_t *(*idle_task)(int cpu); + unsigned int (*task_timeslice)(task_t *p); + int (*try_to_wake_up)(task_t * p, unsigned int state, int sync); + void (*sched_init_fn)(void); + int (*task_curr)(const task_t *p); + void (*init_idle)(task_t *idle, int cpu); +}; + +struct scheduler { + struct list_head list; + struct task_struct *container; + char *name; + int is_guest; + unsigned int inode; + struct completion wakeup; + spinlock_t lock; + struct list_head incoming; + struct sched_task_ops task_ops; +}; + +extern struct scheduler o1_scheduler; + +extern int register_scheduler(struct scheduler *scheduler, char *name); +extern int register_sched_group(int pid, struct scheduler *scheduler); +extern int task_sched_pid(struct task_struct *task); +extern int init_sched_instance(struct scheduler *scheduler); +extern void uninit_sched_instance(struct scheduler *scheduler); +extern int sched_pid(void *sched); +extern void handle_incoming(struct scheduler *scheduler); + +#define sched_add_task(p) p->scheduler->task_ops.sched_add_task(p) +#define sched_remove_task(p) p->scheduler->task_ops.sched_remove_task(p) struct mm_struct { struct vm_area_struct * mmap; /* list of VMAs */ @@ -719,6 +803,7 @@ nodemask_t mems_allowed; int cpuset_mems_generation; #endif + struct scheduler *scheduler; }; static inline pid_t process_group(struct task_struct *tsk) @@ -808,7 +893,7 @@ #endif extern unsigned long long sched_clock(void); -extern unsigned long long current_sched_time(const task_t *current_task); +#define current_sched_time(t) (t)->scheduler->task_ops.current_sched_time(t) /* sched_exec is called by processes performing an exec */ #ifdef CONFIG_SMP @@ -824,13 +909,14 @@ #endif extern void sched_idle_next(void); -extern void set_user_nice(task_t *p, long nice); +#define set_user_nice(p, nice) (p)->scheduler->task_ops.set_user_nice(p, nice) extern int task_prio(const task_t *p); extern int task_nice(const task_t *p); -extern int task_curr(const task_t *p); -extern int idle_cpu(int cpu); -extern int sched_setscheduler(struct task_struct *, int, struct sched_param *); -extern task_t *idle_task(int cpu); +#define task_curr(p) (p)->scheduler->task_ops.task_curr(p) +#define idle_cpu(cpu) current->scheduler->task_ops.idle_cpu(cpu) +#define sched_setscheduler(p, policy, param) \ + (p)->scheduler->task_ops.sched_setscheduler(p, policy, param) +#define idle_task(cpu) current->scheduler->task_ops.idle_task(cpu) void yield(void); @@ -880,8 +966,9 @@ extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state)); extern int FASTCALL(wake_up_process(struct task_struct * tsk)); -extern void FASTCALL(wake_up_new_task(struct task_struct * tsk, - unsigned long clone_flags)); +#define wake_up_new_task(tsk, clone_flags) \ + (tsk)->scheduler->task_ops.wake_up_new_task(tsk, clone_flags) + #ifdef CONFIG_SMP extern void kick_process(struct task_struct *tsk); #else @@ -889,6 +976,7 @@ #endif extern void FASTCALL(sched_fork(task_t * p)); extern void FASTCALL(sched_exit(task_t * p)); +#define sched_exit(p) (p)->scheduler->task_ops.sched_exit(p) extern int in_group_p(gid_t); extern int in_egroup_p(gid_t); Index: guest-sched-2.6.11/kernel/Makefile =================================================================== --- guest-sched-2.6.11.orig/kernel/Makefile 2005-04-20 17:09:23.000000000 -0400 +++ guest-sched-2.6.11/kernel/Makefile 2005-04-20 20:58:24.000000000 -0400 @@ -2,12 +2,13 @@ # Makefile for the linux kernel. # -obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ - exit.o itimer.o time.o softirq.o resource.o \ +obj-y = sched.o host_sched.o fork.o exec_domain.o panic.o printk.o \ + profile.o exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ rcupdate.o intermodule.o extable.o params.o posix-timers.o \ - kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o + kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o \ + sched_group.o obj-$(CONFIG_FUTEX) += futex.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o Index: guest-sched-2.6.11/kernel/host_sched.c =================================================================== --- guest-sched-2.6.11.orig/kernel/host_sched.c 2003-09-15 09:40:47.000000000 -0400 +++ guest-sched-2.6.11/kernel/host_sched.c 2005-04-20 17:07:06.000000000 -0400 @@ -0,0 +1,10 @@ +#include + +int init_sched_instance(struct scheduler *scheduler) +{ + return register_sched_group(0, scheduler); +} + +void uninit_sched_instance(struct scheduler *scheduler) +{ +} Index: guest-sched-2.6.11/kernel/sched.c =================================================================== --- guest-sched-2.6.11.orig/kernel/sched.c 2005-04-20 11:19:10.000000000 -0400 +++ guest-sched-2.6.11/kernel/sched.c 2005-04-20 20:58:24.000000000 -0400 @@ -166,7 +166,7 @@ #define SCALE_PRIO(x, prio) \ max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE) -static unsigned int task_timeslice(task_t *p) +static unsigned int o1_task_timeslice(task_t *p) { if (p->static_prio < NICE_TO_PRIO(0)) return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio); @@ -801,7 +801,7 @@ * task_curr - is this task currently executing on a CPU? * @p: the task in question. */ -inline int task_curr(const task_t *p) +static inline int o1_task_curr(const task_t *p) { return cpu_curr(task_cpu(p)) == p; } @@ -860,7 +860,7 @@ * smp_call_function() if an IPI is sent by the same process we are * waiting to become inactive. */ -void wait_task_inactive(task_t * p) +static void wait_task_inactive(task_t * p) { unsigned long flags; runqueue_t *rq; @@ -984,7 +984,7 @@ * * returns failure only if the task is already active. */ -static int try_to_wake_up(task_t * p, unsigned int state, int sync) +static int o1_try_to_wake_up(task_t * p, unsigned int state, int sync) { int cpu, this_cpu, success = 0; unsigned long flags; @@ -1204,7 +1204,7 @@ * that must be done for every newly created context, then puts the task * on the runqueue and wakes it. */ -void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags) +static void fastcall o1_wake_up_new_task(task_t * p, unsigned long clone_flags) { unsigned long flags; int this_cpu, cpu; @@ -1290,7 +1290,7 @@ * artificially, because any timeslice recovered here * was given away by the parent in the first place.) */ -void fastcall sched_exit(task_t * p) +static void fastcall o1_sched_exit(task_t * p) { unsigned long flags; runqueue_t *rq; @@ -1357,7 +1357,7 @@ * schedule_tail - first thing a freshly forked thread must call. * @prev: the thread we just switched away from. */ -asmlinkage void schedule_tail(task_t *prev) +static asmlinkage void o1_schedule_tail(task_t *prev) __releases(rq->lock) { finish_task_switch(prev); @@ -1402,7 +1402,7 @@ * threads, current number of uninterruptible-sleeping threads, total * number of context switches performed since bootup. */ -unsigned long nr_running(void) +static unsigned long o1_nr_running(void) { unsigned long i, sum = 0; @@ -1412,7 +1412,7 @@ return sum; } -unsigned long nr_uninterruptible(void) +static unsigned long o1_nr_uninterruptible(void) { unsigned long i, sum = 0; @@ -1429,7 +1429,7 @@ return sum; } -unsigned long long nr_context_switches(void) +static unsigned long long o1_nr_context_switches(void) { unsigned long long i, sum = 0; @@ -1439,7 +1439,7 @@ return sum; } -unsigned long nr_iowait(void) +static unsigned long o1_nr_iowait(void) { unsigned long i, sum = 0; @@ -2257,7 +2257,7 @@ * Return current->sched_time plus any more ns on the sched_clock * that have not yet been banked. */ -unsigned long long current_sched_time(const task_t *tsk) +unsigned long long o1_current_sched_time(const task_t *tsk) { unsigned long long ns; unsigned long flags; @@ -2290,7 +2290,7 @@ * @hardirq_offset: the offset to subtract from hardirq_count() * @cputime: the cpu time spent in user space since the last update */ -void account_user_time(struct task_struct *p, cputime_t cputime) +static void o1_account_user_time(struct task_struct *p, cputime_t cputime) { struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; cputime64_t tmp; @@ -2311,8 +2311,8 @@ * @hardirq_offset: the offset to subtract from hardirq_count() * @cputime: the cpu time spent in kernel space since the last update */ -void account_system_time(struct task_struct *p, int hardirq_offset, - cputime_t cputime) +static void o1_account_system_time(struct task_struct *p, int hardirq_offset, + cputime_t cputime) { struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; runqueue_t *rq = this_rq(); @@ -2343,7 +2343,7 @@ * @p: the process from which the cpu time has been stolen * @steal: the cpu time spent in involuntary wait */ -void account_steal_time(struct task_struct *p, cputime_t steal) +static void o1_account_steal_time(struct task_struct *p, cputime_t steal) { struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; cputime64_t tmp = cputime_to_cputime64(steal); @@ -2366,7 +2366,7 @@ * It also gets called by the fork code, when changing the parent's * timeslices. */ -void scheduler_tick(void) +static void o1_scheduler_tick(void) { int cpu = smp_processor_id(); runqueue_t *rq = this_rq(); @@ -2619,7 +2619,7 @@ /* * schedule() is the main scheduler function. */ -asmlinkage void __sched schedule(void) +static asmlinkage void __sched o1_schedule(void) { long *switch_count; task_t *prev, *next; @@ -2789,8 +2789,6 @@ goto need_resched; } -EXPORT_SYMBOL(schedule); - #ifdef CONFIG_PREEMPT /* * this is is the entry point to schedule() from in-kernel preemption @@ -3186,7 +3184,7 @@ EXPORT_SYMBOL(sleep_on_timeout); -void set_user_nice(task_t *p, long nice) +static void o1_set_user_nice(task_t *p, long nice) { unsigned long flags; prio_array_t *array; @@ -3233,8 +3231,6 @@ task_rq_unlock(rq, &flags); } -EXPORT_SYMBOL(set_user_nice); - #ifdef __ARCH_WANT_SYS_NICE /* @@ -3314,18 +3310,16 @@ * idle_cpu - is a given cpu idle currently? * @cpu: the processor in question. */ -int idle_cpu(int cpu) +static int o1_idle_cpu(int cpu) { return cpu_curr(cpu) == cpu_rq(cpu)->idle; } -EXPORT_SYMBOL_GPL(idle_cpu); - /** * idle_task - return the idle task for a given cpu. * @cpu: the processor in question. */ -task_t *idle_task(int cpu) +static task_t *o1_idle_task(int cpu) { return cpu_rq(cpu)->idle; } @@ -3358,7 +3352,8 @@ * @policy: new policy. * @param: structure containing the new RT priority. */ -int sched_setscheduler(struct task_struct *p, int policy, struct sched_param *param) +static int o1_sched_setscheduler(struct task_struct *p, int policy, + struct sched_param *param) { int retval; int oldprio, oldpolicy = -1; @@ -3425,7 +3420,6 @@ task_rq_unlock(rq, &flags); return 0; } -EXPORT_SYMBOL_GPL(sched_setscheduler); static int do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) { @@ -3677,7 +3671,7 @@ * to the expired array. If there are no other threads running on this * CPU then this function will return. */ -asmlinkage long sys_sched_yield(void) +static long o1_sched_yield(void) { runqueue_t *rq = this_rq_lock(); prio_array_t *array = current->array; @@ -3723,6 +3717,11 @@ return 0; } +asmlinkage long sys_sched_yield(void) +{ + return do_sched_yield(); +} + static inline void __cond_resched(void) { do { @@ -3810,7 +3809,7 @@ * But don't do that if it is a deliberate, throttling IO wait (this task * has set its backing_dev_info: the queue against which it should throttle) */ -void __sched io_schedule(void) +static void __sched o1_io_schedule(void) { struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id()); @@ -3819,9 +3818,7 @@ atomic_dec(&rq->nr_iowait); } -EXPORT_SYMBOL(io_schedule); - -long __sched io_schedule_timeout(long timeout) +static long __sched o1_io_schedule_timeout(long timeout) { struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id()); long ret; @@ -4014,7 +4011,7 @@ read_unlock(&tasklist_lock); } -void __devinit init_idle(task_t *idle, int cpu) +static void o1_init_idle(task_t *idle, int cpu) { runqueue_t *rq = cpu_rq(cpu); unsigned long flags; @@ -4023,7 +4020,6 @@ idle->array = NULL; idle->prio = MAX_PRIO; idle->state = TASK_RUNNING; - idle->cpus_allowed = cpumask_of_cpu(cpu); set_task_cpu(idle, cpu); spin_lock_irqsave(&rq->lock, flags); @@ -4074,13 +4070,15 @@ * task must not exit() & deallocate itself prematurely. The * call is not atomic; no spinlocks may be held. */ -int set_cpus_allowed(task_t *p, cpumask_t new_mask) +static int set_cpus_allowed(task_t *p, cpumask_t new_mask) { unsigned long flags; int ret = 0; migration_req_t req; runqueue_t *rq; + perfctr_set_cpus_allowed(p, new_mask); + rq = task_rq_lock(p, &flags); if (!cpus_intersects(new_mask, cpu_online_map)) { ret = -EINVAL; @@ -4105,8 +4103,6 @@ return ret; } -EXPORT_SYMBOL_GPL(set_cpus_allowed); - /* * Move (not current) task off this cpu, onto dest cpu. We're doing * this because either it can't run here any more (set_cpus_allowed() @@ -4915,7 +4911,7 @@ && addr < (unsigned long)__sched_text_end); } -void __init sched_init(void) +static void o1_sched_init(void) { runqueue_t *rq; int i, j, k; @@ -5017,3 +5013,69 @@ } #endif /* CONFIG_MAGIC_SYSRQ */ + +struct scheduler o1_scheduler = { + .list = LIST_HEAD_INIT(o1_scheduler.list), + .name = "host_o1_scheduler", + .container = &init_task, + .is_guest = 0, + .inode = 0, + .wakeup = COMPLETION_INITIALIZER(o1_scheduler.wakeup), + .lock = SPIN_LOCK_UNLOCKED, + .incoming = LIST_HEAD_INIT(o1_scheduler.incoming), + .task_ops = { + .schedule = o1_schedule, + .io_schedule = o1_io_schedule, + .io_schedule_timeout = o1_io_schedule_timeout, +#ifdef CONFIG_SMP + .wait_task_inactive = o1_wait_task_inactive, +#endif + .wake_up_new_task = o1_wake_up_new_task, + .sched_exit = o1_sched_exit, + .schedule_tail = o1_schedule_tail, + .set_user_nice = o1_set_user_nice, + .sched_setscheduler = o1_sched_setscheduler, +#ifdef CONFIG_SMP + .set_cpus_allowed = o1_set_cpus_allowed, +#endif + .sched_yield = o1_sched_yield, + .nr_running = o1_nr_running, + .nr_uninterruptible = o1_nr_uninterruptible, + .nr_context_switches = o1_nr_context_switches, + .nr_iowait = o1_nr_iowait, + .current_sched_time = o1_current_sched_time, + .account_user_time = o1_account_user_time, + .account_system_time = o1_account_system_time, + .account_steal_time = o1_account_steal_time, + .scheduler_tick = o1_scheduler_tick, + .idle_cpu = o1_idle_cpu, + .idle_task = o1_idle_task, + .task_timeslice = o1_task_timeslice, + .try_to_wake_up = o1_try_to_wake_up, + .sched_init_fn = o1_sched_init, + .task_curr = o1_task_curr, + .init_idle = o1_init_idle, + }, +}; + +static int init_scheduler(void) +{ + char *name = THIS_MODULE ? THIS_MODULE->name : o1_scheduler.name; + int err; + + err = init_sched_instance(&o1_scheduler); + if(err) + goto error; + + err = register_scheduler(&o1_scheduler, name); + if(err) + goto error; + + return 0; + + error: + uninit_sched_instance(&o1_scheduler); + return err; +} + +postcore_initcall(init_scheduler); Index: guest-sched-2.6.11/kernel/sched_group.c =================================================================== --- guest-sched-2.6.11.orig/kernel/sched_group.c 2003-09-15 09:40:47.000000000 -0400 +++ guest-sched-2.6.11/kernel/sched_group.c 2005-04-20 20:58:20.000000000 -0400 @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include + +static LIST_HEAD(schedulers); +static DEFINE_SPINLOCK(schedulers_lock); + +static struct proc_dir_entry *schedulers_entry = NULL; +static struct proc_dir_entry *sched_groups_entry = NULL; + +static int init_schedulers(void) +{ + schedulers_entry = proc_mkdir("schedulers", NULL); + sched_groups_entry = proc_mkdir("sched-groups", NULL); + return 0; +} + +core_initcall(init_schedulers); + +static int scheduler_open(struct inode *inode, struct file *file) +{ + struct scheduler *s, *found = NULL; + struct list_head *entry; + int err = -ENOENT; + + spin_lock(&schedulers_lock); + list_for_each(entry, &schedulers){ + s = list_entry(entry, struct scheduler, list); + if(s->inode == inode->i_ino){ + found = s; + break; + } + } + spin_unlock(&schedulers_lock); + + if(found == NULL) + goto out; + + err = -EPERM; + if(!found->is_guest) + goto out; + + found->task_ops.sched_init_fn(); + + out: + return -EINVAL; +} + +static struct file_operations scheduler_file_ops = { + .open = scheduler_open, +}; + +int register_scheduler(struct scheduler *scheduler, char *name) +{ + struct proc_dir_entry *entry; + int err = -ENOENT; + + if(schedulers_entry == NULL) + goto out_none; + + spin_lock(&schedulers_lock); + list_add(&scheduler->list, &schedulers); + + entry = create_proc_entry(name, 0444, schedulers_entry); + if(entry == NULL) + goto out_del; + + entry->proc_fops = &scheduler_file_ops; + scheduler->inode = entry->low_ino; + + printk("Registering scheduler '%s'\n", scheduler->name); + err = 0; + + out: + spin_unlock(&schedulers_lock); + out_none: + return err; + + out_del: + list_del(&scheduler->list); + goto out; +} + +EXPORT_SYMBOL(register_scheduler); + +extern int sched_group_readdir(struct file * filp, void * dirent, + filldir_t filldir); + +static struct file_operations sched_group_file_ops = { + .read = generic_read_dir, + .readdir = sched_group_readdir, +}; + +extern struct dentry *sched_group_lookup(struct inode *dir, + struct dentry * dentry, + struct nameidata *nd); + +static struct inode_operations sched_group_inode_ops = { + .lookup = sched_group_lookup, +}; + +int register_sched_group(int pid, struct scheduler *scheduler) +{ + struct proc_dir_entry *entry; + char name[sizeof("12345\0")]; + int err = -ENOENT; + + if(sched_groups_entry == NULL) + goto out; + + sprintf(name, "%d", pid); + entry = proc_mkdir(name, sched_groups_entry); + if(entry == NULL) + goto out; + + entry->data = scheduler; + entry->proc_fops = &sched_group_file_ops; + entry->proc_iops = &sched_group_inode_ops; + + err = 0; + printk("Created sched_group %d ('%s')\n", pid, scheduler->name); + out: + return err; +} + +EXPORT_SYMBOL(register_sched_group); + +int task_sched_pid(struct task_struct *task) +{ + return(task->scheduler->container->pid); +} + +int sched_pid(void *scheduler) +{ + return(((struct scheduler *) scheduler)->container->pid); +}