2.5: conditional schedules with a preemptive kernel
Subsystems (9)
PATCH 1/1 2.5: conditional schedules with a preemptive kernel
Linus,
With a preemptive kernel, explicit conditional schedules when preempt_count is zero are a waste of cycles and code size. The attached patch, against 2.5.5, implements variants of cond_resched() and need_resched() that optimize away when CONFIG_PREEMPT is set.
This patch also converts some uses of cond_resched() and need_resched() to the new __cond_resched() and __need_resched() methods. These codepaths have been heavily tested and a lock is _never_ held across them. Thus we guarantee the same scheduling semantics.
Robert Love
Documentation/DocBook/kernel-hacking.tmpl +10 -1
@@ -371,7 +371,16 @@ </para> <programlisting> -cond_resched(); /* Will sleep */ +cond_resched(); /* Will sleep */ + </programlisting> + + <para> + or, if you know the lock count is zero (and thus the kernel is + preemptible), don't waste the cycles: + </para> + + <programlisting> +__cond_resched(); /* Is not called if CONFIG_PREEMPT is set */ </programlisting> <para>
drivers/char/random.c +3 -1
@@ -1308,9 +1308,10 @@wake_up_interruptible (&random_write_wait); r->extract_count += nbytes; - + ret =0 ;while (nbytes) { +#ifndef CONFIG_PREEMPT /* * Check if we need to break out or reschedule.... */
@@ -1322,6 +1323,7 @@ }schedule (); } +#endif /* Hash the pool to get the output */ tmp[0 ] =0x67452301 ;
drivers/char/tty_io.c +1 -1
@@ -712,7 +712,7 @@ ret = -ERESTARTSYS ;if (signal_pending (current))break ; -cond_resched (); +__cond_resched (); } }if (written) {
fs/namei.c +1 -1
@@ -342,7 +342,7 @@ goto loop;if (current->total_link_count >=40 ) goto loop; -if (need_resched ()) { +if (__need_resched ()) { current->state =TASK_RUNNING ;schedule (); }
include/linux/sched.h +16 -1
@@ -830,7 +830,22 @@ {return unlikely (test_tsk_thread_flag (p,TIF_SIGPENDING )); } - + +/* +* With a preemptible kernel, explicit conditional schedules +* when preempt_count is zero are a waste of cycles. If you +* know the lock count is zero, use +* __cond_resched() instead of cond_resched() and +* __need_resched() instead of need_resched() +*/ +#ifndef CONFIG_PREEMPT +#define __cond_resched () cond_resched() +#define __need_resched () need_resched() +#else +#define __cond_resched () do { } while(0) +#define __need_resched () 0 +#endif +static inline int need_resched (void ) {return unlikely (test_thread_flag (TIF_NEED_RESCHED ));
kernel/softirq.c +1 -1
@@ -387,7 +387,7 @@while (softirq_pending (cpu)) {do_softirq (); -cond_resched (); +__cond_resched (); }__set_current_state (TASK_INTERRUPTIBLE );
mm/filemap.c +1 -1
@@ -401,7 +401,7 @@ }page_cache_release (page); -if (need_resched ()) { +if (__need_resched ()) {__set_current_state (TASK_RUNNING );schedule (); }
mm/vmscan.c +1 -1
@@ -627,7 +627,7 @@for (i = pgdat->nr_zones-1 ; i >=0 ; i--) { zone = pgdat->node_zones + i; -cond_resched (); +__cond_resched ();if (!zone->need_balance)continue ;if (!try_to_free_pages (zone,GFP_KSWAPD ,0 )) {
Quoted 3 lines · Robert Love
With a preemptive kernel, explicit conditional schedules when
preempt_countis zero are a waste of cycles and code size.
Hmm.. Are there any other kind?
Another way of saying this: how can a conditional schedule _ever_ be nothing but a waste of cycles and code size with preemption enabled?
If the reason is the BKL, then I would much prefer those paths to be BKL-fixed, than have two different conditional schedules.
In short, I'd rather get a patch that just unconditionally makes the conditional schedules no-ops with preemption enabled. That would seem to make a lot more sense.
Linus
Quoted 11 lines · Linus Torvalds
Quoted 3 lines · Robert Love
With a preemptive kernel, explicit conditional schedules when
preempt_countis zero are a waste of cycles and code size.Hmm.. Are there any other kind?
Another way of saying this: how can a conditional schedule _ever_ be nothing but a waste of cycles and code size with preemption enabled?
Quoted 6 lines
If the reason is the BKL, then I would much prefer those paths to be BKL-fixed, than have two different conditional schedules.
In short, I'd rather get a patch that just unconditionally makes the conditional schedules no-ops with preemption enabled. That would seem to make a lot more sense.
I assume (and hope) the reason is always the BKL.
I would rather not eliminate any explicit reschedules from the kernel for the preemptive kernel case only. That sort of defeats a purpose (response improvement) of the kernel.
And I wholeheartedly agree that the situations where the BKL is held should be handled and an ideal solution is to just not explicitly schedule anywhere in the kernel with a preemptive kernel. But I suspect this will involve a lot of dark magic wrt BKL locking semantics.
What do you have in mind?
Robert Love