diff -urN 2.2.19pre2/include/linux/sched.h wakeone/include/linux/sched.h --- 2.2.19pre2/include/linux/sched.h Wed Dec 20 03:31:39 2000 +++ wakeone/include/linux/sched.h Wed Dec 20 03:35:34 2000 @@ -252,7 +252,6 @@ struct task_struct *next_task, *prev_task; struct task_struct *next_run, *prev_run; - unsigned int task_exclusive; /* task wants wake-one semantics in __wake_up() */ /* task state */ struct linux_binfmt *binfmt; int exit_code, exit_signal; @@ -375,7 +374,6 @@ /* counter */ DEF_PRIORITY,DEF_PRIORITY,0, \ /* SMP */ 0,0,0,-1, \ /* schedlink */ &init_task,&init_task, &init_task, &init_task, \ -/* task_exclusive */ 0, \ /* binfmt */ NULL, \ /* ec,brk... */ 0,0,0,0,0,0, \ /* pid etc.. */ 0,0,0,0,0, \ @@ -502,8 +500,8 @@ signed long timeout)); extern void FASTCALL(wake_up_process(struct task_struct * tsk)); -#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE) -#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE) +#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE) +#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE) #define __set_current_state(state_value) do { current->state = state_value; } while (0) #ifdef __SMP__ diff -urN 2.2.19pre2/kernel/sched.c wakeone/kernel/sched.c --- 2.2.19pre2/kernel/sched.c Wed Dec 20 03:31:39 2000 +++ wakeone/kernel/sched.c Wed Dec 20 03:35:34 2000 @@ -727,7 +727,7 @@ goto move_rr_last; move_rr_back: - switch (prev->state) { + switch (prev->state & ~TASK_EXCLUSIVE) { case TASK_INTERRUPTIBLE: if (signal_pending(prev)) { prev->state = TASK_RUNNING; @@ -890,9 +890,9 @@ */ void __wake_up(struct wait_queue **q, unsigned int mode) { - struct task_struct *p, *best_exclusive; + struct task_struct *p; struct wait_queue *head, *next; - unsigned int do_exclusive; + int wake_one = 0; if (!q) goto out; @@ -907,23 +907,27 @@ if (!next) goto out_unlock; - best_exclusive = 0; - do_exclusive = mode & TASK_EXCLUSIVE; while (next != head) { p = next->task; next = next->next; if (p->state & mode) { - if (do_exclusive && p->task_exclusive) { - if (best_exclusive == NULL) - best_exclusive = p; + if (p->state & TASK_EXCLUSIVE) { + if (wake_one) + continue; + wake_one = 1; } - else { + /* + * We can drop the read-lock early if this + * is the only/last process. + */ + if (next == head) { + read_unlock(&waitqueue_lock); wake_up_process(p); + goto out; } + wake_up_process(p); } } - if (best_exclusive) - wake_up_process(best_exclusive); out_unlock: read_unlock(&waitqueue_lock); out: @@ -1221,7 +1225,7 @@ read_lock(&tasklist_lock); for_each_task(p) { if ((p->state == TASK_RUNNING || - p->state == TASK_UNINTERRUPTIBLE || + p->state & TASK_UNINTERRUPTIBLE || p->state == TASK_SWAPPING)) nr += FIXED_1; } diff -urN 2.2.19pre2/kernel/signal.c wakeone/kernel/signal.c --- 2.2.19pre2/kernel/signal.c Thu May 4 13:00:40 2000 +++ wakeone/kernel/signal.c Wed Dec 20 03:35:34 2000 @@ -394,7 +394,7 @@ out: spin_unlock_irqrestore(&t->sigmask_lock, flags); - if (t->state == TASK_INTERRUPTIBLE && signal_pending(t)) + if (t->state & TASK_INTERRUPTIBLE && signal_pending(t)) wake_up_process(t); out_nolock: diff -urN 2.2.19pre2/net/ipv4/tcp.c wakeone/net/ipv4/tcp.c --- 2.2.19pre2/net/ipv4/tcp.c Wed Dec 20 03:31:39 2000 +++ wakeone/net/ipv4/tcp.c Wed Dec 20 03:35:34 2000 @@ -1619,10 +1619,9 @@ struct wait_queue wait = { current, NULL }; struct open_request *req; - current->task_exclusive = 1; add_wait_queue(sk->sleep, &wait); for (;;) { - current->state = TASK_INTERRUPTIBLE; + current->state = TASK_INTERRUPTIBLE | TASK_EXCLUSIVE; release_sock(sk); schedule(); lock_sock(sk); @@ -1633,8 +1632,6 @@ break; } current->state = TASK_RUNNING; - wmb(); - current->task_exclusive = 0; remove_wait_queue(sk->sleep, &wait); return req; }