diff -ur --new-file linux-2.2.14/Makefile linux-2.2.14-taskex/Makefile --- linux-2.2.14/Makefile Wed Mar 22 23:08:43 2000 +++ linux-2.2.14-taskex/Makefile Wed Mar 22 23:11:33 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 14 -EXTRAVERSION = +EXTRAVERSION = -taskex ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -ur --new-file linux-2.2.14/include/linux/sched.h linux-2.2.14-taskex/include/linux/sched.h --- linux-2.2.14/include/linux/sched.h Wed Mar 22 23:13:54 2000 +++ linux-2.2.14-taskex/include/linux/sched.h Wed Mar 22 23:53:21 2000 @@ -79,6 +79,7 @@ #define TASK_ZOMBIE 4 #define TASK_STOPPED 8 #define TASK_SWAPPING 16 +#define TASK_EXCLUSIVE 32 /* * Scheduling policies @@ -686,17 +687,6 @@ extern int do_execve(char *, char **, char **, struct pt_regs *); extern int do_fork(unsigned long, unsigned long, struct pt_regs *); -/* - * The wait-queues are circular lists, and you have to be *very* sure - * to keep them correct. Use only these two functions to add/remove - * entries in the queues. - */ -extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) -{ - wait->next = *p ? : WAIT_QUEUE_HEAD(p); - *p = wait; -} - extern rwlock_t waitqueue_lock; extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) @@ -708,16 +698,13 @@ write_unlock_irqrestore(&waitqueue_lock, flags); } -extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) +extern inline void add_wait_queue_exclusive(struct wait_queue ** p, struct wait_queue * wait) { - struct wait_queue * next = wait->next; - struct wait_queue * head = next; - struct wait_queue * tmp; + unsigned long flags; - while ((tmp = head->next) != wait) { - head = tmp; - } - head->next = next; + write_lock_irqsave(&waitqueue_lock, flags); + __add_wait_queue_tail(p, wait); + write_unlock_irqrestore(&waitqueue_lock, flags); } extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) diff -ur --new-file linux-2.2.14/include/linux/wait.h linux-2.2.14-taskex/include/linux/wait.h --- linux-2.2.14/include/linux/wait.h Wed Mar 22 23:13:54 2000 +++ linux-2.2.14-taskex/include/linux/wait.h Wed Mar 22 23:53:21 2000 @@ -17,6 +17,38 @@ #define WAIT_QUEUE_HEAD(x) ((struct wait_queue *)((x)-1)) +extern inline void __add_wait_queue(struct wait_queue **p, struct wait_queue *wait) +{ + wait->next = *p ? : WAIT_QUEUE_HEAD(p); + *p = wait; + /* list_add(&new->task_list, &head->task_list); */ +} + +extern inline void __add_wait_queue_tail(struct wait_queue **p, struct wait_queue *wait) +{ + struct wait_queue * head = WAIT_QUEUE_HEAD(p); + struct wait_queue * tmp = *p; + + while (tmp->next != head) + tmp = tmp->next; + wait->next = tmp->next; + tmp->next = wait; + /* list_add(&new->task_list, head->task_list.prev); */ +} + +extern inline void __remove_wait_queue(struct wait_queue **p, struct wait_queue *wait) +{ + struct wait_queue * next = wait->next; + struct wait_queue * head = next; + struct wait_queue * tmp; + + while ((tmp = head->next) != wait) { + head = tmp; + } + head->next = next; + /* list_del(&old->task_list); */ +} + static inline void init_waitqueue(struct wait_queue **q) { *q = WAIT_QUEUE_HEAD(q); diff -ur --new-file linux-2.2.14/kernel/sched.c linux-2.2.14-taskex/kernel/sched.c --- linux-2.2.14/kernel/sched.c Wed Mar 22 23:08:23 2000 +++ linux-2.2.14-taskex/kernel/sched.c Wed Mar 22 23:47:30 2000 @@ -899,9 +899,12 @@ goto out_unlock; while (next != head) { + unsigned int state; + p = next->task; next = next->next; - if (p->state & mode) { + state = p->state; + if (state & mode) { /* * We can drop the read-lock early if this * is the only/last process. @@ -912,6 +915,8 @@ goto out; } wake_up_process(p); + if (state & TASK_EXCLUSIVE) + break; } } out_unlock: @@ -1203,8 +1208,8 @@ read_lock(&tasklist_lock); for_each_task(p) { if ((p->state == TASK_RUNNING || - p->state == TASK_UNINTERRUPTIBLE || - p->state == TASK_SWAPPING)) + (p->state == TASK_UNINTERRUPTIBLE) || + (p->state == TASK_SWAPPING))) nr += FIXED_1; } read_unlock(&tasklist_lock); diff -ur --new-file linux-2.2.14/kernel/signal.c linux-2.2.14-taskex/kernel/signal.c --- linux-2.2.14/kernel/signal.c Wed Mar 22 23:08:23 2000 +++ linux-2.2.14-taskex/kernel/signal.c Wed Mar 22 23:48:33 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 -ur --new-file linux-2.2.14/net/core/sock.c linux-2.2.14-taskex/net/core/sock.c --- linux-2.2.14/net/core/sock.c Mon May 10 12:55:25 1999 +++ linux-2.2.14-taskex/net/core/sock.c Wed Mar 22 23:49:48 2000 @@ -1036,7 +1036,8 @@ sk->type = sock->type; sk->sleep = &sock->wait; sock->sk = sk; - } + } else + sk->sleep = NULL; sk->state_change = sock_def_wakeup; sk->data_ready = sock_def_readable; diff -ur --new-file linux-2.2.14/net/ipv4/tcp.c linux-2.2.14-taskex/net/ipv4/tcp.c --- linux-2.2.14/net/ipv4/tcp.c Wed Mar 22 23:08:24 2000 +++ linux-2.2.14-taskex/net/ipv4/tcp.c Wed Mar 22 23:51:20 2000 @@ -1606,9 +1606,9 @@ struct wait_queue wait = { current, NULL }; struct open_request *req; - add_wait_queue(sk->sleep, &wait); + add_wait_queue_exclusive(sk->sleep, &wait); for (;;) { - current->state = TASK_INTERRUPTIBLE; + current->state = TASK_EXCLUSIVE | TASK_INTERRUPTIBLE; release_sock(sk); schedule(); lock_sock(sk);