diff -rNu linux-O6/kernel/futex.c linux-O7/kernel/futex.c --- linux-O6/kernel/futex.c 2003-02-11 10:38:52.000000000 +0100 +++ linux-O7/kernel/futex.c 2003-02-11 10:39:11.000000000 +0100 @@ -58,6 +58,47 @@ static struct list_head futex_queues[1<pid, (int *)uaddr, uval, len, args); +#define FPRINT(format,uaddr, uval, len, args...) \ + if (unlikely(futex_debug)) \ + __FPRINT(format,uaddr,uval,len,args); + +#define __FDEBUG(format,args...) \ +do { \ + unsigned int uval; \ + if (likely(!futex_debug)) \ + break; \ + if (get_user(uval, (int *)uaddr)) \ + uval = -EFAULT; \ + __FPRINT(format,uaddr,uval,list_len(head),args); \ +} while (0) + +#define FDEBUG(format,args...) \ +do { \ + if (likely(!futex_debug)) \ + break; \ + spin_lock(&futex_lock); \ + __FDEBUG(format,args); \ + spin_unlock(&futex_lock); \ +} while (0) + +int futex_debug; + /* * These are all locks that are necessery to look up a physical * mapping safely, and modify/search the futex hash, atomically: @@ -145,6 +186,22 @@ put_page(page); } +static int futex_pid (struct futex_q *q) +{ + task_t *p; + struct list_head *tmp; + + if (!q) + return -1; + tmp = q->waiters.task_list.next; + if (!tmp || list_empty(tmp)) + return -1; + p = list_entry(q->waiters.task_list.next, wait_queue_t,task_list)->task; + if (!p) + return -1; + return p->pid; +} + /* * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: @@ -170,6 +227,7 @@ if (this->page == page && this->offset == offset) { list_del_init(i); + __FDEBUG(" WAKING %d.", futex_pid(this)); __detach_vcache(&this->vcache); tell_waiter(this); ret++; @@ -177,9 +235,9 @@ break; } } - unlock_futex_mm(); unpin_page(page); + FDEBUG(" WOKE: %d.", ret); return ret; } @@ -220,31 +278,38 @@ * to make sure a COW properly rehashes the futex-queue. */ __attach_vcache(&q->vcache, uaddr, current->mm, futex_vcache_callback); + __FDEBUG("%s", " QUEUED"); } /* Return 1 if we were still queued (ie. 0 means we were woken) */ -static inline int unqueue_me(struct futex_q *q) +static inline int unqueue_me(struct futex_q *q, void *uaddr) { + struct list_head *head; int ret = 0; spin_lock(&vcache_lock); spin_lock(&futex_lock); + head = q->list.next; if (!list_empty(&q->list)) { list_del(&q->list); __detach_vcache(&q->vcache); ret = 1; } + __FDEBUG("%s", " UNQUEUED"); spin_unlock(&futex_lock); spin_unlock(&vcache_lock); return ret; } +#define time_val(time) (time == 2147483647 ? -1 : time) + static int futex_wait(unsigned long uaddr, int offset, int val, unsigned long time) { DECLARE_WAITQUEUE(wait, current); + struct list_head *head; int ret = 0, curval; struct page *page; struct futex_q q; @@ -267,7 +332,10 @@ ret = -EFAULT; goto out; } + + head = &q.list; if (curval != val) { + FDEBUG(" CHANGE: %d != %d", curval, val); ret = -EWOULDBLOCK; goto out; } @@ -280,8 +348,12 @@ */ add_wait_queue(&q.waiters, &wait); set_current_state(TASK_INTERRUPTIBLE); - if (!list_empty(&q.list)) + if (!list_empty(&q.list)) { + FDEBUG(" ==> AWAY, t:%ld, %d == %d", time_val(time), curval, val); time = schedule_timeout(time); + FDEBUG(" <== BACK, t:%ld, sig:%d", time_val(time), signal_pending(current)); + } + set_current_state(TASK_RUNNING); /* * NOTE: we dont remove ourselves from the waitqueue because @@ -295,7 +367,7 @@ ret = -EINTR; out: /* Were we woken up anyway? */ - if (!unqueue_me(&q)) + if (!unqueue_me(&q, (void *)uaddr)) ret = 0; unpin_page(page); @@ -330,6 +402,8 @@ if (pos_in_page % sizeof(int)) return -EINVAL; + FPRINT("ENTER SYS op:%d, v:%d", uaddr, val, -1, op, val); + switch (op) { case FUTEX_WAIT: ret = futex_wait_utime(uaddr, pos_in_page, val, utime); @@ -351,6 +425,7 @@ default: ret = -EINVAL; } + FPRINT("EXIT SYS op:%d, v:%d, ret:%d", uaddr, val, -1, op, val, ret); return ret; } diff -rNu linux-O6/kernel/sysctl.c linux-O7/kernel/sysctl.c --- linux-O6/kernel/sysctl.c 2003-02-11 10:38:52.000000000 +0100 +++ linux-O7/kernel/sysctl.c 2003-02-11 10:39:11.000000000 +0100 @@ -42,6 +42,7 @@ /* External variables not in a header file. */ extern int panic_timeout; extern int print_fatal_signals; +extern int futex_debug; extern int C_A_D; extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern int sysctl_overcommit_memory; @@ -177,6 +178,8 @@ 0644, NULL, &proc_dointvec}, {KERN_PANIC, "print_fatal_signals", &print_fatal_signals, sizeof(int), 0644, NULL, &proc_dointvec}, + {KERN_PANIC, "futex_debug", &futex_debug, sizeof(int), + 0644, NULL, &proc_dointvec}, {KERN_CORE_USES_PID, "core_uses_pid", &core_uses_pid, sizeof(int), 0644, NULL, &proc_dointvec}, {KERN_CORE_PATTERN, "core_pattern", core_pattern, 64,