Messages in this thread Patch in this message | | | Date | Tue, 14 Sep 2004 11:15:29 +0200 | From | Ingo Molnar <> | Subject | [patch] preempt-cleanup.patch, 2.6.9-rc2 |
| |
the attached patch is ontop of preempt-smp.patch. This is another generic fallout from the voluntary-preempt patchset: a cleanup of the cond_resched() infrastructure, in preparation of the latency reduction patches. The changes:
- uninline cond_resched() - this makes the footprint smaller, especially once the number of cond_resched() points increase.
- add a 'was rescheduled' return value to cond_resched. This makes it symmetric to cond_resched_lock() and later latency reduction patches rely on the ability to tell whether there was any preemption.
- make cond_resched() more robust by using the same mechanism as preempt_kernel(): by using PREEMPT_ACTIVE. This preserves the task's state - e.g. if the task is in TASK_ZOMBIE but gets preempted via cond_resched() just prior scheduling off then this approach preserves TASK_ZOMBIE.
- the patch also adds need_lockbreak() which critical sections can use to detect lock-break requests.
i've tested the patch on x86 SMP and UP.
Ingo
the attached patch is ontop of preempt-smp.patch. This is another generic fallout from the voluntary-preempt patchset: a cleanup of the cond_resched() infrastructure, in preparation of the latency reduction patches. The changes:
- uninline cond_resched() - this makes the footprint smaller, especially once the number of cond_resched() points increase.
- add a 'was rescheduled' return value to cond_resched. This makes it symmetric to cond_resched_lock() and later latency reduction patches rely on the ability to tell whether there was any preemption.
- make cond_resched() more robust by using the same mechanism as preempt_kernel(): by using PREEMPT_ACTIVE. This preserves the task's state - e.g. if the task is in TASK_ZOMBIE but gets preempted via cond_resched() just prior scheduling off then this approach preserves TASK_ZOMBIE.
- the patch also adds need_lockbreak() which critical sections can use to detect lock-break requests.
i've tested the patch on x86 SMP and UP.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
--- linux/include/linux/sched.h.orig +++ linux/include/linux/sched.h @@ -951,15 +951,24 @@ static inline int need_resched(void) return unlikely(test_thread_flag(TIF_NEED_RESCHED)); } -extern void __cond_resched(void); -static inline void cond_resched(void) -{ - if (need_resched()) - __cond_resched(); -} - +/* + * cond_resched() and cond_resched_lock(): latency reduction via + * explicit rescheduling in places that are safe. The return + * value indicates whether a reschedule was done in fact. + */ +extern int cond_resched(void); extern int cond_resched_lock(spinlock_t * lock); +/* + * Does a critical section need to be broken due to another + * task waiting?: + */ +#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) +# define need_lockbreak(lock) ((lock)->break_lock) +#else +# define need_lockbreak(lock) 0 +#endif + /* Reevaluate whether the task has signals pending delivery. This is required every time the blocked sigset_t changes. callers must hold sighand->siglock. */ --- linux/kernel/sched.c.orig +++ linux/kernel/sched.c @@ -3539,13 +3539,25 @@ asmlinkage long sys_sched_yield(void) return 0; } -void __sched __cond_resched(void) +static inline void __cond_resched(void) { - set_current_state(TASK_RUNNING); - schedule(); + do { + preempt_count() += PREEMPT_ACTIVE; + schedule(); + preempt_count() -= PREEMPT_ACTIVE; + } while (need_resched()); } -EXPORT_SYMBOL(__cond_resched); +int __sched cond_resched(void) +{ + if (need_resched()) { + __cond_resched(); + return 1; + } + return 0; +} + +EXPORT_SYMBOL(cond_resched); /* * cond_resched_lock() - if a reschedule is pending, drop the given lock, @@ -3568,8 +3580,7 @@ int cond_resched_lock(spinlock_t * lock) if (need_resched()) { _raw_spin_unlock(lock); preempt_enable_no_resched(); - set_current_state(TASK_RUNNING); - schedule(); + __cond_resched(); spin_lock(lock); return 1; }
| |