diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2003-01-02 11:01:30 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2003-01-02 11:01:30 +0000 |
| commit | 05df18c3475157cda8126a07b5bb0f52082a0b67 (patch) | |
| tree | ad9be04821a2ec180444af2c737d104141857206 | |
| parent | caf7a872326ee21ad20698baa62ca5599a46d866 (diff) | |
| download | glibc-05df18c3475157cda8126a07b5bb0f52082a0b67.tar.xz glibc-05df18c3475157cda8126a07b5bb0f52082a0b67.zip | |
Update.
2003-01-02 Ulrich Drepper <drepper@redhat.com>
* sysdeps/pthread/bits/pthreadtypes.h (pthread_cond_t): Add padding.
* condvar.c: Add symbol versioning. The compatibility versions
are the same as the change in the interface does not effect this
implementation.
* Versions [libpthread]: Add definitions for new pthread_cond_*
interfaces for version GLIBC_2.3.2.
| -rw-r--r-- | linuxthreads/ChangeLog | 9 | ||||
| -rw-r--r-- | linuxthreads/Versions | 6 | ||||
| -rw-r--r-- | linuxthreads/condvar.c | 52 | ||||
| -rw-r--r-- | linuxthreads/sysdeps/pthread/bits/pthreadtypes.h | 2 | ||||
| -rw-r--r-- | nptl/ChangeLog | 25 | ||||
| -rw-r--r-- | nptl/DESIGN-condvar.txt | 101 | ||||
| -rw-r--r-- | nptl/Makefile | 5 | ||||
| -rw-r--r-- | nptl/Versions | 5 | ||||
| -rw-r--r-- | nptl/old_pthread_cond_broadcast.c | 46 | ||||
| -rw-r--r-- | nptl/old_pthread_cond_destroy.c | 37 | ||||
| -rw-r--r-- | nptl/old_pthread_cond_init.c | 43 | ||||
| -rw-r--r-- | nptl/old_pthread_cond_signal.c | 46 | ||||
| -rw-r--r-- | nptl/old_pthread_cond_timedwait.c | 48 | ||||
| -rw-r--r-- | nptl/old_pthread_cond_wait.c | 47 | ||||
| -rw-r--r-- | nptl/pthreadP.h | 11 | ||||
| -rw-r--r-- | nptl/pthread_cond_destroy.c | 1 | ||||
| -rw-r--r-- | nptl/pthread_cond_init.c | 5 | ||||
| -rw-r--r-- | nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h | 10 | ||||
| -rw-r--r-- | nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S | 625 |
19 files changed, 941 insertions, 183 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 20ee770f8f..a667e22ede 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,12 @@ +2003-01-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/bits/pthreadtypes.h (pthread_cond_t): Add padding. + * condvar.c: Add symbol versioning. The compatibility versions + are the same as the change in the interface does not effect this + implementation. + * Versions [libpthread]: Add definitions for new pthread_cond_* + interfaces for version GLIBC_2.3.2. + 2002-12-31 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for diff --git a/linuxthreads/Versions b/linuxthreads/Versions index cf7f340f77..8dd40eec28 100644 --- a/linuxthreads/Versions +++ b/linuxthreads/Versions @@ -156,6 +156,12 @@ libpthread { # Cancellation wrapper __nanosleep; } + GLIBC_2.3.2 { + # Changed pthread_cond_t. + pthread_cond_init; pthread_cond_destroy; + pthread_cond_wait; pthread_cond_timedwait; + pthread_cond_signal; pthread_cond_broadcast; + } GLIBC_PRIVATE { # Internal libc interface to libpthread __pthread_kill_other_threads_np; diff --git a/linuxthreads/condvar.c b/linuxthreads/condvar.c index a40ae49fab..6ab95b88ae 100644 --- a/linuxthreads/condvar.c +++ b/linuxthreads/condvar.c @@ -24,6 +24,7 @@ #include "spinlock.h" #include "queue.h" #include "restart.h" +#include <shlib-compat.h> int __pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) @@ -32,14 +33,26 @@ int __pthread_cond_init(pthread_cond_t *cond, cond->__c_waiting = NULL; return 0; } -strong_alias (__pthread_cond_init, pthread_cond_init) +versioned_symbol (libpthread, __pthread_cond_init, pthread_cond_init, + GLIBC_2_3_2); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +strong_alias (__pthread_cond_init, __old_pthread_cond_init) +compat_symbol (libpthread, __old_pthread_cond_init, pthread_cond_init, + GLIBC_2_0); +#endif int __pthread_cond_destroy(pthread_cond_t *cond) { if (cond->__c_waiting != NULL) return EBUSY; return 0; } -strong_alias (__pthread_cond_destroy, pthread_cond_destroy) +versioned_symbol (libpthread, __pthread_cond_destroy, pthread_cond_destroy, + GLIBC_2_3_2); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +strong_alias (__pthread_cond_destroy, __old_pthread_cond_destroy) +compat_symbol (libpthread, __old_pthread_cond_destroy, pthread_cond_destroy, + GLIBC_2_0); +#endif /* Function called by pthread_cancel to remove the thread from waiting on a condition variable queue. */ @@ -134,7 +147,13 @@ int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) pthread_mutex_lock(mutex); return 0; } -strong_alias (__pthread_cond_wait, pthread_cond_wait) +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +strong_alias (__pthread_cond_wait, __old_pthread_cond_wait) +compat_symbol (libpthread, __old_pthread_cond_wait, pthread_cond_wait, + GLIBC_2_0); +#endif static int pthread_cond_timedwait_relative(pthread_cond_t *cond, @@ -230,12 +249,19 @@ pthread_cond_timedwait_relative(pthread_cond_t *cond, return 0; } -int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - const struct timespec * abstime) +int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec * abstime) { /* Indirect call through pointer! */ return pthread_cond_timedwait_relative(cond, mutex, abstime); } +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, + GLIBC_2_3_2); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +strong_alias (__pthread_cond_timedwait, __old_pthread_cond_timedwait) +compat_symbol (libpthread, __old_pthread_cond_timedwait, + pthread_cond_timedwait, GLIBC_2_0); +#endif int __pthread_cond_signal(pthread_cond_t *cond) { @@ -251,7 +277,13 @@ int __pthread_cond_signal(pthread_cond_t *cond) } return 0; } -strong_alias (__pthread_cond_signal, pthread_cond_signal) +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, + GLIBC_2_3_2); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +strong_alias (__pthread_cond_signal, __old_pthread_cond_signal) +compat_symbol (libpthread, __old_pthread_cond_signal, pthread_cond_signal, + GLIBC_2_0); +#endif int __pthread_cond_broadcast(pthread_cond_t *cond) { @@ -270,7 +302,13 @@ int __pthread_cond_broadcast(pthread_cond_t *cond) } return 0; } -strong_alias (__pthread_cond_broadcast, pthread_cond_broadcast) +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, + GLIBC_2_3_2); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +strong_alias (__pthread_cond_broadcast, __old_pthread_cond_broadcast) +compat_symbol (libpthread, __old_pthread_cond_broadcast, + pthread_cond_broadcast, GLIBC_2_0); +#endif int __pthread_condattr_init(pthread_condattr_t *attr) { diff --git a/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h index 3ee5c48134..43d4f7dc00 100644 --- a/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h +++ b/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h @@ -57,6 +57,8 @@ typedef struct { struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ _pthread_descr __c_waiting; /* Threads waiting on this condition */ + char __padding[48 - sizeof (struct _pthread_fastlock) + - sizeof (_pthread_descr)]; } pthread_cond_t; diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 764ab23cd9..ec44dffa21 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,28 @@ +2003-01-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + New, larger type definition. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: New condvar + implementation. + * Versions [libpthread]: Add definitions for new pthread_cond_* + interfaces for version GLIBC_2.3.2. + * pthread_cond_init.c: Update initialization for new type definition. + * Makefile (libpthread-routines): Remove pthread_cond_wait, + pthread_cond_timedwait, pthread_cond_signal, and + pthread_cond_broadcast. Add old_pthread_cond_init, + old_pthread_cond_destroy, old_pthread_cond_wait, + old_pthread_cond_timedwait, old_pthread_cond_signal, and + old_pthread_cond_broadcast. + * old_pthread_cond_broadcast.c: New file. + * old_pthread_cond_destroy.c: New file. + * old_pthread_cond_init.c: New file. + * old_pthread_cond_signal.c: New file. + * old_pthread_cond_timedwait.c: New file. + * old_pthread_cond_wait.c: New file. + * pthreadP.h: Add prototypes for the compatibility interfaces. + + * pthread_cond_destroy.c: Don't include <errno.h>. + 2003-01-01 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Avoid diff --git a/nptl/DESIGN-condvar.txt b/nptl/DESIGN-condvar.txt index 303807be6d..749180ed4b 100644 --- a/nptl/DESIGN-condvar.txt +++ b/nptl/DESIGN-condvar.txt @@ -7,49 +7,78 @@ Conditional Variable pseudocode. struct pthread_cond_t { - unsigned int lock: + unsigned int cond_lock; internal mutex - unsigned int nr_wakers: + uint64_t total_seq; - number of threads signalled to be woken up. + Total number of threads using the conditional variable. - unsigned int nr_sleepers: + uint64_t wakeup_seq; - number of threads waiting for the cv. + sequence number for next wakeup. + + uint64_t woken_seq; + + sequence number of last woken thread. } -#define ALL_THREADS (1 << (BITS_PER_LONG-1)) -cond_wait_timeout(cv, mutex, timeout): + +cleanup_handler(cv) +{ + lll_lock(cv->lock); + + ++cv->wakeup_seq; + ++cv->woken_seq; + + lll_unlock(cv->lock); +} + + +cond_timedwait(cv, mutex, timeout): { lll_lock(cv->lock); mutex_unlock(mutex); - cv->nr_sleepers++; - for (;;) { + cleanup_push + + ++cv->total_seq; + val = seq = cv->wakeup_seq; + + while (1) { + + lll_unlock(cv->lock); + + enable_async - if (cv->nr_wakers) { - cv->nr_wakers--; - break; - } - val = cv->nr_wakers; + ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); - lll_unlock(cv->lock); + restore_async - ret = FUTEX WAIT (cv->nr_wakers, val, timeout) + lll_lock(cv->lock); - lll_lock(cv->lock); + val = cv->wakeup_seq; - if (ret == TIMEOUT) - break; + if (cv->woken_seq >= seq && cv->woken_seq < val) { ret = 0; + break; + } + + if (ret == TIMEDOUT) { + ++cv->wakeup_seq; + break; + } } - if (!--cv->nr_sleepers) - cv->nr_wakers = 0; /* no memory of wakeups */ + + ++cv->woken_seq; + lll_unlock(cv->lock); + + cleanup_pop + mutex_lock(mutex); return ret; @@ -57,34 +86,24 @@ cond_wait_timeout(cv, mutex, timeout): cond_signal(cv) { - int do_wakeup = 0; - lll_lock(cv->lock); - if (cv->nr_sleepers) { - if (!++cv->nr_wakers) /* overflow detection for the nutcase */ - cv->nr_wakers = ALL_THREADS; - do_wakeup = 1; + + if (cv->total_seq > cv->wakeup_seq) { + ++cv->wakeup_seq; + FUTEX_WAKE(cv->wakeup_seq, 1); } + lll_unlock(cv->lock); - if (do_wakeup) - FUTEX WAKE (cv->nr_wakers, 1) } cond_broadcast(cv) { - int do_wakeup = 0; - lll_lock(cv->lock); - if (cv->nr_sleepers) { - cv->nr_wakers |= ALL_THREADS; - do_wakeup = 1; + + if (cv->total_seq > cv->wakeup_seq) { + cv->wakeup_seq = cv->total_seq; + FUTEX_WAKE(cv->wakeup_seq, ALL); } + lll_unlock(cv->lock); - if (do_wakeup) - FUTEX WAKE (cv->nr_wakers, ALL_THREADS); } - -weaknesses of the implementation: - - it might generate spurious wakeups in the broadcast case, but those are - allowed by POSIX. diff --git a/nptl/Makefile b/nptl/Makefile index f1aaf48475..274b1b2930 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -65,8 +65,9 @@ libpthread-routines = init events \ pthread_rwlockattr_getkind_np \ pthread_rwlockattr_setkind_np \ pthread_cond_init pthread_cond_destroy \ - pthread_cond_wait pthread_cond_timedwait \ - pthread_cond_signal pthread_cond_broadcast \ + old_pthread_cond_init old_pthread_cond_destroy \ + old_pthread_cond_wait old_pthread_cond_timedwait \ + old_pthread_cond_signal old_pthread_cond_broadcast \ pthread_condattr_init pthread_condattr_destroy \ pthread_condattr_getpshared pthread_condattr_setpshared \ pthread_spin_init pthread_spin_destroy \ diff --git a/nptl/Versions b/nptl/Versions index b9de74afd9..26655f37c1 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -186,6 +186,11 @@ libpthread { } GLIBC_2.3.2 { + # Changed pthread_cond_t. + pthread_cond_init; pthread_cond_destroy; + pthread_cond_wait; pthread_cond_timedwait; + pthread_cond_signal; pthread_cond_broadcast; + # Proposed API extensions. # XXX Adjust number for final release. pthread_tryjoin_np; pthread_timedjoin_np; diff --git a/nptl/old_pthread_cond_broadcast.c b/nptl/old_pthread_cond_broadcast.c new file mode 100644 index 0000000000..9d63af9a1d --- /dev/null +++ b/nptl/old_pthread_cond_broadcast.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__old_pthread_cond_broadcast (cond) + pthread_cond_t *cond; +{ + pthread_cond_t **realp = (pthread_cond_t **) cond; + + if (*realp == NULL) + { + *realp = (pthread_cond_t *) malloc (sizeof (pthread_cond_t)); + if (*realp == NULL) + return ENOMEM; + + **realp = (struct pthread_cond_t) PTHREAD_COND_INITIALIZER; + } + + return __pthread_cond_broadcast (*realp); +} +compat_symbol (libpthread, __old_pthread_cond_broadcast, + pthread_cond_broadcast, GLIBC_2_0); +#endif diff --git a/nptl/old_pthread_cond_destroy.c b/nptl/old_pthread_cond_destroy.c new file mode 100644 index 0000000000..9afe7d323b --- /dev/null +++ b/nptl/old_pthread_cond_destroy.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__old_pthread_cond_destroy (cond) + pthread_cond_t *cond; +{ + /* Free the memory which was eventually allocated. */ + free (*(void **) cond); + + return 0; +} +compat_symbol (libpthread, __old_pthread_cond_destroy, pthread_cond_destroy, + GLIBC_2_0); +#endif diff --git a/nptl/old_pthread_cond_init.c b/nptl/old_pthread_cond_init.c new file mode 100644 index 0000000000..70275d94df --- /dev/null +++ b/nptl/old_pthread_cond_init.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__old_pthread_cond_init (cond, cond_attr) + pthread_cond_t *cond; + const pthread_condattr_t *cond_attr; +{ + /* Note that we don't need the COND-ATTR. It contains only the + PSHARED flag which is unimportant here since conditional + variables are always usable in multiple processes. */ + + /* The type of the first argument is actually that of the old, too + small pthread_cond_t. We use only the first word of it, as a + pointer. */ + *((void **) cond) = NULL; + + return 0; +} +compat_symbol (libpthread, __old_pthread_cond_init, pthread_cond_init, + GLIBC_2_0); +#endif diff --git a/nptl/old_pthread_cond_signal.c b/nptl/old_pthread_cond_signal.c new file mode 100644 index 0000000000..467812eb4b --- /dev/null +++ b/nptl/old_pthread_cond_signal.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <shlib-compat.h> + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2) +int +__old_pthread_cond_signal (cond) + pthread_cond_t *cond; +{ + pthread_cond_t **realp = (pthread_cond_t **) cond; + + if (*realp == NULL) + { + *realp = (pthread_cond_t *) malloc (sizeof (pthr |
