diff options
author | Richard Braun <rbraun@sceen.net> | 2012-09-03 20:29:10 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-11-25 00:29:44 +0100 |
commit | 2531b513b4c3338a69230f273a57f6a7f927b3c8 (patch) | |
tree | 33944d20c52d369ab725af8ffc097f95bd642bea /sysdeps/mach | |
parent | ee750a7cefcb13a88d87a124bb36f8f8a344ecd9 (diff) |
Add Hurd-specific condition wait function
* Makefile (libpthread-routines): Add pt-hurd-cond-wait.
* Versions (libc): Add pthread_hurd_cond_wait_np.
(libpthread): Likewise.
* sysdeps/mach/hurd/bits/pthread-np.h: New file.
* sysdeps/mach/hurd/pt-hurd-cond-wait.c: Likewise.
Diffstat (limited to 'sysdeps/mach')
-rw-r--r-- | sysdeps/mach/hurd/bits/pthread-np.h | 32 | ||||
-rw-r--r-- | sysdeps/mach/hurd/pt-hurd-cond-wait.c | 93 |
2 files changed, 125 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/bits/pthread-np.h b/sysdeps/mach/hurd/bits/pthread-np.h new file mode 100644 index 0000000..9817a06 --- /dev/null +++ b/sysdeps/mach/hurd/bits/pthread-np.h @@ -0,0 +1,32 @@ +/* Non-portable functions. Hurd on Mach version. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * Never include this file directly; use <pthread.h> or <cthreads.h> instead. + */ + +#ifndef _BITS_PTHREAD_NP_H +#define _BITS_PTHREAD_NP_H 1 + +/* Same as pthread_cond_wait, but for Hurd-specific cancellation. + See hurd_thread_cancel. */ +extern int pthread_hurd_cond_wait_np (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +#endif /* bits/pthread-np.h */ diff --git a/sysdeps/mach/hurd/pt-hurd-cond-wait.c b/sysdeps/mach/hurd/pt-hurd-cond-wait.c new file mode 100644 index 0000000..d2b5847 --- /dev/null +++ b/sysdeps/mach/hurd/pt-hurd-cond-wait.c @@ -0,0 +1,93 @@ +/* pthread_hurd_cond_wait. Hurd-specific wait on a condition. + Copyright (C) 2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <pthread.h> +#include <assert.h> +#include <hurd/signal.h> + +#include <pt-internal.h> + +int +pthread_hurd_cond_wait_np (pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + /* This function will be called by hurd_thread_cancel while we are blocked + We wake up all threads blocked on COND, so our thread will wake up and + notice the cancellation flag. */ + void cancel_me (void) + { + pthread_cond_broadcast (cond); + } + struct hurd_sigstate *ss = _hurd_self_sigstate (); + struct __pthread *self = _pthread_self (); + int cancel; + + assert (ss->intr_port == MACH_PORT_NULL); /* Sanity check for signal bugs. */ + + /* Atomically enqueue our thread on the condition variable's queue of + waiters, and mark our sigstate to indicate that `cancel_me' must be + called to wake us up. We must hold the sigstate lock while acquiring + the condition variable's lock and tweaking it, so that + hurd_thread_cancel can never suspend us and then deadlock in + pthread_cond_broadcast waiting for the condition variable's lock. */ + + __spin_lock (&ss->lock); + __pthread_spin_lock (&cond->__lock); + cancel = ss->cancel; + if (cancel) + /* We were cancelled before doing anything. Don't block at all. */ + ss->cancel = 0; + else + { + /* Put us on the queue so that pthread_cond_broadcast will know to wake + us up. */ + __pthread_enqueue (&cond->__queue, self); + /* Tell hurd_thread_cancel how to unblock us. */ + ss->cancel_hook = &cancel_me; + } + __pthread_spin_unlock (&cond->__lock); + __spin_unlock (&ss->lock); + + + if (cancel) + /* Cancelled on entry. Just leave the mutex locked. */ + mutex = NULL; + else + { + /* Now unlock the mutex and block until woken. */ + __pthread_mutex_unlock (mutex); + __pthread_block (self); + } + + __spin_lock (&ss->lock); + /* Clear the hook, now that we are done blocking. */ + ss->cancel_hook = NULL; + /* Check the cancellation flag; we might have unblocked due to + cancellation rather than a normal pthread_cond_signal or + pthread_cond_broadcast (or we might have just happened to get cancelled + right after waking up). */ + cancel |= ss->cancel; + ss->cancel = 0; + __spin_unlock (&ss->lock); + + if (mutex) + /* Reacquire the mutex and return. */ + __pthread_mutex_lock (mutex); + + return cancel; +} |