From: William Lee Irwin III <wli@holomorphy.com>

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)

_