[patch] set_{current,task}_state() SMP safe

Andrea Arcangeli (andrea@suse.de)
Tue, 31 Aug 1999 18:08:17 +0200 (MEST)


I produced a new patch to fix the wait-event-interface SMP-races. I hope I
merged all the good implementation-hints I got. All architectures will
need to provide set_mb() to make the thing working. set_mb() can safely be
implemented everywhere as I did in the Alpha port (see the changes
include/asm-alpha/system.h). That should be the obvious implementation. As
Ingo pointed out on x86 it's a bit faster implemented using xchg than
using mb() and that's why we have a per-arch set_mb().

The other thing to note is that in a UP compile __set_current/task_state
will be completly equal to set_current/task_state (and that's the real
cons against the raw mb()).

The old:

current->state = XXX;

is equivalent to:

__set_current_state(XXX);

The old:

struct task_struct * tsk = current;
tsk->state = XXX;

is always equivalent to:

struct task_struct * tsk;
__set_task_state(tsk, XXX);

Choosing between the old and the new style will make no difference at all.

The real difference instead is between:

__set_{current,task}_state and set_{current,task}_state.

when the kernel is compiled SMP. The former will only set the state of
the task, the latter instead will set the state of the task and _then_
will force a SMP memory barrier.

The task->state is just volatile so no need of barrier() after setting it
on UP.

The SMP safe set_{current,task}_state are always safe. So if somebody is
unsure he should use it in the wait-event interface. In general if you
grab a spinlock between the set_current_state and the condtion-check you
can use the raw __set_current_state version.

Comments are welcome.

Patch against 2.3.16-pre1:

diff -urN 2.3.16-pre1/arch/i386/kernel/apm.c 2.3.16-pre1-wait_event/arch/i386/kernel/apm.c
--- 2.3.16-pre1/arch/i386/kernel/apm.c Thu Aug 12 20:53:22 1999
+++ 2.3.16-pre1-wait_event/arch/i386/kernel/apm.c Tue Aug 31 13:08:10 1999
@@ -1077,7 +1077,7 @@
return -EAGAIN;
add_wait_queue(&apm_waitqueue, &wait);
repeat:
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty(as) && !signal_pending(current)) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/arch/m68k/mac/adb-bus.c 2.3.16-pre1-wait_event/arch/m68k/mac/adb-bus.c
--- 2.3.16-pre1/arch/m68k/mac/adb-bus.c Mon Aug 9 21:27:30 1999
+++ 2.3.16-pre1-wait_event/arch/m68k/mac/adb-bus.c Tue Aug 31 13:08:10 1999
@@ -2334,8 +2334,8 @@
int ret = 0;
DECLARE_WAITQUEUE(wait,current);

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&adb_wait, &wait);
- current->state = TASK_INTERRUPTIBLE;

while (!state->req.got_reply) {
if (file->f_flags & O_NONBLOCK) {
@@ -2349,7 +2349,7 @@
schedule();
}

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&adb_wait, &wait);

return ret;
@@ -2562,8 +2562,8 @@
printk("ADB request: wait_reply (blocking ... \n");
#endif

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&adb_wait, &wait);
- current->state = TASK_INTERRUPTIBLE;

while (!state->req.got_reply) {
if (file->f_flags & O_NONBLOCK) {
@@ -2577,7 +2577,7 @@
schedule();
}

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&adb_wait, &wait);

return ret;
diff -urN 2.3.16-pre1/arch/mips/baget/vacserial.c 2.3.16-pre1-wait_event/arch/mips/baget/vacserial.c
--- 2.3.16-pre1/arch/mips/baget/vacserial.c Tue Aug 31 13:06:12 1999
+++ 2.3.16-pre1-wait_event/arch/mips/baget/vacserial.c Tue Aug 31 13:08:10 1999
@@ -1778,7 +1778,6 @@
baget_printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
#endif
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -1903,7 +1902,7 @@
restore_flags(flags);
info->blocked_open++;
while (1) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/arch/ppc/8xx_io/uart.c 2.3.16-pre1-wait_event/arch/ppc/8xx_io/uart.c
--- 2.3.16-pre1/arch/ppc/8xx_io/uart.c Tue Aug 31 13:06:12 1999
+++ 2.3.16-pre1-wait_event/arch/ppc/8xx_io/uart.c Tue Aug 31 13:08:10 1999
@@ -1826,7 +1826,7 @@
serial_inp(info, UART_MCR) |
(UART_MCR_DTR | UART_MCR_RTS));
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/arch/sparc64/solaris/timod.c 2.3.16-pre1-wait_event/arch/sparc64/solaris/timod.c
--- 2.3.16-pre1/arch/sparc64/solaris/timod.c Tue Aug 3 07:07:16 1999
+++ 2.3.16-pre1-wait_event/arch/sparc64/solaris/timod.c Tue Aug 31 13:08:10 1999
@@ -677,7 +677,7 @@
wait = &wait_table;
for(;;) {
SOLD("loop");
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
/* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
/* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
/* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
diff -urN 2.3.16-pre1/drivers/block/raid5.c 2.3.16-pre1-wait_event/drivers/block/raid5.c
--- 2.3.16-pre1/drivers/block/raid5.c Thu Aug 12 19:16:28 1999
+++ 2.3.16-pre1-wait_event/drivers/block/raid5.c Tue Aug 31 13:08:10 1999
@@ -97,7 +97,7 @@
sh->count++;
add_wait_queue(&sh->wait, &wait);
repeat:
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (stripe_locked(sh)) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/drivers/char/busmouse.c 2.3.16-pre1-wait_event/drivers/char/busmouse.c
--- 2.3.16-pre1/drivers/char/busmouse.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/busmouse.c Tue Aug 31 13:08:10 1999
@@ -273,7 +273,7 @@

add_wait_queue(&mse->wait, &wait);
repeat:
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (!mse->ready && !signal_pending(current)) {
spin_unlock_irqrestore(&mse->lock, flags);
schedule();
diff -urN 2.3.16-pre1/drivers/char/cyclades.c 2.3.16-pre1-wait_event/drivers/char/cyclades.c
--- 2.3.16-pre1/drivers/char/cyclades.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/cyclades.c Tue Aug 31 13:08:10 1999
@@ -2554,7 +2554,7 @@
}
CY_UNLOCK(info, flags);

- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)
|| !(info->flags & ASYNC_INITIALIZED) ){
return ((info->flags & ASYNC_HUP_NOTIFY) ?
@@ -2615,7 +2615,7 @@
printk("cyc:block_til_ready raising Z DTR\n");
#endif

- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)
|| !(info->flags & ASYNC_INITIALIZED) ){
return ((info->flags & ASYNC_HUP_NOTIFY) ?
@@ -2851,7 +2851,6 @@
printk("Not clean (jiff=%lu)...", jiffies);
#endif
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -2864,7 +2863,6 @@
}
/* Run one more char cycle */
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(char_time * 5);
current->state = TASK_RUNNING;
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
diff -urN 2.3.16-pre1/drivers/char/dz.c 2.3.16-pre1-wait_event/drivers/char/dz.c
--- 2.3.16-pre1/drivers/char/dz.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/dz.c Tue Aug 31 13:08:10 1999
@@ -1194,7 +1194,7 @@
info->count--;
info->blocked_open++;
while (1) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p (filp) || !(info->is_initialized)) {
retval = -EAGAIN;
break;
diff -urN 2.3.16-pre1/drivers/char/epca.c 2.3.16-pre1-wait_event/drivers/char/epca.c
--- 2.3.16-pre1/drivers/char/epca.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/epca.c Tue Aug 31 13:08:10 1999
@@ -1367,7 +1367,7 @@
while(1)
{ /* Begin forever while */

- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

if (tty_hung_up_p(filp) ||
!(ch->asyncflags & ASYNC_INITIALIZED))
diff -urN 2.3.16-pre1/drivers/char/esp.c 2.3.16-pre1-wait_event/drivers/char/esp.c
--- 2.3.16-pre1/drivers/char/esp.c Wed Jul 7 04:16:55 1999
+++ 2.3.16-pre1-wait_event/drivers/char/esp.c Tue Aug 31 13:08:10 1999
@@ -2317,7 +2317,7 @@
scratch | UART_MCR_DTR | UART_MCR_RTS);
}
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/drivers/char/ftape/lowlevel/ftape-io.c 2.3.16-pre1-wait_event/drivers/char/ftape/lowlevel/ftape-io.c
--- 2.3.16-pre1/drivers/char/ftape/lowlevel/ftape-io.c Wed Nov 4 18:57:43 1998
+++ 2.3.16-pre1-wait_event/drivers/char/ftape/lowlevel/ftape-io.c Tue Aug 31 13:08:10 1999
@@ -95,19 +95,19 @@

TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks);
timeout = ticks;
- current->state = TASK_INTERRUPTIBLE;
save_flags(flags);
sti();
+ set_current_state(TASK_INTERRUPTIBLE);
do {
- while (current->state != TASK_RUNNING) {
- timeout = schedule_timeout(timeout);
- }
/* Mmm. Isn't current->blocked == 0xffffffff ?
*/
if (signal_pending(current)) {
TRACE(ft_t_err,
"awoken by non-blocked signal :-(");
break; /* exit on signal */
+ }
+ while (current->state != TASK_RUNNING) {
+ timeout = schedule_timeout(timeout);
}
} while (timeout);
restore_flags(flags);
diff -urN 2.3.16-pre1/drivers/char/generic_serial.c 2.3.16-pre1-wait_event/drivers/char/generic_serial.c
--- 2.3.16-pre1/drivers/char/generic_serial.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/generic_serial.c Tue Aug 31 13:08:10 1999
@@ -698,7 +698,7 @@
while (1) {
CD = port->rd->get_CD (port);
gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
diff -urN 2.3.16-pre1/drivers/char/ip2/i2lib.c 2.3.16-pre1-wait_event/drivers/char/ip2/i2lib.c
--- 2.3.16-pre1/drivers/char/ip2/i2lib.c Mon Aug 23 19:23:23 1999
+++ 2.3.16-pre1-wait_event/drivers/char/ip2/i2lib.c Tue Aug 31 13:08:10 1999
@@ -640,7 +640,6 @@

if (!in_interrupt()) {
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0;
schedule_timeout(1); // short nap
} else {
// we cannot sched/sleep in interrrupt silly
@@ -1135,7 +1134,6 @@
ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
#endif
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0;
schedule_timeout(2);
if (signal_pending(current)) {
break;
diff -urN 2.3.16-pre1/drivers/char/ip2main.c 2.3.16-pre1-wait_event/drivers/char/ip2main.c
--- 2.3.16-pre1/drivers/char/ip2main.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/ip2main.c Tue Aug 31 13:08:10 1999
@@ -1573,7 +1573,6 @@
if (pCh->wopen) {
if (pCh->ClosingDelay) {
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0;
schedule_timeout(pCh->ClosingDelay);
}
wake_up_interruptible(&pCh->open_wait);
diff -urN 2.3.16-pre1/drivers/char/isicom.c 2.3.16-pre1-wait_event/drivers/char/isicom.c
--- 2.3.16-pre1/drivers/char/isicom.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/isicom.c Tue Aug 31 13:08:10 1999
@@ -995,7 +995,7 @@
raise_dtr_rts(port);

sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
diff -urN 2.3.16-pre1/drivers/char/joystick/joystick.c 2.3.16-pre1-wait_event/drivers/char/joystick/joystick.c
--- 2.3.16-pre1/drivers/char/joystick/joystick.c Wed May 12 22:27:37 1999
+++ 2.3.16-pre1-wait_event/drivers/char/joystick/joystick.c Tue Aug 31 13:08:10 1999
@@ -525,8 +525,8 @@

if (GOF(curl->tail) == jd->bhead && curl->startup == jd->num_axes + jd->num_buttons) {

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&jd->wait, &wait);
- current->state = TASK_INTERRUPTIBLE;

while (GOF(curl->tail) == jd->bhead) {

diff -urN 2.3.16-pre1/drivers/char/msp3400.c 2.3.16-pre1-wait_event/drivers/char/msp3400.c
--- 2.3.16-pre1/drivers/char/msp3400.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/msp3400.c Tue Aug 31 13:08:10 1999
@@ -795,9 +795,8 @@
UNLOCK_I2C_BUS(msp->bus);

/* wait 1 sec */
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + HZ;
- schedule();
+ __set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
if (signal_pending(current))
goto done;
if (msp->restart) {
diff -urN 2.3.16-pre1/drivers/char/n_tty.c 2.3.16-pre1-wait_event/drivers/char/n_tty.c
--- 2.3.16-pre1/drivers/char/n_tty.c Tue May 11 23:37:40 1999
+++ 2.3.16-pre1-wait_event/drivers/char/n_tty.c Tue Aug 31 13:08:10 1999
@@ -948,7 +948,7 @@
/* This statement must be first before checking for input
so that any interrupt will set the state back to
TASK_RUNNING. */
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

if (((minimum - (b - buf)) < tty->minimum_to_wake) &&
((minimum - (b - buf)) >= 1))
@@ -1073,7 +1073,7 @@

add_wait_queue(&tty->write_wait, &wait);
while (1) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
diff -urN 2.3.16-pre1/drivers/char/pc_keyb.c 2.3.16-pre1-wait_event/drivers/char/pc_keyb.c
--- 2.3.16-pre1/drivers/char/pc_keyb.c Tue Aug 3 01:40:36 1999
+++ 2.3.16-pre1-wait_event/drivers/char/pc_keyb.c Tue Aug 31 13:08:10 1999
@@ -872,7 +872,7 @@
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty() && !signal_pending(current)) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/drivers/char/pcxx.c 2.3.16-pre1-wait_event/drivers/char/pcxx.c
--- 2.3.16-pre1/drivers/char/pcxx.c Thu Aug 5 23:34:01 1999
+++ 2.3.16-pre1-wait_event/drivers/char/pcxx.c Tue Aug 31 13:08:10 1999
@@ -356,7 +356,7 @@
memoff(info);
}
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if(tty_hung_up_p(filp) || (info->asyncflags & ASYNC_INITIALIZED) == 0) {
if(info->asyncflags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
diff -urN 2.3.16-pre1/drivers/char/planb.c 2.3.16-pre1-wait_event/drivers/char/planb.c
--- 2.3.16-pre1/drivers/char/planb.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/planb.c Tue Aug 31 13:08:10 1999
@@ -383,7 +383,7 @@

add_wait_queue(&pb->lockq, &wait);
repeat:
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (pb->lock) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/drivers/char/qpmouse.c 2.3.16-pre1-wait_event/drivers/char/qpmouse.c
--- 2.3.16-pre1/drivers/char/qpmouse.c Tue May 11 23:37:40 1999
+++ 2.3.16-pre1-wait_event/drivers/char/qpmouse.c Tue Aug 31 13:08:10 1999
@@ -267,7 +267,7 @@
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty() && !signal_pending(current)) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/drivers/char/random.c 2.3.16-pre1-wait_event/drivers/char/random.c
--- 2.3.16-pre1/drivers/char/random.c Mon Aug 23 19:10:29 1999
+++ 2.3.16-pre1-wait_event/drivers/char/random.c Tue Aug 31 13:08:10 1999
@@ -1309,7 +1309,7 @@

add_wait_queue(&random_read_wait, &wait);
while (nbytes > 0) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

n = nbytes;
if (n > random_state.entropy_count / 8)
diff -urN 2.3.16-pre1/drivers/char/riscom8.c 2.3.16-pre1-wait_event/drivers/char/riscom8.c
--- 2.3.16-pre1/drivers/char/riscom8.c Thu Aug 5 23:34:01 1999
+++ 2.3.16-pre1-wait_event/drivers/char/riscom8.c Tue Aug 31 13:08:10 1999
@@ -1027,7 +1027,7 @@
rc_out(bp, RC_DTR, bp->DTR);
}
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
diff -urN 2.3.16-pre1/drivers/char/rocket.c 2.3.16-pre1-wait_event/drivers/char/rocket.c
--- 2.3.16-pre1/drivers/char/rocket.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/rocket.c Tue Aug 31 13:08:10 1999
@@ -888,7 +888,7 @@
sSetDTR(&info->channel);
sSetRTS(&info->channel);
}
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ROCKET_INITIALIZED)) {
if (info->flags & ROCKET_HUP_NOTIFY)
diff -urN 2.3.16-pre1/drivers/char/selection.c 2.3.16-pre1-wait_event/drivers/char/selection.c
--- 2.3.16-pre1/drivers/char/selection.c Tue May 11 23:37:40 1999
+++ 2.3.16-pre1-wait_event/drivers/char/selection.c Tue Aug 31 13:08:10 1999
@@ -301,7 +301,7 @@
poke_blanked_console();
add_wait_queue(&vt->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (test_bit(TTY_THROTTLED, &tty->flags)) {
schedule();
continue;
diff -urN 2.3.16-pre1/drivers/char/serial.c 2.3.16-pre1-wait_event/drivers/char/serial.c
--- 2.3.16-pre1/drivers/char/serial.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/serial.c Tue Aug 31 13:08:10 1999
@@ -2511,7 +2511,7 @@
serial_inp(info, UART_MCR) |
(UART_MCR_DTR | UART_MCR_RTS));
restore_flags(flags);
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/drivers/char/serial167.c 2.3.16-pre1-wait_event/drivers/char/serial167.c
--- 2.3.16-pre1/drivers/char/serial167.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/serial167.c Tue Aug 31 13:08:10 1999
@@ -2094,7 +2094,7 @@
#endif
}
restore_flags(flags);
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)
|| !(info->flags & ASYNC_INITIALIZED) ){
if (info->flags & ASYNC_HUP_NOTIFY) {
diff -urN 2.3.16-pre1/drivers/char/specialix.c 2.3.16-pre1-wait_event/drivers/char/specialix.c
--- 2.3.16-pre1/drivers/char/specialix.c Tue Aug 31 13:06:15 1999
+++ 2.3.16-pre1-wait_event/drivers/char/specialix.c Tue Aug 31 13:08:10 1999
@@ -1398,7 +1398,7 @@
}
}
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
diff -urN 2.3.16-pre1/drivers/char/synclink.c 2.3.16-pre1-wait_event/drivers/char/synclink.c
--- 2.3.16-pre1/drivers/char/synclink.c Thu Jun 17 04:26:27 1999
+++ 2.3.16-pre1-wait_event/drivers/char/synclink.c Tue Aug 31 13:08:10 1999
@@ -3413,7 +3413,6 @@
if ( info->params.mode == MGSL_MODE_HDLC ) {
while (info->tx_active) {
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -3424,7 +3423,6 @@
while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) &&
info->tx_enabled) {
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -3561,7 +3559,7 @@
spin_unlock_irqrestore(&info->irq_spinlock,flags);
}

- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){
retval = (info->flags & ASYNC_HUP_NOTIFY) ?
diff -urN 2.3.16-pre1/drivers/char/tty_io.c 2.3.16-pre1-wait_event/drivers/char/tty_io.c
--- 2.3.16-pre1/drivers/char/tty_io.c Mon Aug 23 19:23:23 1999
+++ 2.3.16-pre1-wait_event/drivers/char/tty_io.c Tue Aug 31 13:08:10 1999
@@ -1631,7 +1631,7 @@

static int send_break(struct tty_struct *tty, int duration)
{
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

tty->driver.break_ctl(tty, -1);
if (!signal_pending(current))
diff -urN 2.3.16-pre1/drivers/char/tty_ioctl.c 2.3.16-pre1-wait_event/drivers/char/tty_ioctl.c
--- 2.3.16-pre1/drivers/char/tty_ioctl.c Tue May 11 23:37:40 1999
+++ 2.3.16-pre1-wait_event/drivers/char/tty_ioctl.c Tue Aug 31 13:08:10 1999
@@ -59,7 +59,7 @@
printk("waiting %s...(%d)\n", tty_name(tty, buf),
tty->driver.chars_in_buffer(tty));
#endif
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
goto stop_waiting;
if (!tty->driver.chars_in_buffer(tty))
diff -urN 2.3.16-pre1/drivers/char/vt.c 2.3.16-pre1-wait_event/drivers/char/vt.c
--- 2.3.16-pre1/drivers/char/vt.c Mon Aug 23 20:15:53 1999
+++ 2.3.16-pre1-wait_event/drivers/char/vt.c Tue Aug 31 13:08:10 1999
@@ -1113,7 +1113,7 @@

add_wait_queue(&vt_activate_queue, &wait);
for (;;) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
retval = 0;
if (vt == fg_console)
break;
diff -urN 2.3.16-pre1/drivers/isdn/isdn_tty.c 2.3.16-pre1-wait_event/drivers/isdn/isdn_tty.c
--- 2.3.16-pre1/drivers/isdn/isdn_tty.c Thu Aug 12 18:42:33 1999
+++ 2.3.16-pre1-wait_event/drivers/isdn/isdn_tty.c Tue Aug 31 13:08:10 1999
@@ -1981,7 +1981,7 @@
restore_flags(flags);
info->blocked_open++;
while (1) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ISDN_ASYNC_INITIALIZED)) {
#ifdef MODEM_DO_RESTART
diff -urN 2.3.16-pre1/drivers/macintosh/macserial.c 2.3.16-pre1-wait_event/drivers/macintosh/macserial.c
--- 2.3.16-pre1/drivers/macintosh/macserial.c Thu Aug 12 20:50:14 1999
+++ 2.3.16-pre1-wait_event/drivers/macintosh/macserial.c Tue Aug 31 13:08:10 1999
@@ -1674,7 +1674,7 @@
(tty->termios->c_cflag & CBAUD))
zs_rtsdtr(info, 1);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ZILOG_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/drivers/net/cosa.c 2.3.16-pre1-wait_event/drivers/net/cosa.c
--- 2.3.16-pre1/drivers/net/cosa.c Mon Aug 23 19:10:29 1999
+++ 2.3.16-pre1-wait_event/drivers/net/cosa.c Tue Aug 31 13:08:10 1999
@@ -1560,7 +1560,6 @@
/* sleep if not ready to read */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
- current->state = TASK_RUNNING;
}
printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
cosa_getstatus(cosa));
@@ -1588,7 +1587,6 @@
/* sleep if not ready to read */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
- current->state = TASK_RUNNING;
#endif
}
printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
diff -urN 2.3.16-pre1/drivers/net/cycx_drv.c 2.3.16-pre1-wait_event/drivers/net/cycx_drv.c
--- 2.3.16-pre1/drivers/net/cycx_drv.c Thu Aug 12 18:46:13 1999
+++ 2.3.16-pre1-wait_event/drivers/net/cycx_drv.c Tue Aug 31 13:08:10 1999
@@ -638,7 +638,6 @@
know it all the contexts where this routine is used are interruptible... */

current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(sec*HZ);
}

diff -urN 2.3.16-pre1/drivers/sbus/char/aurora.c 2.3.16-pre1-wait_event/drivers/sbus/char/aurora.c
--- 2.3.16-pre1/drivers/sbus/char/aurora.c Wed Jun 30 20:24:54 1999
+++ 2.3.16-pre1-wait_event/drivers/sbus/char/aurora.c Tue Aug 31 13:08:10 1999
@@ -1327,7 +1327,7 @@
bp->r[chip]->r[CD180_MSVR]=port->MSVR;/* auto drops DTR */
}
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
diff -urN 2.3.16-pre1/drivers/sbus/char/pcikbd.c 2.3.16-pre1-wait_event/drivers/sbus/char/pcikbd.c
--- 2.3.16-pre1/drivers/sbus/char/pcikbd.c Wed Jun 9 23:44:25 1999
+++ 2.3.16-pre1-wait_event/drivers/sbus/char/pcikbd.c Tue Aug 31 13:08:10 1999
@@ -893,7 +893,7 @@
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty() && !signal_pending(current)) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/drivers/sbus/char/sab82532.c 2.3.16-pre1-wait_event/drivers/sbus/char/sab82532.c
--- 2.3.16-pre1/drivers/sbus/char/sab82532.c Sun Jul 4 18:53:12 1999
+++ 2.3.16-pre1-wait_event/drivers/sbus/char/sab82532.c Tue Aug 31 13:08:10 1999
@@ -1802,7 +1802,7 @@
info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
}
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/drivers/sbus/char/su.c 2.3.16-pre1-wait_event/drivers/sbus/char/su.c
--- 2.3.16-pre1/drivers/sbus/char/su.c Sun Jul 4 18:53:12 1999
+++ 2.3.16-pre1-wait_event/drivers/sbus/char/su.c Tue Aug 31 13:08:10 1999
@@ -1965,7 +1965,7 @@
serial_inp(info, UART_MCR) |
(UART_MCR_DTR | UART_MCR_RTS));
restore_flags(flags);
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/drivers/sbus/char/zs.c 2.3.16-pre1-wait_event/drivers/sbus/char/zs.c
--- 2.3.16-pre1/drivers/sbus/char/zs.c Tue Aug 3 07:07:16 1999
+++ 2.3.16-pre1-wait_event/drivers/sbus/char/zs.c Tue Aug 31 13:08:10 1999
@@ -1711,7 +1711,7 @@
if (!(info->flags & ZILOG_CALLOUT_ACTIVE))
zs_rtsdtr(info, 1);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ZILOG_INITIALIZED)) {
#ifdef SERIAL_DEBUG_OPEN
diff -urN 2.3.16-pre1/drivers/scsi/scsi.h 2.3.16-pre1-wait_event/drivers/scsi/scsi.h
--- 2.3.16-pre1/drivers/scsi/scsi.h Mon Aug 30 15:02:56 1999
+++ 2.3.16-pre1-wait_event/drivers/scsi/scsi.h Tue Aug 31 16:39:45 1999
@@ -715,7 +715,7 @@
DECLARE_WAITQUEUE(wait, current); \
add_wait_queue(QUEUE, &wait); \
for(;;) { \
- current->state = TASK_UNINTERRUPTIBLE; \
+ set_current_state(TASK_UNINTERRUPTIBLE); \
if (CONDITION) { \
if (in_interrupt()) \
panic("scsi: trying to call schedule() in interrupt" \
diff -urN 2.3.16-pre1/drivers/sgi/char/sgiserial.c 2.3.16-pre1-wait_event/drivers/sgi/char/sgiserial.c
--- 2.3.16-pre1/drivers/sgi/char/sgiserial.c Tue Jun 29 18:22:08 1999
+++ 2.3.16-pre1-wait_event/drivers/sgi/char/sgiserial.c Tue Aug 31 13:08:10 1999
@@ -1591,7 +1591,7 @@
if (!(info->flags & ZILOG_CALLOUT_ACTIVE))
zs_rtsdtr(info, 1);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ZILOG_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/drivers/tc/zs.c 2.3.16-pre1-wait_event/drivers/tc/zs.c
--- 2.3.16-pre1/drivers/tc/zs.c Tue Aug 31 13:06:16 1999
+++ 2.3.16-pre1-wait_event/drivers/tc/zs.c Tue Aug 31 13:08:10 1999
@@ -1315,7 +1315,6 @@
char_time = MIN(char_time, timeout);
while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
current->state = TASK_INTERRUPTIBLE;
- current->counter = 0; /* make us low-priority */
schedule_timeout(char_time);
if (signal_pending(current))
break;
@@ -1433,7 +1432,7 @@
(tty->termios->c_cflag & CBAUD))
zs_rtsdtr(info, 1);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ZILOG_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
diff -urN 2.3.16-pre1/fs/buffer.c 2.3.16-pre1-wait_event/fs/buffer.c
--- 2.3.16-pre1/fs/buffer.c Tue Aug 31 13:06:17 1999
+++ 2.3.16-pre1-wait_event/fs/buffer.c Tue Aug 31 13:08:10 1999
@@ -146,8 +146,8 @@
atomic_inc(&bh->b_count);
add_wait_queue(&bh->b_wait, &wait);
repeat:
- tsk->state = TASK_UNINTERRUPTIBLE;
run_task_queue(&tq_disk);
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (buffer_locked(bh)) {
schedule();
goto repeat;
@@ -1088,7 +1088,6 @@
*/
static struct buffer_head * create_buffers(unsigned long page, unsigned long size, int async)
{
- DECLARE_WAITQUEUE(wait, current);
struct buffer_head *bh, *head;
long offset;

@@ -1153,14 +1152,7 @@
* Set our state for sleeping, then check again for buffer heads.
* This ensures we won't miss a wake_up from an interrupt.
*/
- add_wait_queue(&buffer_wait, &wait);
- current->state = TASK_UNINTERRUPTIBLE;
- if (nr_unused_buffer_heads < MAX_BUF_PER_PAGE) {
- current->policy |= SCHED_YIELD;
- schedule();
- }
- remove_wait_queue(&buffer_wait, &wait);
- current->state = TASK_RUNNING;
+ wait_event(buffer_wait, nr_unused_buffer_heads >= MAX_BUF_PER_PAGE);
goto try_again;
}

diff -urN 2.3.16-pre1/fs/coda/upcall.c 2.3.16-pre1-wait_event/fs/coda/upcall.c
--- 2.3.16-pre1/fs/coda/upcall.c Mon Aug 23 19:14:44 1999
+++ 2.3.16-pre1-wait_event/fs/coda/upcall.c Tue Aug 31 13:08:10 1999
@@ -625,9 +625,9 @@
add_wait_queue(&vmp->uc_sleep, &wait);
for (;;) {
if ( coda_hard == 0 )
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
else
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);

/* got a reply */
if ( vmp->uc_flags & REQ_WRITE )
diff -urN 2.3.16-pre1/fs/dquot.c 2.3.16-pre1-wait_event/fs/dquot.c
--- 2.3.16-pre1/fs/dquot.c Mon Aug 23 20:15:53 1999
+++ 2.3.16-pre1-wait_event/fs/dquot.c Tue Aug 31 13:08:10 1999
@@ -199,7 +199,7 @@

add_wait_queue(&dquot->dq_wait, &wait);
repeat:
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (dquot->dq_flags & DQ_LOCKED) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/fs/inode.c 2.3.16-pre1-wait_event/fs/inode.c
--- 2.3.16-pre1/fs/inode.c Tue Jul 6 05:34:31 1999
+++ 2.3.16-pre1-wait_event/fs/inode.c Tue Aug 31 13:08:10 1999
@@ -103,7 +103,7 @@

add_wait_queue(&inode->i_wait, &wait);
repeat:
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (inode->i_state & I_LOCK) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/fs/iobuf.c 2.3.16-pre1-wait_event/fs/iobuf.c
--- 2.3.16-pre1/fs/iobuf.c Tue Jul 27 07:50:35 1999
+++ 2.3.16-pre1-wait_event/fs/iobuf.c Tue Aug 31 13:08:10 1999
@@ -122,8 +122,8 @@

add_wait_queue(&kiobuf->wait_queue, &wait);
repeat:
- tsk->state = TASK_UNINTERRUPTIBLE;
run_task_queue(&tq_disk);
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (atomic_read(&kiobuf->io_count) != 0) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/fs/ncpfs/sock.c 2.3.16-pre1-wait_event/fs/ncpfs/sock.c
--- 2.3.16-pre1/fs/ncpfs/sock.c Fri May 14 21:43:00 1999
+++ 2.3.16-pre1-wait_event/fs/ncpfs/sock.c Tue Aug 31 13:08:10 1999
@@ -172,7 +172,10 @@
re_select:
wait_table.nr = 0;
wait_table.entry = &entry;
- current->state = TASK_INTERRUPTIBLE;
+ /* mb() is not necessary because ->poll() will serialize
+ instructions adding the wait_table waitqueues in the
+ waitqueue-head before going to calculate the mask-retval. */
+ __set_current_state(TASK_INTERRUPTIBLE);
if (!(file->f_op->poll(file, &wait_table) & POLLIN)) {
int timed_out;
if (timeout > max_timeout) {
diff -urN 2.3.16-pre1/fs/nfs/write.c 2.3.16-pre1-wait_event/fs/nfs/write.c
--- 2.3.16-pre1/fs/nfs/write.c Sat Jul 3 19:44:05 1999
+++ 2.3.16-pre1-wait_event/fs/nfs/write.c Tue Aug 31 13:08:11 1999
@@ -392,7 +392,7 @@
rpc_clnt_sigmask(clnt, &oldmask);
add_wait_queue(&req->wb_wait, &wait);
for (;;) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
retval = 0;
if (req->wb_flags & NFS_WRITE_COMPLETE)
break;
diff -urN 2.3.16-pre1/fs/select.c 2.3.16-pre1-wait_event/fs/select.c
--- 2.3.16-pre1/fs/select.c Mon Aug 23 20:15:53 1999
+++ 2.3.16-pre1-wait_event/fs/select.c Tue Aug 31 13:08:11 1999
@@ -174,7 +174,7 @@
n = retval;
retval = 0;
for (;;) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
for (i = 0 ; i < n; i++) {
unsigned long bit = BIT(i);
unsigned long mask;
@@ -337,7 +337,7 @@
unsigned int j;
struct pollfd * fdpnt;

- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
for (fdpnt = fds, j = 0; j < nfds; j++, fdpnt++) {
int fd;
unsigned int mask;
diff -urN 2.3.16-pre1/fs/super.c 2.3.16-pre1-wait_event/fs/super.c
--- 2.3.16-pre1/fs/super.c Mon Aug 23 20:15:53 1999
+++ 2.3.16-pre1-wait_event/fs/super.c Tue Aug 31 13:08:11 1999
@@ -417,7 +417,7 @@

add_wait_queue(&sb->s_wait, &wait);
repeat:
- current->state = TASK_UNINTERRUPTIBLE;
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (sb->s_lock) {
schedule();
goto repeat;
diff -urN 2.3.16-pre1/include/asm-alpha/system.h 2.3.16-pre1-wait_event/include/asm-alpha/system.h
--- 2.3.16-pre1/include/asm-alpha/system.h Tue Aug 3 17:01:29 1999
+++ 2.3.16-pre1-wait_event/include/asm-alpha/system.h Tue Aug 31 17:45:30 1999
@@ -108,6 +108,15 @@
#define wmb() \
__asm__ __volatile__("wmb": : :"memory")

+#define set_mb(var, value) \
+do { var = value; mb(); } while (0)
+
+#define set_rmb(var, value) \
+do { var = value; rmb(); } while (0)
+
+#define set_wmb(var, value) \
+do { var = value; wmb(); } while (0)
+
#define imb() \
__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")

diff -urN 2.3.16-pre1/include/asm-i386/system.h 2.3.16-pre1-wait_event/include/asm-i386/system.h
--- 2.3.16-pre1/include/asm-i386/system.h Mon Aug 30 15:01:41 1999
+++ 2.3.16-pre1-wait_event/include/asm-i386/system.h Tue Aug 31 15:25:15 1999
@@ -133,7 +133,7 @@
* Note 2: xchg has side effect, so that attribute volatile is necessary,
* but generally the primitive is invalid, *ptr is output argument. --ANK
*/
-static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
switch (size) {
case 1:
@@ -175,6 +175,9 @@
#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#define rmb() mb()
#define wmb() __asm__ __volatile__ ("": : :"memory")
+#define set_rmb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) set_rmb(var, value)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)

/* interrupt control.. */
#define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
diff -urN 2.3.16-pre1/include/linux/sched.h 2.3.16-pre1-wait_event/include/linux/sched.h
--- 2.3.16-pre1/include/linux/sched.h Mon Aug 30 15:01:41 1999
+++ 2.3.16-pre1-wait_event/include/linux/sched.h Tue Aug 31 17:45:51 1999
@@ -83,6 +83,26 @@
#define TASK_SWAPPING 16
#define TASK_EXCLUSIVE 32

+#define __set_task_state(tsk, state_value) \
+ do { tsk->state = state_value; } while (0)
+#ifdef __SMP__
+#define set_task_state(tsk, state_value) \
+ set_mb(tsk->state, state_value)
+#else
+#define set_task_state(tsk, state_value) \
+ __set_task_state(tsk, state_value)
+#endif
+
+#define __set_current_state(state_value) \
+ do { current->state = state_value; } while (0)
+#ifdef __SMP__
+#define set_current_state(state_value) \
+ set_mb(current->state, state_value)
+#else
+#define set_current_state(state_value) \
+ __set_current_state(state_value)
+#endif
+
/*
* Scheduling policies
*/
@@ -715,8 +735,7 @@
\
add_wait_queue(&wq, &__wait); \
for (;;) { \
- current->state = TASK_UNINTERRUPTIBLE; \
- mb(); \
+ set_current_state(TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
@@ -739,8 +758,7 @@
\
add_wait_queue(&wq, &__wait); \
for (;;) { \
- current->state = TASK_INTERRUPTIBLE; \
- mb(); \
+ set_current_state(TASK_INTERRUPTIBLE); \
if (condition) \
break; \
if (!signal_pending(current)) { \
diff -urN 2.3.16-pre1/mm/filemap.c 2.3.16-pre1-wait_event/mm/filemap.c
--- 2.3.16-pre1/mm/filemap.c Tue Aug 31 13:06:18 1999
+++ 2.3.16-pre1-wait_event/mm/filemap.c Tue Aug 31 13:08:11 1999
@@ -595,8 +595,8 @@

add_wait_queue(&page->wait, &wait);
do {
- tsk->state = TASK_UNINTERRUPTIBLE;
run_task_queue(&tq_disk);
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
if (!PageLocked(page))
break;
schedule();
@@ -610,23 +610,8 @@
*/
void lock_page(struct page *page)
{
- if (TryLockPage(page)) {
- struct task_struct *tsk = current;
- DECLARE_WAITQUEUE(wait, current);
-
- run_task_queue(&tq_disk);
- add_wait_queue(&page->wait, &wait);
- tsk->state = TASK_UNINTERRUPTIBLE;
-
- while (TryLockPage(page)) {
- run_task_queue(&tq_disk);
- schedule();
- tsk->state = TASK_UNINTERRUPTIBLE;
- }
-
- remove_wait_queue(&page->wait, &wait);
- tsk->state = TASK_RUNNING;
- }
+ while (TryLockPage(page))
+ ___wait_on_page(page);
}


@@ -655,13 +640,14 @@
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);

+ run_task_queue(&tq_disk);
+
+ __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
add_wait_queue(&page->wait, &wait);
- tsk->state = TASK_UNINTERRUPTIBLE;

- run_task_queue(&tq_disk);
if (PageLocked(page))
schedule();
- tsk->state = TASK_RUNNING;
+ __set_task_state(tsk, TASK_RUNNING);
remove_wait_queue(&page->wait, &wait);

/*
@@ -704,13 +690,14 @@
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);

+ run_task_queue(&tq_disk);
+
+ __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
add_wait_queue(&page->wait, &wait);
- tsk->state = TASK_UNINTERRUPTIBLE;

- run_task_queue(&tq_disk);
if (PageLocked(page))
schedule();
- tsk->state = TASK_RUNNING;
+ __set_task_state(tsk, TASK_RUNNING);
remove_wait_queue(&page->wait, &wait);

/*
diff -urN 2.3.16-pre1/net/core/datagram.c 2.3.16-pre1-wait_event/net/core/datagram.c
--- 2.3.16-pre1/net/core/datagram.c Mon Aug 23 19:01:02 1999
+++ 2.3.16-pre1-wait_event/net/core/datagram.c Tue Aug 31 13:08:11 1999
@@ -65,10 +65,8 @@

DECLARE_WAITQUEUE(wait, current);

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(sk->sleep, &wait);
- current->state = TASK_INTERRUPTIBLE;
-
- barrier();

/* Socket errors? */
error = sock_error(sk);
diff -urN 2.3.16-pre1/net/core/sock.c 2.3.16-pre1-wait_event/net/core/sock.c
--- 2.3.16-pre1/net/core/sock.c Mon Aug 23 19:01:02 1999
+++ 2.3.16-pre1-wait_event/net/core/sock.c Tue Aug 31 13:08:11 1999
@@ -672,7 +672,7 @@
for (;;) {
if (signal_pending(current))
break;
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (atomic_read(&sk->wmem_alloc) < sk->sndbuf)
break;
if (sk->shutdown & SEND_SHUTDOWN)
@@ -681,7 +681,7 @@
break;
schedule();
}
- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sleep, &wait);
}

diff -urN 2.3.16-pre1/net/ipv4/af_inet.c 2.3.16-pre1-wait_event/net/ipv4/af_inet.c
--- 2.3.16-pre1/net/ipv4/af_inet.c Wed Aug 25 23:46:02 1999
+++ 2.3.16-pre1-wait_event/net/ipv4/af_inet.c Tue Aug 31 17:54:07 1999
@@ -564,13 +564,9 @@
{
DECLARE_WAITQUEUE(wait, current);

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(sk->sleep, &wait);
- current->state = TASK_INTERRUPTIBLE;

- /* RED-PEN. current->state is volatile. Is it enough to prevent
- * reordering it and sk->state check? I put barrier to be sure.
- */
- barrier();
while ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
if (signal_pending(current))
break;
@@ -579,10 +575,9 @@
release_sock(sk);
schedule();
lock_sock(sk);
- current->state = TASK_INTERRUPTIBLE;
- barrier();
+ set_current_state(TASK_INTERRUPTIBLE);
}
- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sleep, &wait);
}

diff -urN 2.3.16-pre1/net/ipv4/tcp.c 2.3.16-pre1-wait_event/net/ipv4/tcp.c
--- 2.3.16-pre1/net/ipv4/tcp.c Mon Aug 23 22:44:03 1999
+++ 2.3.16-pre1-wait_event/net/ipv4/tcp.c Tue Aug 31 13:08:11 1999
@@ -689,7 +689,7 @@
if(signal_pending(tsk))
return -ERESTARTSYS;

- tsk->state = TASK_INTERRUPTIBLE;
+ __set_task_state(tsk, TASK_INTERRUPTIBLE);
add_wait_queue(sk->sleep, &wait);
sk->tp_pinfo.af_tcp.write_pending++;

@@ -697,7 +697,7 @@
schedule();
lock_sock(sk);

- tsk->state = TASK_RUNNING;
+ __set_task_state(tsk, TASK_RUNNING);
remove_wait_queue(sk->sleep, &wait);
sk->tp_pinfo.af_tcp.write_pending--;
}
@@ -720,7 +720,7 @@
sk->socket->flags &= ~SO_NOSPACE;
add_wait_queue(sk->sleep, &wait);
for (;;) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

if (signal_pending(current))
break;
@@ -1121,7 +1121,7 @@

add_wait_queue(sk->sleep, &wait);

- current->state = TASK_INTERRUPTIBLE;
+ __set_current_state(TASK_INTERRUPTIBLE);

sk->socket->flags |= SO_WAITDATA;
release_sock(sk);
@@ -1133,7 +1133,7 @@
sk->socket->flags &= ~SO_WAITDATA;

remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
}

/*
@@ -1595,7 +1595,7 @@
add_wait_queue(sk->sleep, &wait);

while (1) {
- tsk->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
if (!closing(sk))
break;
release_sock(sk);
diff -urN 2.3.16-pre1/net/ipv4/tcp_ipv4.c 2.3.16-pre1-wait_event/net/ipv4/tcp_ipv4.c
--- 2.3.16-pre1/net/ipv4/tcp_ipv4.c Tue Aug 31 13:06:18 1999
+++ 2.3.16-pre1-wait_event/net/ipv4/tcp_ipv4.c Tue Aug 31 13:08:11 1999
@@ -412,16 +412,16 @@
DECLARE_WAITQUEUE(wait, current);

add_wait_queue(&tcp_lhash_wait, &wait);
- do {
- current->state = TASK_UNINTERRUPTIBLE;
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (atomic_read(&tcp_lhash_users) == 0)
break;
write_unlock_bh(&tcp_lhash_lock);
schedule();
write_lock_bh(&tcp_lhash_lock);
- } while (atomic_read(&tcp_lhash_users));
+ }

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&tcp_lhash_wait, &wait);
}
}
diff -urN 2.3.16-pre1/net/irda/ircomm/ircomm_tty.c 2.3.16-pre1-wait_event/net/irda/ircomm/ircomm_tty.c
--- 2.3.16-pre1/net/irda/ircomm/ircomm_tty.c Tue Aug 31 13:06:19 1999
+++ 2.3.16-pre1-wait_event/net/irda/ircomm/ircomm_tty.c Tue Aug 31 13:21:49 1999
@@ -305,7 +305,7 @@
restore_flags(flags);
}

- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);

if (tty_hung_up_p(filp) || !(self->flags & ASYNC_INITIALIZED)){
retval = (self->flags & ASYNC_HUP_NOTIFY) ?
@@ -337,7 +337,7 @@
schedule();
}

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&self->open_wait, &wait);

if (extra_count)
diff -urN 2.3.16-pre1/net/khttpd/main.c 2.3.16-pre1-wait_event/net/khttpd/main.c
--- 2.3.16-pre1/net/khttpd/main.c Mon Aug 23 22:44:03 1999
+++ 2.3.16-pre1-wait_event/net/khttpd/main.c Tue Aug 31 13:08:14 1999
@@ -144,7 +144,7 @@
changes +=AcceptConnections(CPUNR,MainSocket);
}

- current->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+ set_current_state(TASK_INTERRUPTIBLE|TASK_EXCLUSIVE);
if (changes==0)
{
(void)interruptible_sleep_on_timeout(&(DummyWQ[CPUNR]),1);
diff -urN 2.3.16-pre1/net/netlink/af_netlink.c 2.3.16-pre1-wait_event/net/netlink/af_netlink.c
--- 2.3.16-pre1/net/netlink/af_netlink.c Mon Aug 23 19:01:02 1999
+++ 2.3.16-pre1-wait_event/net/netlink/af_netlink.c Tue Aug 31 13:08:14 1999
@@ -103,16 +103,16 @@
DECLARE_WAITQUEUE(wait, current);

add_wait_queue(&nl_table_wait, &wait);
- do {
- current->state = TASK_UNINTERRUPTIBLE;
+ for(;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
if (atomic_read(&nl_table_users) == 0)
break;
write_unlock_bh(&nl_table_lock);
schedule();
write_lock_bh(&nl_table_lock);
- } while (atomic_read(&nl_table_users));
+ }

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&nl_table_wait, &wait);
}
}
@@ -417,10 +417,8 @@
return -EAGAIN;
}

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&sk->protinfo.af_netlink->wait, &wait);
- current->state = TASK_INTERRUPTIBLE;
-
- barrier();

if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
test_bit(0, &sk->protinfo.af_netlink->state)) &&
@@ -428,7 +426,7 @@
!sk->dead)
schedule();

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&sk->protinfo.af_netlink->wait, &wait);
sock_put(sk);

diff -urN 2.3.16-pre1/net/unix/af_unix.c 2.3.16-pre1-wait_event/net/unix/af_unix.c
--- 2.3.16-pre1/net/unix/af_unix.c Wed Aug 25 23:46:05 1999
+++ 2.3.16-pre1-wait_event/net/unix/af_unix.c Tue Aug 31 13:08:14 1999
@@ -747,10 +747,8 @@
int sched;
DECLARE_WAITQUEUE(wait, current);

+ __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&other->protinfo.af_unix.peer_wait, &wait);
- current->state = TASK_INTERRUPTIBLE;
-
- barrier();

sched = (!other->dead &&
!(other->shutdown&RCV_SHUTDOWN) &&
@@ -762,7 +760,7 @@
if (sched)
schedule();

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(&other->protinfo.af_unix.peer_wait, &wait);
}

@@ -1393,9 +1391,7 @@
add_wait_queue(sk->sleep, &wait);

for (;;) {
- current->state = TASK_INTERRUPTIBLE;
-
- barrier();
+ set_current_state(TASK_INTERRUPTIBLE);

if (skb_queue_len(&sk->receive_queue) ||
sk->err ||
@@ -1410,7 +1406,7 @@
sk->socket->flags &= ~SO_WAITDATA;
}

- current->state = TASK_RUNNING;
+ __set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sleep, &wait);
unix_state_runlock(sk);
}

I also removed some tsk->current = 0 that can only fool the scheduler. If
the kernel would been compiled in C++ the current field would been
declared as private ;).

Andrea

-
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/