diff -urNp x-ref/kernel/fork.c xx/kernel/fork.c --- x-ref/kernel/fork.c Thu Oct 10 06:06:34 2002 +++ xx/kernel/fork.c Thu Oct 10 06:06:38 2002 @@ -690,8 +690,6 @@ int do_fork(unsigned long clone_flags, u if (p->pid < 0) /* valid pids are >= 0 */ goto bad_fork_cleanup; - INIT_LIST_HEAD(&p->run_list); - p->p_cptr = NULL; init_waitqueue_head(&p->wait_chldexit); p->vfork_done = NULL; @@ -725,7 +723,6 @@ int do_fork(unsigned long clone_flags, u spin_lock_init(&p->sigmask_lock); } #endif - p->array = NULL; p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; diff -urNp x-ref/kernel/sched.c xx/kernel/sched.c --- x-ref/kernel/sched.c Thu Oct 10 06:06:37 2002 +++ xx/kernel/sched.c Thu Oct 10 06:06:46 2002 @@ -54,9 +54,8 @@ */ #define MIN_TIMESLICE ( 10 * HZ / 1000) #define MAX_TIMESLICE (300 * HZ / 1000) -#define CHILD_PENALTY 95 +#define CHILD_PENALTY 50 #define PARENT_PENALTY 100 -#define EXIT_WEIGHT 3 #define PRIO_BONUS_RATIO 25 #define INTERACTIVE_DELTA 2 #define MAX_SLEEP_AVG (2*HZ) @@ -119,7 +118,7 @@ runqueue_t runqueues[NR_CPUS] __cachelin */ #ifndef prepare_arch_switch # define prepare_arch_switch(rq, next) do { } while(0) -# define finish_arch_switch(rq, next) spin_unlock_irq(&(rq)->lock) +# define finish_arch_switch(rq, prev) spin_unlock_irq(&(rq)->lock) #endif /* @@ -157,12 +156,18 @@ static inline void dequeue_task(struct t __clear_bit(p->prio, array->bitmap); } -static inline void enqueue_task(struct task_struct *p, prio_array_t *array) +#define enqueue_task(p, array) __enqueue_task(p, array, NULL) +static inline void __enqueue_task(struct task_struct *p, prio_array_t *array, task_t * parent) { - list_add_tail(&p->run_list, array->queue + p->prio); - __set_bit(p->prio, array->bitmap); + if (!parent) { + list_add_tail(&p->run_list, array->queue + p->prio); + __set_bit(p->prio, array->bitmap); + p->array = array; + } else { + list_add_tail(&p->run_list, &parent->run_list); + array = p->array = parent->array; + } array->nr_active++; - p->array = array; } static inline int effective_prio(task_t *p) @@ -191,12 +196,13 @@ static inline int effective_prio(task_t return prio; } -static inline void activate_task(task_t *p, runqueue_t *rq) +#define activate_task(p, rq) __activate_task(p, rq, NULL) +static inline void __activate_task(task_t *p, runqueue_t *rq, task_t * parent) { unsigned long sleep_time = jiffies - p->sleep_timestamp; prio_array_t *array = rq->active; - if (!rt_task(p) && sleep_time) { + if (!parent && !rt_task(p) && sleep_time) { /* * This code gives a bonus to interactive tasks. We update * an 'average sleep time' value here, based on @@ -204,12 +210,13 @@ static inline void activate_task(task_t * the higher the average gets - and the higher the priority * boost gets as well. */ + p->sleep_timestamp = jiffies; p->sleep_avg += sleep_time; if (p->sleep_avg > MAX_SLEEP_AVG) p->sleep_avg = MAX_SLEEP_AVG; p->prio = effective_prio(p); } - enqueue_task(p, array); + __enqueue_task(p, array, parent); rq->nr_running++; } @@ -328,23 +335,47 @@ int wake_up_process(task_t * p) void wake_up_forked_process(task_t * p) { runqueue_t *rq; + task_t * parent = current; rq = this_rq(); spin_lock_irq(&rq->lock); p->state = TASK_RUNNING; - if (!rt_task(p)) { + if (likely(!rt_task(p) && parent->array)) { /* - * We decrease the sleep average of forking parents - * and children as well, to keep max-interactive tasks + * We decrease the sleep average of forked + * children, to keep max-interactive tasks * from forking tasks that are max-interactive. + * CHILD_PENALTY is set to 50% since we have + * no clue if this is still an interactive + * task like the parent or if this will be a + * cpu bound task. The parent isn't touched + * as we don't make assumption about the parent + * changing behaviour after the child is forked. */ - current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100; + parent->sleep_avg = parent->sleep_avg * PARENT_PENALTY / 100; p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100; + + /* + * For its first schedule keep the child at the same + * priority (i.e. in the same list) of the parent, + * activate_forked_task() will take care to put the + * child in front of the parent (lifo) to guarantee a + * schedule-child-first behaviour after fork. + */ + p->prio = parent->prio; + } else { + /* + * Take the usual wakeup path if it's RT or if + * it's a child of the first idle task (during boot + * only). + */ p->prio = effective_prio(p); + parent = NULL; } + p->cpu = smp_processor_id(); - activate_task(p, rq); + __activate_task(p, rq, parent); spin_unlock_irq(&rq->lock); } @@ -366,13 +397,6 @@ void sched_exit(task_t * p) current->time_slice = MAX_TIMESLICE; } __sti(); - /* - * If the child was a (relative-) CPU hog then decrease - * the sleep_avg of the parent as well. - */ - if (p->sleep_avg < current->sleep_avg) - current->sleep_avg = (current->sleep_avg * EXIT_WEIGHT + - p->sleep_avg) / (EXIT_WEIGHT + 1); } #if CONFIG_SMP @@ -1027,7 +1051,7 @@ void set_user_nice(task_t *p, long nice) * If the task is running and lowered its priority, * or increased its priority then reschedule its CPU: */ - if ((NICE_TO_PRIO(nice) < p->static_prio) || (p == rq->curr)) + if (p == rq->curr) resched_task(rq->curr); } out_unlock: