diff -urN wake-one-ref/include/linux/sched.h wake-one/include/linux/sched.h --- wake-one-ref/include/linux/sched.h Sun Dec 24 17:07:38 2000 +++ wake-one/include/linux/sched.h Sun Dec 24 17:07:55 2000 @@ -79,7 +79,6 @@ #define TASK_ZOMBIE 4 #define TASK_STOPPED 8 #define TASK_SWAPPING 16 -#define TASK_EXCLUSIVE 32 /* * Scheduling policies @@ -263,7 +262,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; @@ -386,7 +384,6 @@ /* counter */ DEF_PRIORITY,DEF_PRIORITY,0,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, \ @@ -504,17 +501,19 @@ #define CURRENT_TIME (xtime.tv_sec) -extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode)); +extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode, unsigned int wq_mode)); extern void FASTCALL(sleep_on(struct wait_queue ** p)); extern long FASTCALL(sleep_on_timeout(struct wait_queue ** p, signed long timeout)); extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p)); extern long FASTCALL(interruptible_sleep_on_timeout(struct wait_queue ** p, signed long timeout)); -extern void FASTCALL(wake_up_process(struct task_struct * tsk)); +extern int 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, WQ_FLAG_EXCLUSIVE) +#define wake_up_all(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0) +#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE, WQ_FLAG_EXCLUSIVE) +#define wake_up_interruptible_all(x) __wake_up((x),TASK_INTERRUPTIBLE, 0) #define __set_current_state(state_value) do { current->state = state_value; } while (0) #ifdef __SMP__ @@ -736,6 +735,17 @@ { unsigned long flags; + wait->flags = 0; + write_lock_irqsave(&waitqueue_lock, flags); + __add_wait_queue(p, wait); + write_unlock_irqrestore(&waitqueue_lock, flags); +} + +extern inline void add_wait_queue_exclusive(struct wait_queue ** p, struct wait_queue * wait) +{ + unsigned long flags; + + wait->flags = WQ_FLAG_EXCLUSIVE; write_lock_irqsave(&waitqueue_lock, flags); __add_wait_queue(p, wait); write_unlock_irqrestore(&waitqueue_lock, flags); diff -urN wake-one-ref/include/linux/wait.h wake-one/include/linux/wait.h --- wake-one-ref/include/linux/wait.h Fri Dec 22 19:24:23 2000 +++ wake-one/include/linux/wait.h Sun Dec 24 17:07:55 2000 @@ -13,6 +13,8 @@ struct wait_queue { struct task_struct * task; struct wait_queue * next; + int flags; +#define WQ_FLAG_EXCLUSIVE 0x01 }; typedef struct wait_queue wait_queue_t; diff -urN wake-one-ref/kernel/sched.c wake-one/kernel/sched.c --- wake-one-ref/kernel/sched.c Sun Dec 24 17:07:38 2000 +++ wake-one/kernel/sched.c Sun Dec 24 17:08:21 2000 @@ -398,7 +398,7 @@ * "current->state = TASK_RUNNING" to mark yourself runnable * without the overhead of this. */ -void wake_up_process(struct task_struct * p) +int wake_up_process(struct task_struct * p) { unsigned long flags; @@ -412,9 +412,10 @@ add_to_runqueue(p); reschedule_idle(p, flags); // spin_unlocks runqueue - return; + return 1; out: spin_unlock_irqrestore(&runqueue_lock, flags); + return 0; } static void process_timeout(unsigned long __data) @@ -850,11 +851,11 @@ * have to protect against interrupts), as the actual removal from the * queue is handled by the process itself. */ -void __wake_up(struct wait_queue **q, unsigned int mode) +void __wake_up(struct wait_queue **q, unsigned int mode, unsigned int wq_mode) { - struct task_struct *p, *best_exclusive; + struct task_struct *p; struct wait_queue *head, *next; - unsigned int do_exclusive; + int wake_one = 0, flags; if (!q) goto out; @@ -869,23 +870,21 @@ if (!next) goto out_unlock; - best_exclusive = 0; - do_exclusive = mode & TASK_EXCLUSIVE; while (next != head) { p = next->task; + flags = next->flags; next = next->next; if (p->state & mode) { - if (do_exclusive && p->task_exclusive) { - if (best_exclusive == NULL) - best_exclusive = p; - } - else { + if (!(flags & wq_mode & WQ_FLAG_EXCLUSIVE)) wake_up_process(p); + else { + if (wake_one) + continue; + if (wake_up_process(p)) + wake_one = 1; } } } - if (best_exclusive) - wake_up_process(best_exclusive); out_unlock: read_unlock(&waitqueue_lock); out: diff -urN wake-one-ref/net/ipv4/tcp.c wake-one/net/ipv4/tcp.c --- wake-one-ref/net/ipv4/tcp.c Sun Dec 24 17:07:38 2000 +++ wake-one/net/ipv4/tcp.c Sun Dec 24 17:07:55 2000 @@ -1619,8 +1619,7 @@ struct wait_queue wait = { current, NULL }; struct open_request *req; - current->task_exclusive = 1; - add_wait_queue(sk->sleep, &wait); + add_wait_queue_exclusive(sk->sleep, &wait); for (;;) { current->state = TASK_INTERRUPTIBLE; release_sock(sk); @@ -1633,8 +1632,6 @@ break; } current->state = TASK_RUNNING; - wmb(); - current->task_exclusive = 0; remove_wait_queue(sk->sleep, &wait); return req; }