Re: [PATCH] sched_yield() flawed since 2.2.13?

From: George Anzinger (george@pioneer.net)
Date: Fri May 19 2000 - 11:33:27 EST


There have been numerous proposals around this (and several related)
problem(s). I suggest you look up the discussion in the digest.

The principle problem with your patch is that it introduces more code in
the inner schedule loop. A different approach might be to:
a.) Set the counter to zero for a sched yield process,
b.) Do the sched loop
c.) Reset the counter to its prior value

In this case you would also want to reset the counter if the reset
counter code is entered, but careful code placement will make this
happen. One also needs to consider the case where the only process in
the run list is the one trying to yield. This will force a counter
update in most variants, which is ok as long as it does not loop forever
doing this.

George
Giuseppe Ciaccio wrote:
>
> Hello,
> This message reports about a possible bug in the implementation of sched_yield()
> in kernel 2.2.13, which might not have been fixed in later kernels. A patch
> is proposed, which should solve the problem.
>
> I did the following experiment on a single-CPU machine with kernel 2.2.13:
>
> 1) Open three shells
>
> 2) Launch "top" on the first shell
>
> 3) Launch the following (endless) "loop" program on the second shell:
> void main (void)
> {
> for (;;);
> return;
> }
>
> 4) Launch the following (endless) "yield_loop" program on the third shell:
> #include <asm/unistd.h>
> int sched_yield (void)
> {
> long res;
> __asm__ __volatile__ ("int $0x80":"=a"(res):
> "0"(__NR_sched_yield)
> );
> return (int)res;
> }
>
> void main (void)
> {
> for (;;) sched_yield();
> return;
> }
>
> 5) Look at "top" in the first shell. You will see that both "loop" and
> "yield_loop" consume about 50% CPU time. According to the semantics of
> sched_yield(), however, one would expect 99% CPU time to be consumed by
> "loop", and only a negligible fraction of CPU time to be consumed by
> "yield_loop". Apparently, the implementation of sched_yield() is flawed.
>
> I could solve the problem by modifying file kernel/sched.c in 2.2.13.
>
> By comparing file kernel/sched.c in 2.2.13 and 2.3.99pre8 kernels, it
> appears that the same bug should also occur with the latter, at least with
> single-CPU machines. Could anyone confirm? If so, could anybody try applying
> the following patch to kernel/sched.c in 2.3.99pre8 and see if it fixes the
> bug? Thank you!
>
> Giuseppe
>
> Giuseppe Ciaccio http://www.disi.unige.it/person/CiaccioG/
> DISI - Universita' di Genova via Dodecaneso 35 16146 Genova, Italy
> phone +39 10 353 6638 fax +39 010 3536699 ciaccio@disi.unige.it
> ------------------------------------------------------------------------
>
> *** sched.c Fri May 19 12:41:36 2000
> --- sched.c.new Fri May 19 12:55:22 2000
> ***************
> *** 10,15 ****
> --- 10,17 ----
> * 1998-11-19 Implemented schedule_timeout() and related stuff
> * by Andrea Arcangeli
> * 1998-12-28 Implemented better SMP scheduling by Ingo Molnar
> + * 2000-05-19 Fixed wrong semantics of sched_yield() caused by bugs in
> + * prev_goodness() and goodness(), by Giuseppe Ciaccio
> */
>
> /*
> ***************
> *** 113,118 ****
> --- 115,126 ----
> {
> int weight;
>
> + /* Goodness of sched_yield()ed processes must be zero. */
> + if (p->policy & SCHED_YIELD) {
> + p->policy &= ~SCHED_YIELD;
> + return 0;
> + }
> +
> /*
> * Realtime process, select the first one on the
> * runqueue (taking priorities within processes
> ***************
> *** 150,170 ****
> return weight;
> }
>
> - /*
> - * subtle. We want to discard a yielded process only if it's being
> - * considered for a reschedule. Wakeup-time 'queries' of the scheduling
> - * state do not count. Another optimization we do: sched_yield()-ed
> - * processes are runnable (and thus will be considered for scheduling)
> - * right when they are calling schedule(). So the only place we need
> - * to care about SCHED_YIELD is when we calculate the previous process'
> - * goodness ...
> - */
> static inline int prev_goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm)
> {
> ! if (p->policy & SCHED_YIELD) {
> ! p->policy &= ~SCHED_YIELD;
> return 0;
> - }
> return goodness(p, this_cpu, this_mm);
> }
>
> --- 158,167 ----
> return weight;
> }
>
> static inline int prev_goodness(struct task_struct * p, int this_cpu, struct mm_struct *this_mm)
> {
> ! if (p->policy & SCHED_YIELD)
> return 0;
> return goodness(p, this_cpu, this_mm);
> }
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.rutgers.edu
> Please read the FAQ at http://www.tux.org/lkml/

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue May 23 2000 - 21:00:17 EST