summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hurd/ChangeLog9
-rw-r--r--hurd/futex.h17
-rw-r--r--hurd/mutex.h12
-rw-r--r--libpthread/sysdeps/generic/pt-mutex-unlock.c7
-rw-r--r--viengoos/ChangeLog14
-rw-r--r--viengoos/object.c5
-rw-r--r--viengoos/server.c15
-rw-r--r--viengoos/thread.h14
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. */