From: William Lee Irwin III what the heck? kernel/fork.c | 19 ++++++++++++++++--- 1 files changed, 16 insertions(+), 3 deletions(-) diff -puN kernel/fork.c~reinstate-task-freeing-hack-for-ia64 kernel/fork.c --- 25/kernel/fork.c~reinstate-task-freeing-hack-for-ia64 2003-05-13 18:44:25.000000000 -0700 +++ 25-akpm/kernel/fork.c 2003-05-13 18:44:25.000000000 -0700 @@ -52,6 +52,7 @@ unsigned long total_forks; /* Handle nor DEFINE_PER_CPU(unsigned long, process_counts) = 0; rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */ +static struct task_struct *task_cache[NR_CPUS] __cacheline_aligned; int nr_processes(void) { @@ -68,9 +69,15 @@ int nr_processes(void) #ifdef __HAVE_THREAD_INFO_IN_TASK_STRUCT static inline struct task_struct *dup_task_struct(struct task_struct *orig) { + int cpu = get_cpu(); struct task_struct *tsk; - tsk = (void *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER); + tsk = task_cache[cpu]; + task_cache[cpu] = NULL; + put_cpu(); + + if (!tsk) + tsk = (void *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER); if (likely(tsk != NULL)) { memcpy(tsk, orig, sizeof(*tsk) + sizeof(struct thread_info)); tsk->thread_info = (struct thread_info *)(tsk + 1); @@ -83,7 +90,14 @@ static inline struct task_struct *dup_ta static inline void free_task_struct (struct task_struct *tsk) { - free_pages((unsigned long)tsk, KERNEL_STACK_SIZE_ORDER); + if (tsk == current) { + int cpu = get_cpu(); + tsk = task_cache[cpu]; + task_cache[cpu] = current; + put_cpu(); + } + if (tsk) + free_pages((unsigned long)tsk, KERNEL_STACK_SIZE_ORDER); } #else /* @@ -91,7 +105,6 @@ free_task_struct (struct task_struct *ts * the very last portion of sys_exit() is executed with * preemption turned off. */ -static struct task_struct *task_cache[NR_CPUS] __cacheline_aligned; static kmem_cache_t *task_struct_cachep; struct task_struct *dup_task_struct(struct task_struct *orig) _