diff options
-rw-r--r-- | hurd/ChangeLog | 9 | ||||
-rw-r--r-- | hurd/futex.h | 17 | ||||
-rw-r--r-- | hurd/mutex.h | 12 | ||||
-rw-r--r-- | libpthread/sysdeps/generic/pt-mutex-unlock.c | 7 | ||||
-rw-r--r-- | viengoos/ChangeLog | 14 | ||||
-rw-r--r-- | viengoos/object.c | 5 | ||||
-rw-r--r-- | viengoos/server.c | 15 | ||||
-rw-r--r-- | viengoos/thread.h | 14 |
8 files changed, 87 insertions, 6 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog index e09ea21..4ff7d2d 100644 --- a/hurd/ChangeLog +++ b/hurd/ChangeLog @@ -1,5 +1,14 @@ 2008-06-22 Neal H. Walfield <neal@gnu.org> + * futex.h [! RM_INTERN]: Include <errno.h>. + (futex_wait): On error, set ERRNO and return -1. + (futex_timed_wait): Likewise. + (futex_wake): Likewise. + * mutex.h (ss_mutex_lock): If FUTEX_WAIT returns failure, print + some debugging information. + +2008-06-22 Neal H. Walfield <neal@gnu.org> + * lock.h (SS_MUTEX_LOCK, SS_MUTEX_LOCK_WAIT, SS_MUTEX_UNLOCK, SS_MUTEX_TRYLOCK, SS_MUTEX_TRYLOCK_BLOCKED, SS_RMUTEX_LOCK, SS_RMUTEX_LOCK_INC, SS_RMUTEX_LOCK_WAIT, SS_RMUTEX_UNLOCK, diff --git a/hurd/futex.h b/hurd/futex.h index 5910212..8c4507c 100644 --- a/hurd/futex.h +++ b/hurd/futex.h @@ -116,6 +116,8 @@ RPC (futex, 8, 1, #undef RPC_TARGET #ifndef RM_INTERN +#include <errno.h> + struct futex_return { error_t err; @@ -149,7 +151,10 @@ futex_wait (int *f, int val) struct futex_return ret; ret = futex (f, FUTEX_WAIT, val, NULL, 0, 0); if (ret.err) - return 0; + { + errno = ret.err; + return -1; + } return ret.ret; } @@ -160,7 +165,10 @@ futex_timed_wait (int *f, int val, struct timespec *timespec) struct futex_return ret; ret = futex (f, FUTEX_WAIT, val, timespec, 0, 0); if (ret.err) - return 0; + { + errno = ret.err; + return -1; + } return ret.ret; } @@ -171,7 +179,10 @@ futex_wake (int *f, int nwake) struct futex_return ret; ret = futex (f, FUTEX_WAKE, nwake, NULL, 0, 0); if (ret.err) - return 0; + { + errno = ret.err; + return -1; + } return ret.ret; } #endif /* !RM_INTERN */ diff --git a/hurd/mutex.h b/hurd/mutex.h index 3f50934..f1aee64 100644 --- a/hurd/mutex.h +++ b/hurd/mutex.h @@ -68,7 +68,17 @@ ss_mutex_lock (__const char *caller, int line, ss_mutex_t *lockp) /* Try to sleep but only if LOCKP is _MUTEX_WAITERS. */ while (c != _MUTEX_UNLOCKED) { - futex_wait (lockp, _MUTEX_WAITERS); + if (futex_wait (lockp, _MUTEX_WAITERS) == -1) + { + debug (0, "Possible deadlock: %p!", lockp); + extern int backtrace (void **array, int size); + void *a[20]; + int c = backtrace (a, sizeof (a) / sizeof (a[0])); + int i; + for (i = 0; i < c; i ++) + debug (0, "%p", a[i]); + ss_lock_trace_dump (lockp); + } c = atomic_exchange_acq (lockp, _MUTEX_WAITERS); } } diff --git a/libpthread/sysdeps/generic/pt-mutex-unlock.c b/libpthread/sysdeps/generic/pt-mutex-unlock.c index 492dfcb..d2a4257 100644 --- a/libpthread/sysdeps/generic/pt-mutex-unlock.c +++ b/libpthread/sysdeps/generic/pt-mutex-unlock.c @@ -37,7 +37,12 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex) if (_pthread_self ()) { assert (mutex->owner); - assert (mutex->owner == _pthread_self ()); + assertx (mutex->owner == _pthread_self (), + "%p(%x) != %p(%x)", + mutex->owner, + ((struct __pthread *) mutex->owner)->threadid, + _pthread_self (), + _pthread_self ()->threadid); mutex->owner = NULL; } #endif diff --git a/viengoos/ChangeLog b/viengoos/ChangeLog index 803ad60..d1b39b3 100644 --- a/viengoos/ChangeLog +++ b/viengoos/ChangeLog @@ -1,3 +1,17 @@ +2008-06-22 Neal H. Walfield <neal@gnu.org> + + * thread.h: Include "list.h". + (struct thread) [! NDEBUG]: Add field futex_waiter_node. + [! NDEBUG]: Instantiate the futex_waiter list class. + (futex_waiters) [! NDEBUG]: Declare. + * server.c (futex_waiters) [! NDEBUG]: New variable. + (server_loop) [! NDEBUG]: If we don't get an RPC for a while, + dequeue all thread's enqueued on FUTEX_WAITERS and return EDEADLK. + When blocking a thread on a futex, add THREAD to FUTEX_WAITERS. + * object.c (object_wait_queue_dequeue) [! NDEBUG]: If + THREAD->WAIT_REASON is THREAD_WAIT_FUTEX, unlink THREAD from + FUTEX_WAITERS. + 2008-06-20 Neal H. Walfield <neal@gnu.org> * profile.c: New file. diff --git a/viengoos/object.c b/viengoos/object.c index 7a9eb24..6c458a8 100644 --- a/viengoos/object.c +++ b/viengoos/object.c @@ -1096,5 +1096,10 @@ object_wait_queue_dequeue (struct activity *activity, struct thread *thread) thread->wait_queue_p = false; +#ifndef NDEBUG + if (thread->wait_reason == THREAD_WAIT_FUTEX) + futex_waiter_list_unlink (&futex_waiters, thread); +#endif + object_wait_queue_check (activity, thread); } diff --git a/viengoos/server.c b/viengoos/server.c index 99d5ed1..91cd939 100644 --- a/viengoos/server.c +++ b/viengoos/server.c @@ -42,6 +42,10 @@ #include "profile.h" #ifndef NDEBUG +struct futex_waiter_list futex_waiters; +#endif + +#ifndef NDEBUG struct trace_buffer rpc_trace = TRACE_BUFFER_INIT ("rpcs", 0, false, false, false); @@ -130,6 +134,13 @@ server_loop (void) any message in the last few seconds. Perhaps there is a dead-lock. Dump the rpc trace. */ { + struct thread *thread; + while ((thread = futex_waiter_list_head (&futex_waiters))) + { + object_wait_queue_dequeue (root_activity, thread); + rpc_error_reply (thread->tid, EDEADLK); + } + trace_buffer_dump (&rpc_trace, 0); rpc_trace_just_dumped = true; } @@ -1452,6 +1463,10 @@ server_loop (void) object_wait_queue_enqueue (principal, object1, thread); +#ifndef NDEBUG + futex_waiter_list_queue (&futex_waiters, thread); +#endif + /* Don't reply. */ do_reply = 0; break; diff --git a/viengoos/thread.h b/viengoos/thread.h index 7ce235f..2d6cb63 100644 --- a/viengoos/thread.h +++ b/viengoos/thread.h @@ -1,5 +1,5 @@ /* thread.h - Thread object interface. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. Written by Neal H. Walfield <neal@gnu.org>. This file is part of the GNU Hurd. @@ -24,6 +24,8 @@ #include <l4.h> #include <errno.h> +#include "list.h" + /* Forward. */ struct folio; struct activity; @@ -107,8 +109,18 @@ struct thread oid_t next; oid_t prev; } wait_queue; + +#ifndef NDEBUG + struct list_node futex_waiter_node; +#endif }; +#ifndef NDEBUG +LIST_CLASS(futex_waiter, struct thread, futex_waiter_node, true) +/* List of threads waiting on a futex. */ +extern struct futex_waiter_list futex_waiters; +#endif + /* The hardwired base of the UTCB (2.5GB). */ #define UTCB_AREA_BASE (0xA0000000) /* The size of the UTCB. */ |