2.4-ac task->cpu abstraction and optimization
Subsystems (3)
PATCH 1/1 2.4-ac task->cpu abstraction and optimization
Alan,
Implement "task_cpu()" and "set_task_cpu()" as wrappers for reading and writing task->cpu, respectively.
Additionally, introduce a nice optimization: on UP, task_cpu() can hard-code to "0" and set_task_cpu() can be a no-op.
Patch is against 2.4.20-pre5-ac4, please apply.
Robert Love
Documentation/sched-coding.txt +7 -4
@@ -88,12 +88,13 @@ Returns the runqueue of the specified cpu. this_rq() Returns the runqueue of the current cpu. -task_rq(pid) - Returns the runqueue which holds the specified pid. +task_rq(task) + Returns the runqueue which holds the specified task. cpu_curr(cpu) Returns the task currently running on the given cpu. -rt_task(pid) - Returns true if pid is real-time, false if not. +rt_task(task) + Returns true if task is real-time, false if not. +task_cpu(task) Process Control Methods
@@ -117,6 +118,8 @@ Clears need_resched in the given task. void set_need_resched() Sets need_resched in the current task. +void set_task_cpu(task, cpu) + Sets task->cpu to cpu on SMP. Noop on UP. void clear_need_resched() Clears need_resched in the current task. int need_resched()
fs/proc/array.c +1 -1
@@ -389,7 +389,7 @@ task->nswap, task->cnswap, task->exit_signal, - task->cpu); + task_cpu(task));if (mm)mmput (mm);return res;
include/linux/sched.h +28 -0
@@ -976,6 +976,34 @@return unlikely (current->need_resched); } +/* +* Wrappers for p->cpu access. No-op on UP. +*/ +#ifdef CONFIG_SMP + +static inline unsigned int task_cpu (struct task_struct *p) +{ +return p->cpu; +} + +static inline void set_task_cpu (struct task_struct *p,unsigned int cpu) +{ + p->cpu = cpu; +} + +#else + +static inline unsigned int task_cpu (struct task_struct *p) +{ +return 0 ; +} + +static inline void set_task_cpu (struct task_struct *p,unsigned int cpu) +{ +} + +#endif /* CONFIG_SMP */ +#endif /* __KERNEL__ */ #endif
kernel/sched.c +14 -14
@@ -148,7 +148,7 @@#define cpu_rq (cpu) (runqueues + (cpu))#define this_rq () cpu_rq(smp_processor_id()) -#define task_rq (p) cpu_rq((p)->cpu) +#define task_rq (p) cpu_rq(task_cpu(p))#define cpu_curr (cpu) (cpu_rq(cpu)->curr)#define rt_task (p) ((p)->prio < MAX_RT_PRIO)
@@ -311,8 +311,8 @@ need_resched = p->need_resched;wmb ();set_tsk_need_resched (p); -if (!need_resched && (p->cpu !=smp_processor_id ())) -smp_send_reschedule (p->cpu); +if (!need_resched && (task_cpu (p) !=smp_processor_id ())) +smp_send_reschedule (task_cpu (p));#else set_tsk_need_resched (p);#endif
@@ -391,10 +391,10 @@* currently. Do not violate hard affinity. */ if (unlikely (sync && (rq->curr != p) && - (p->cpu !=smp_processor_id ()) && + (task_cpu (p) !=smp_processor_id ()) && (p->cpus_allowed & (1UL <<smp_processor_id ())))) { - p->cpu =smp_processor_id (); +set_task_cpu (p,smp_processor_id ());task_rq_unlock (rq, &flags); goto repeat_lock_task; }
@@ -437,7 +437,7 @@ p->sleep_avg = p->sleep_avg *CHILD_PENALTY /100 ; p->prio =effective_prio (p); } - p->cpu =smp_processor_id (); +set_task_cpu (p,smp_processor_id ());activate_task (p, rq);rq_unlock (rq);
@@ -727,7 +727,7 @@*/ dequeue_task (next, array); busiest->nr_running--; - next->cpu = this_cpu; +set_task_cpu (next, this_cpu); this_rq->nr_running++;enqueue_task (next, this_rq->active);if (next->prio < current->prio)
@@ -1718,7 +1718,7 @@void __init init_idle (task_t *idle,int cpu) { -runqueue_t *idle_rq =cpu_rq (cpu), *rq =cpu_rq (idle->cpu); +runqueue_t *idle_rq =cpu_rq (cpu), *rq =cpu_rq (task_cpu (idle));unsigned long flags;__save_flags (flags);
@@ -1730,7 +1730,7 @@ idle->array =NULL ; idle->prio =MAX_PRIO ; idle->state =TASK_RUNNING ; - idle->cpu = cpu; +set_task_cpu (idle, cpu);double_rq_unlock (idle_rq, rq);set_tsk_need_resched (idle);__restore_flags (flags);
@@ -1835,7 +1835,7 @@* Can the task run on the task's current CPU? If not then * migrate the process off to a proper CPU. */ -if (new_mask & (1UL << p->cpu)) { +if (new_mask & (1UL <<task_cpu (p))) {task_rq_unlock (rq, &flags); goto out; }
@@ -1844,7 +1844,7 @@* it is sufficient to simply update the task's cpu field. */ if (!p->array && (p != rq->curr)) { - p->cpu =__ffs (p->cpus_allowed); +set_task_cpu (p,__ffs (p->cpus_allowed));task_rq_unlock (rq, &flags); goto out; }
@@ -1914,18 +1914,18 @@ cpu_dest =__ffs (p->cpus_allowed); rq_dest =cpu_rq (cpu_dest); repeat: - cpu_src = p->cpu; + cpu_src =task_cpu (p); rq_src =cpu_rq (cpu_src);local_irq_save (flags);double_rq_lock (rq_src, rq_dest); -if (p->cpu != cpu_src) { +if (task_cpu (p) != cpu_src) {double_rq_unlock (rq_src, rq_dest);local_irq_restore (flags); goto repeat; }if (rq_src == rq) { - p->cpu = cpu_dest; +set_task_cpu (p, cpu_dest);if (p->array) {deactivate_task (p, rq_src);activate_task (p, rq_dest);
Quoted 9 lines · Robert Love
Alan,
Implement "
task_cpu()" and "set_task_cpu()" as wrappers for reading and writingtask->cpu, respectively.Additionally, introduce a nice optimization: on UP,
task_cpu()can hard-code to "0" andset_task_cpu()can be a no-op.Patch is against 2.4.20-pre5-ac4, please apply.
This is fairly similar to the "up-opt" patch I have been using for my 2.4 standard (not -ac) kernels since last winter, available as
<http://www.csd.uu.se/~mikpe/linux/patches/2.4/patch-up-opt-2.4.20-pre6>.
It's not a direct substitute for yours, since -ac changes kernel/sched.c quite a bit, and it has some unnecessary patches to SMP code, but other than that, I totally agree with the intention of your patch.
/Mikael
Quoted 6 lines · Mikael Pettersson
This is fairly similar to the "up-opt" patch I have been using for my 2.4 standard (not -ac) kernels since last winter, available as
<http://www.csd.uu.se/~mikpe/linux/patches/2.4/patch-up-opt-2.4.20-pre6>.
It's not a direct substitute for yours, since -ac changeskernel/sched.cquite a bit, and it has some unnecessary patches to SMP code, but other than that, I totally agree with the intention of your patch.
Good ;)
I should of added this is from 2.5; so it has been around for awhile. I also took a look at your patch -- looks good, you should submit it to Marcelo... it cannot hurt for 2.4.
One thing:
- int processor;
+#ifdef CONFIG_SMP
+ int processor; /* keep old name to avoid upsetting all archs */
+#endifIt is normally bad form to have conditionally entries in the task_struct... otherwise, looks good.
Robert Love
Quoted 9 lines · Robert Love
Quoted 6 lines · Mikael Pettersson
This is fairly similar to the "up-opt" patch I have been using for my 2.4 standard (not -ac) kernels since last winter, available as
<http://www.csd.uu.se/~mikpe/linux/patches/2.4/patch-up-opt-2.4.20-pre6>.
It's not a direct substitute for yours, since -ac changeskernel/sched.cquite a bit, and it has some unnecessary patches to SMP code, but other than that, I totally agree with the intention of your patch.
Quoted 3 lines
Good ;)
I should of added this is from 2.5; so it has been around for awhile. I
Actually, the 2.5 patch sort of originates from my 2.4 patch: I did a 2.5 version, Dave Jones included it in the -dj kernel, and Ingo pulled it out and pushed it into Linus' kernel.
Quoted 2 lines
also took a look at your patch -- looks good, you should submit it to Marcelo... it cannot hurt for 2.4.
I might do that, unless Alan plans on pushing the -ac sched.c stuff to Marcelo, in which case my patch would just confuse things. Alan?
Quoted 7 lines
- int processor; +#ifdef CONFIG_SMP + int processor; /* keep old name to avoid upsetting all archs */ +#endifIt is normally bad form to have conditionally entries in the
task_struct... otherwise, looks good.
I did that mainly to help catch unconverted references to ->processor. It's easy enough to clean out.
/Mikael
Quoted 5 lines
Quoted 2 lines
also took a look at your patch -- looks good, you should submit it to Marcelo... it cannot hurt for 2.4.
I might do that, unless Alan plans on pushing the -ac
sched.cstuff to Marcelo, in which case my patch would just confuse things. Alan?
I'd like to see it in 2.4 base. Its really Marcelo's call.