diff -NurbP --minimal linux-2.4.21-rc7/Makefile linux-2.4.21-rc7-v0.05/Makefile --- linux-2.4.21-rc7/Makefile Wed Jun 4 08:00:24 2003 +++ linux-2.4.21-rc7-v0.05/Makefile Tue Jun 10 00:36:54 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc7-v0.05 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -NurbP --minimal linux-2.4.21-rc7/arch/i386/kernel/entry.S linux-2.4.21-rc7-v0.05/arch/i386/kernel/entry.S --- linux-2.4.21-rc7/arch/i386/kernel/entry.S Wed Jun 4 08:00:27 2003 +++ linux-2.4.21-rc7-v0.05/arch/i386/kernel/entry.S Tue Jun 10 00:36:54 2003 @@ -663,6 +663,8 @@ .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_wait */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_remap_file_pages */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_tid_address */ + .long SYMBOL_NAME(sys_create_virtual) + .long SYMBOL_NAME(sys_migrate) /* 260 */ .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) diff -NurbP --minimal linux-2.4.21-rc7/arch/i386/kernel/init_task.c linux-2.4.21-rc7-v0.05/arch/i386/kernel/init_task.c --- linux-2.4.21-rc7/arch/i386/kernel/init_task.c Tue Sep 18 00:29:09 2001 +++ linux-2.4.21-rc7-v0.05/arch/i386/kernel/init_task.c Tue Jun 10 00:36:54 2003 @@ -10,6 +10,7 @@ static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM(init_mm); +struct virtual_struct init_virtual = INIT_VIRTUAL(init_virtual); /* * Initial task structure. diff -NurbP --minimal linux-2.4.21-rc7/fs/proc/array.c linux-2.4.21-rc7-v0.05/fs/proc/array.c --- linux-2.4.21-rc7/fs/proc/array.c Wed Jun 4 08:01:16 2003 +++ linux-2.4.21-rc7-v0.05/fs/proc/array.c Tue Jun 10 00:36:54 2003 @@ -272,6 +272,11 @@ cap_t(p->cap_effective)); } +static inline char *task_virtual(struct task_struct *p, char *buffer) +{ + return proc_virtual_info(p->virt, buffer); +} + int proc_pid_status(struct task_struct *task, char * buffer) { @@ -291,6 +296,7 @@ } buffer = task_sig(task, buffer); buffer = task_cap(task, buffer); + buffer = task_virtual(task, buffer); #if defined(CONFIG_ARCH_S390) buffer = task_show_regs(task, buffer); #endif diff -NurbP --minimal linux-2.4.21-rc7/fs/proc/proc_misc.c linux-2.4.21-rc7-v0.05/fs/proc/proc_misc.c --- linux-2.4.21-rc7/fs/proc/proc_misc.c Wed Jun 4 08:01:16 2003 +++ linux-2.4.21-rc7-v0.05/fs/proc/proc_misc.c Tue Jun 10 00:36:54 2003 @@ -305,7 +305,6 @@ int count, int *eof, void *data) { int i, len = 0; - extern unsigned long total_forks; unsigned long jif = jiffies; unsigned int sum = 0, user = 0, nice = 0, system = 0; int major, disk; diff -NurbP --minimal linux-2.4.21-rc7/fs/proc/root.c linux-2.4.21-rc7-v0.05/fs/proc/root.c --- linux-2.4.21-rc7/fs/proc/root.c Tue Dec 10 03:19:58 2002 +++ linux-2.4.21-rc7-v0.05/fs/proc/root.c Tue Jun 10 00:36:54 2003 @@ -68,6 +68,7 @@ proc_rtas_init(); #endif proc_bus = proc_mkdir("bus", 0); + proc_virtual = proc_mkdir("virtual", 0); } static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry) @@ -144,4 +145,5 @@ EXPORT_SYMBOL(proc_root_fs); EXPORT_SYMBOL(proc_net); EXPORT_SYMBOL(proc_bus); +EXPORT_SYMBOL(proc_virtual); EXPORT_SYMBOL(proc_root_driver); diff -NurbP --minimal linux-2.4.21-rc7/include/asm-i386/processor.h linux-2.4.21-rc7-v0.05/include/asm-i386/processor.h --- linux-2.4.21-rc7/include/asm-i386/processor.h Sun Jun 8 15:05:35 2003 +++ linux-2.4.21-rc7-v0.05/include/asm-i386/processor.h Tue Jun 10 00:40:09 2003 @@ -458,7 +458,7 @@ #define free_task_struct(p) free_pages((unsigned long) (p), 1) #define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) -#define init_task (init_task_union.task) +#define master_init_task (init_task_union.task) #define init_stack (init_task_union.stack) struct microcode { diff -NurbP --minimal linux-2.4.21-rc7/include/asm-i386/unistd.h linux-2.4.21-rc7-v0.05/include/asm-i386/unistd.h --- linux-2.4.21-rc7/include/asm-i386/unistd.h Tue Dec 10 03:25:25 2002 +++ linux-2.4.21-rc7-v0.05/include/asm-i386/unistd.h Tue Jun 10 00:36:54 2003 @@ -258,6 +258,9 @@ #define __NR_free_hugepages 251 #define __NR_exit_group 252 +#define __NR_create_virtual 259 +#define __NR_migrate 260 + /* user-visible error numbers are in the range -1 - -124: see */ #define __syscall_return(type, res) \ diff -NurbP --minimal linux-2.4.21-rc7/include/linux/sched.h linux-2.4.21-rc7-v0.05/include/linux/sched.h --- linux-2.4.21-rc7/include/linux/sched.h Wed Jun 4 08:01:29 2003 +++ linux-2.4.21-rc7-v0.05/include/linux/sched.h Tue Jun 10 00:40:09 2003 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include struct exec_domain; @@ -73,8 +75,6 @@ #define CT_TO_SECS(x) ((x) / HZ) #define CT_TO_USECS(x) (((x) % HZ) * 1000000/HZ) -extern int nr_running, nr_threads; -extern int last_pid; #include #include @@ -415,6 +415,7 @@ /* journalling filesystem info */ void *journal_info; + struct virtual_struct *virt; }; /* @@ -509,6 +510,7 @@ blocked: {{0}}, \ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ + virt: &init_virtual, \ } @@ -526,9 +528,6 @@ extern struct mm_struct init_mm; extern struct task_struct *init_tasks[NR_CPUS]; -/* PID hashing. (shouldnt this be dynamic?) */ -#define PIDHASH_SZ (4096 >> 2) -extern struct task_struct *pidhash[PIDHASH_SZ]; #define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) @@ -891,7 +890,7 @@ static inline void del_from_runqueue(struct task_struct * p) { - nr_running--; + virtual_nr_running(p)--; p->sleep_time = jiffies; list_del(&p->run_list); p->run_list.next = NULL; @@ -907,7 +906,7 @@ if (task_on_runqueue(p)) out_of_line_bug(); write_lock_irq(&tasklist_lock); - nr_threads--; + virtual(p,nr_threads)--; unhash_pid(p); REMOVE_LINKS(p); list_del(&p->thread_group); diff -NurbP --minimal linux-2.4.21-rc7/include/linux/virtual.h linux-2.4.21-rc7-v0.05/include/linux/virtual.h --- linux-2.4.21-rc7/include/linux/virtual.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.21-rc7-v0.05/include/linux/virtual.h Tue Jun 10 00:36:54 2003 @@ -0,0 +1,111 @@ +#ifndef _LINUX_VIRTUAL_H +#define _LINUX_VIRTUAL_H + +/* PID hashing. (shouldnt this be dynamic?) */ +#define PIDHASH_SZ (4096 >> 2) + + +struct virtual_struct { + + int virt_id; + struct virtual_struct *next_virtual, *prev_virtual; + + struct task_struct *virt_init_task; + struct task_struct *virt_child_reaper; + + int virt_nr_threads; + int virt_nr_running; + int virt_max_threads; + int virt_last_pid; + + unsigned long virt_total_forks; + + struct task_struct *virt_pidhash[PIDHASH_SZ]; + struct proc_dir_entry *procent; +}; + +extern struct virtual_struct init_virtual; + +extern struct proc_dir_entry *proc_virtual; + +extern void release_virtual(struct virtual_struct *); + +struct virtual_setup { + int flags; +}; + + +#define INIT_VIRTUAL(virt) \ +{ \ + virt_id: 0, \ + next_virtual: &virt, \ + prev_virtual: &virt, \ + virt_init_task: &master_init_task, \ + virt_child_reaper: NULL, \ + virt_nr_threads: 0, \ + virt_nr_running: 0, \ + virt_max_threads: 0, \ + virt_last_pid: 0, \ + virt_total_forks: 0, \ + procent: NULL, \ +} + +static inline char *proc_virtual_info(struct virtual_struct *p, char *buffer) +{ + return buffer + sprintf(buffer, "virt_id:\t%d\n" + "init_task:\t%016lx\n" + "nr_threads:\t%d\n" + "nr_running:\t%d\n" + "total_forks:\t%ld\n" + "max_threads:\t%d\n" + "last_pid:\t%d\n", + p->virt_id, + (unsigned long)p->virt_init_task, + p->virt_nr_threads, + p->virt_nr_running, + p->virt_total_forks, + p->virt_max_threads, + p->virt_last_pid); +} + + +#define virtual(p,e) ((p)->virt->virt_ ## e) + + +#define virtual_nr_threads(p) virtual(p,nr_threads) +#define virtual_nr_running(p) virtual(p,nr_running) + +#define virtual_max_threads(p) virtual(p,max_threads) +#define virtual_last_pid(p) virtual(p,last_pid) + +#define virtual_total_forks(p) virtual(p,total_forks) +#define virtual_pidhash(p) virtual(p,pidhash) + +#define virtual_init_task(p) (*virtual(p,init_task)) +#define virtual_child_reaper(p) virtual(p,child_reaper) + + +#define nr_threads virtual_nr_threads(current) +#define nr_running virtual_nr_running(current) + +#define max_threads virtual_max_threads(current) +#define last_pid virtual_last_pid(current) + +#define total_forks virtual_total_forks(current) +#define pidhash virtual_pidhash(current) + +#define init_task virtual_init_task(current) +#define child_reaper virtual_child_reaper(current) + + +/* walk each struct_virtual except the first (physical) */ +#define for_each_virtual(v) \ + for (v = &init_virtual ; (v = v->next_virtual) != &init_virtual ; ) + +/* walk each virtual struct_task except the first (idle) */ +#define for_each_virtual_task(v,p) \ + for (p = ((v)->virt_init_task) ; \ + (p = p->next_task) != ((v)->virt_init_task) ; ) + + +#endif /* _LINUX_VIRTUAL_H */ diff -NurbP --minimal linux-2.4.21-rc7/init/main.c linux-2.4.21-rc7-v0.05/init/main.c --- linux-2.4.21-rc7/init/main.c Tue Dec 10 03:20:19 2002 +++ linux-2.4.21-rc7-v0.05/init/main.c Tue Jun 10 00:36:54 2003 @@ -435,7 +435,6 @@ rest_init(); } -struct task_struct *child_reaper = &init_task; static void __init do_initcalls(void) { diff -NurbP --minimal linux-2.4.21-rc7/kernel/Makefile linux-2.4.21-rc7-v0.05/kernel/Makefile --- linux-2.4.21-rc7/kernel/Makefile Mon Sep 17 06:22:40 2001 +++ linux-2.4.21-rc7-v0.05/kernel/Makefile Tue Jun 10 00:36:54 2003 @@ -14,7 +14,7 @@ obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ sysctl.o acct.o capability.o ptrace.o timer.o user.o \ - signal.o sys.o kmod.o context.o + signal.o sys.o kmod.o context.o virtual.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o diff -NurbP --minimal linux-2.4.21-rc7/kernel/exit.c linux-2.4.21-rc7-v0.05/kernel/exit.c --- linux-2.4.21-rc7/kernel/exit.c Tue Dec 10 03:25:38 2002 +++ linux-2.4.21-rc7-v0.05/kernel/exit.c Tue Jun 10 00:36:54 2003 @@ -22,7 +22,6 @@ #include extern void sem_exit (void); -extern struct task_struct *child_reaper; int getrusage(struct task_struct *, int, struct rusage *); @@ -66,6 +65,9 @@ current->counter += p->counter; if (current->counter >= MAX_COUNTER) current->counter = MAX_COUNTER; + if (p->pid == 1) + release_virtual(p->virt); + p->pid = 0; free_task_struct(p); } else { @@ -430,8 +432,14 @@ panic("Aiee, killing interrupt handler!"); if (!tsk->pid) panic("Attempted to kill the idle task!"); - if (tsk->pid == 1) + if (tsk->pid == 1) { + if (tsk->virt->virt_id == 0) panic("Attempted to kill init!"); +virtual_keep_alive: + sys_wait4(-1, NULL, __WALL, NULL); + if (current->next_task != &init_task) + goto virtual_keep_alive; + } tsk->flags |= PF_EXITING; del_timer_sync(&tsk->real_timer); diff -NurbP --minimal linux-2.4.21-rc7/kernel/fork.c linux-2.4.21-rc7-v0.05/kernel/fork.c --- linux-2.4.21-rc7/kernel/fork.c Wed Jun 4 08:01:30 2003 +++ linux-2.4.21-rc7-v0.05/kernel/fork.c Tue Jun 10 00:36:54 2003 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -29,15 +30,7 @@ #include #include -/* The idle threads do not count.. */ -int nr_threads; -int nr_running; - -int max_threads; -unsigned long total_forks; /* Handle normal Linux uptimes. */ -int last_pid; - -struct task_struct *pidhash[PIDHASH_SZ]; +int master_max_threads; void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait) { @@ -75,6 +68,7 @@ * value: the thread structures can take up at most half * of memory. */ + master_max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8; max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 8; init_task.rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; @@ -83,8 +77,9 @@ /* Protects next_safe and last_pid. */ spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED; +/* FIXME: should be per virtual ^^^^ */ -static int get_pid(unsigned long flags) +int get_pid(unsigned long flags) { static int next_safe = PID_MAX; struct task_struct *p; diff -NurbP --minimal linux-2.4.21-rc7/kernel/kmod.c linux-2.4.21-rc7-v0.05/kernel/kmod.c --- linux-2.4.21-rc7/kernel/kmod.c Tue Dec 10 03:20:19 2002 +++ linux-2.4.21-rc7-v0.05/kernel/kmod.c Tue Jun 10 00:36:54 2003 @@ -30,8 +30,6 @@ #include -extern int max_threads; - static inline void use_init_fs_context(void) { diff -NurbP --minimal linux-2.4.21-rc7/kernel/sched.c linux-2.4.21-rc7-v0.05/kernel/sched.c --- linux-2.4.21-rc7/kernel/sched.c Wed Jun 4 08:01:30 2003 +++ linux-2.4.21-rc7-v0.05/kernel/sched.c Tue Jun 10 00:36:54 2003 @@ -76,7 +76,7 @@ * via the SMP irq return path. */ -struct task_struct * init_tasks[NR_CPUS] = {&init_task, }; +struct task_struct * init_tasks[NR_CPUS] = {&master_init_task, }; /* * The tasklist_lock protects the linked list of processes. @@ -104,13 +104,12 @@ cycles_t last_schedule; } schedule_data; char __pad [SMP_CACHE_BYTES]; -} aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}}; +} aligned_data [NR_CPUS] __cacheline_aligned = { {{&master_init_task,0}}}; #define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr #define last_schedule(cpu) aligned_data[(cpu)].schedule_data.last_schedule struct kernel_stat kstat; -extern struct task_struct *child_reaper; #ifdef CONFIG_SMP @@ -120,7 +119,7 @@ #else -#define idle_task(cpu) (&init_task) +#define idle_task(cpu) (&master_init_task) #define can_schedule(p,cpu) (1) #endif @@ -329,7 +328,12 @@ static inline void add_to_runqueue(struct task_struct * p) { list_add_tail(&p->run_list, &runqueue_head); - nr_running++; + virtual_nr_running(p)++; +} + +void add_current_to_runqueue(void) +{ + add_to_runqueue(current); } static inline void move_last_runqueue(struct task_struct * p) @@ -615,11 +619,16 @@ /* Do we need to re-calculate counters? */ if (unlikely(!c)) { struct task_struct *p; + struct virtual_struct *v = &init_virtual; spin_unlock_irq(&runqueue_lock); read_lock(&tasklist_lock); - for_each_task(p) + for_each_virtual_task(v,p) p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); + for_each_virtual(v) + for_each_virtual_task(v,p) + p->counter = (p->counter >> 1) + NICE_TO_TICKS(p->nice); + read_unlock(&tasklist_lock); spin_lock_irq(&runqueue_lock); goto repeat_schedule; diff -NurbP --minimal linux-2.4.21-rc7/kernel/sysctl.c linux-2.4.21-rc7-v0.05/kernel/sysctl.c --- linux-2.4.21-rc7/kernel/sysctl.c Wed Jun 4 08:01:30 2003 +++ linux-2.4.21-rc7-v0.05/kernel/sysctl.c Tue Jun 10 00:36:54 2003 @@ -44,7 +44,7 @@ extern int C_A_D; extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern int sysctl_overcommit_memory; -extern int max_threads; +extern int master_max_threads; extern atomic_t nr_queued_signals; extern int max_queued_signals; extern int sysrq_enabled; @@ -242,7 +242,7 @@ #endif {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int), 0600, NULL, &proc_dointvec}, - {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int), + {KERN_MAX_THREADS, "threads-max", &master_max_threads, sizeof(int), 0644, NULL, &proc_dointvec}, {KERN_RANDOM, "random", NULL, 0, 0555, random_table}, {KERN_OVERFLOWUID, "overflowuid", &overflowuid, sizeof(int), 0644, NULL, diff -NurbP --minimal linux-2.4.21-rc7/kernel/virtual.c linux-2.4.21-rc7-v0.05/kernel/virtual.c --- linux-2.4.21-rc7/kernel/virtual.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.21-rc7-v0.05/kernel/virtual.c Tue Jun 10 00:38:29 2003 @@ -0,0 +1,229 @@ +/* + * linux/kernel/virtual.c + * + * Virtual Server Task Context + * + * Copyright (C) 2003 Herbert Pötzl + * + * V0.01 create_virtual (syscall), init_virtual + * V0.02 procfs: /virtual/?_info + * V0.03 migrate (syscall), further virtualization + * V0.04 real/virtual scheduler (fix) + * V0.05 task/memory limits (fix) + * + */ + + +#include +#include +#include +#include + + + + + + /* procfs stuff ... */ + +struct proc_dir_entry *proc_virtual; + +int virtual_read_func (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len; + char *buffer = page; + + buffer = proc_virtual_info(data, buffer); + + len = buffer-page; + if (len <= off+count) *eof = 1; + + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +int virtual_proc_info_create(struct virtual_struct *virt) +{ + struct proc_dir_entry *entry; + char name[32]; + + sprintf(name, "%d_info", virt->virt_id); + entry = create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, + proc_virtual, virtual_read_func, virt); + virt->procent = entry; + return 0; +} + +int virtual_proc_info_destroy(struct virtual_struct *virt) +{ + struct proc_dir_entry *entry = virt->procent; + + if (virt->procent) { + remove_proc_entry(entry->name, proc_virtual); + virt->procent = NULL; + } + return 0; +} + +static int __init virtual_proc_init(void) +{ + virtual_proc_info_create(&init_virtual); + return 0; +} + +__initcall(virtual_proc_init); + + + + + /* helper ... */ + +extern int get_pid(unsigned long); + +extern int master_max_threads; + + +static struct virtual_struct *virtual_by_id(int vid) +{ + struct virtual_struct *virt; + + for_each_virtual(virt) { + if (virt->virt_id == vid) + return virt; + } + return NULL; +} + +void release_virtual(struct virtual_struct *v) +{ + struct task_struct *init; + + init = v->virt_init_task; + if (init != init->next_task) + BUG(); + v->next_virtual->prev_virtual = v->prev_virtual; + v->prev_virtual->next_virtual = v->next_virtual; + v->prev_virtual = v->next_virtual = NULL; + virtual_proc_info_destroy(v); + free_task_struct(init); + kfree(v); + return; +} + + +asmlinkage int +sys_create_virtual(int vid, struct virtual_setup *setup) +{ + int retval = 0; + struct virtual_struct *virt; + + virt = virtual_by_id(vid); + if (virt) + return -EEXIST; + + virt = kmalloc(sizeof(struct virtual_struct), GFP_KERNEL); + if (!virt) + return -ENOMEM; + + memset(virt, 0, sizeof(struct virtual_struct)); + + virt->virt_id = vid; + virt->virt_init_task = alloc_task_struct(); + if (!virt->virt_init_task) + goto bad_create_free; + + virt->virt_max_threads = master_max_threads; + + virt->virt_init_task->rlim[RLIMIT_NPROC].rlim_cur = master_max_threads/2; + virt->virt_init_task->rlim[RLIMIT_NPROC].rlim_max = master_max_threads/2; + + virt->next_virtual = &init_virtual; + virt->prev_virtual = init_virtual.prev_virtual; + init_virtual.prev_virtual->next_virtual = virt; + init_virtual.prev_virtual = virt; + + virt->virt_init_task->next_task = virt->virt_init_task; + virt->virt_init_task->prev_task = virt->virt_init_task; + + virtual_proc_info_create(virt); + +create_out: + return retval; + +bad_create_free: + kfree(virt); + goto create_out; +} + + +extern void add_current_to_runqueue(void); + +asmlinkage int +sys_migrate(int vid) +{ + struct virtual_struct *virt; + + virt = virtual_by_id(vid); + if (!virt) + return -ENOENT; + if (virt == current->virt) + return 0; + + del_from_runqueue(current); + unhash_process(current); /* + - acquires tasklist_lock + - requires process off runqueue + - decrements nr_threads + - unhashes pid (from pidhash) + - removes links (REMOVE_LINK) + - deletes thread_group list + */ + + write_lock_irq(&tasklist_lock); + + current->pid = 0; + current->virt = virt; + + current->pid = get_pid(0); /* CLONE_PID */ + + if (current->pid == 1) + /* new virtual reaper ... */ + child_reaper = current; + else { + current->p_pptr = child_reaper; + current->p_opptr = child_reaper; + } + current->exit_signal = SIGCHLD; + + SET_LINKS(current); + + /* We also take the runqueue_lock while altering task fields + * which affect scheduling decisions */ + spin_lock(&runqueue_lock); + + current->ptrace = 0; + current->nice = DEF_NICE; + current->policy = SCHED_OTHER; + /* cpus_allowed? */ + /* rt_priority? */ + /* signals? */ + current->cap_effective = CAP_INIT_EFF_SET; + current->cap_inheritable = CAP_INIT_INH_SET; + current->cap_permitted = CAP_FULL_SET; + current->keep_capabilities = 0; + memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim))); + current->user = INIT_USER; + + spin_unlock(&runqueue_lock); + INIT_LIST_HEAD(¤t->thread_group); + + hash_pid(current); + nr_threads++; + + write_unlock_irq(&tasklist_lock); + add_current_to_runqueue(); + return 0; +} +