summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-02-27 18:13:05 +0000
committerEric Andersen <andersen@codepoet.org>2003-02-27 18:13:05 +0000
commit187dd78d7bd1c03fcf16e54a30314512d38e1a4a (patch)
tree9780638e5286b40da74a128c9f540a9ea720862f
parentd4d6e2c50565da18253cd0d6f3332484142b6587 (diff)
Major update for pthreads, based in large part on improvements
from glibc 2.3. This should make threads much more efficient. -Erik
-rw-r--r--include/semaphore.h36
-rw-r--r--libc/sysdeps/linux/common/bits/initspin.h15
-rw-r--r--libc/sysdeps/linux/common/bits/pthreadtypes.h4
-rw-r--r--libpthread/Makefile4
-rw-r--r--libpthread/linuxthreads/condvar.c308
-rw-r--r--libpthread/linuxthreads/internals.h37
-rw-r--r--libpthread/linuxthreads/join.c18
-rw-r--r--libpthread/linuxthreads/manager.c100
-rw-r--r--libpthread/linuxthreads/mutex.c216
-rw-r--r--libpthread/linuxthreads/pthread.c416
-rw-r--r--libpthread/linuxthreads/restart.h26
-rw-r--r--libpthread/linuxthreads/semaphore.c159
-rw-r--r--libpthread/linuxthreads/semaphore.h36
-rw-r--r--libpthread/linuxthreads/signals.c3
-rw-r--r--libpthread/linuxthreads/spinlock.c616
-rw-r--r--libpthread/linuxthreads/spinlock.h132
-rw-r--r--libpthread/linuxthreads/sysdeps/alpha/pt-machine.h45
-rw-r--r--libpthread/linuxthreads/sysdeps/alpha/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/pt-machine.h19
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/sigcontextinfo.h75
-rw-r--r--libpthread/linuxthreads/sysdeps/arm/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/cris/pt-machine.h20
-rw-r--r--libpthread/linuxthreads/sysdeps/cris/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h38
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/pt-machine.h27
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/sigcontextinfo.h45
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/tls.h183
-rw-r--r--libpthread/linuxthreads/sysdeps/i386/useldt.h213
-rw-r--r--libpthread/linuxthreads/sysdeps/m68k/pt-machine.h27
-rw-r--r--libpthread/linuxthreads/sysdeps/m68k/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/mips/pt-machine.h111
-rw-r--r--libpthread/linuxthreads/sysdeps/mips/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h82
-rw-r--r--libpthread/linuxthreads/sysdeps/powerpc/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h327
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h35
-rw-r--r--libpthread/linuxthreads/sysdeps/pthread/tls.h81
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/pt-machine.h33
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/stackinfo.h28
-rw-r--r--libpthread/linuxthreads/sysdeps/sh/tls.h115
-rw-r--r--libpthread/linuxthreads/sysdeps/sparc/stackinfo.h28
-rw-r--r--libpthread/linuxthreads_db/Banner1
-rw-r--r--libpthread/linuxthreads_db/ChangeLog190
-rw-r--r--libpthread/linuxthreads_db/Makefile27
-rw-r--r--libpthread/linuxthreads_db/Versions6
-rw-r--r--libpthread/linuxthreads_db/proc_service.h16
-rw-r--r--libpthread/linuxthreads_db/td_init.c4
-rw-r--r--libpthread/linuxthreads_db/td_log.c6
-rw-r--r--libpthread/linuxthreads_db/td_symbol_list.c40
-rw-r--r--libpthread/linuxthreads_db/td_ta_clear_event.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_delete.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_enable_stats.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_event_addr.c2
-rw-r--r--libpthread/linuxthreads_db/td_ta_event_getmsg.c5
-rw-r--r--libpthread/linuxthreads_db/td_ta_get_nthreads.c2
-rw-r--r--libpthread/linuxthreads_db/td_ta_get_ph.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_get_stats.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_map_id2thr.c19
-rw-r--r--libpthread/linuxthreads_db/td_ta_map_lwp2thr.c16
-rw-r--r--libpthread/linuxthreads_db/td_ta_new.c18
-rw-r--r--libpthread/linuxthreads_db/td_ta_reset_stats.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_set_event.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_setconcurrency.c4
-rw-r--r--libpthread/linuxthreads_db/td_ta_thr_iter.c36
-rw-r--r--libpthread/linuxthreads_db/td_ta_tsd_iter.c5
-rw-r--r--libpthread/linuxthreads_db/td_thr_clear_event.c9
-rw-r--r--libpthread/linuxthreads_db/td_thr_dbresume.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_dbsuspend.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_event_enable.c22
-rw-r--r--libpthread/linuxthreads_db/td_thr_event_getmsg.c9
-rw-r--r--libpthread/linuxthreads_db/td_thr_get_info.c21
-rw-r--r--libpthread/linuxthreads_db/td_thr_getfpregs.c8
-rw-r--r--libpthread/linuxthreads_db/td_thr_getgregs.c9
-rw-r--r--libpthread/linuxthreads_db/td_thr_getxregs.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_getxregsize.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_set_event.c9
-rw-r--r--libpthread/linuxthreads_db/td_thr_setfpregs.c9
-rw-r--r--libpthread/linuxthreads_db/td_thr_setgregs.c9
-rw-r--r--libpthread/linuxthreads_db/td_thr_setprio.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_setsigpending.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_setxregs.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_sigsetmask.c4
-rw-r--r--libpthread/linuxthreads_db/td_thr_tls_get_addr.c70
-rw-r--r--libpthread/linuxthreads_db/td_thr_tsd.c12
-rw-r--r--libpthread/linuxthreads_db/td_thr_validate.c21
-rw-r--r--libpthread/linuxthreads_db/thread_db.h37
-rw-r--r--libpthread/linuxthreads_db/thread_dbP.h5
88 files changed, 3644 insertions, 917 deletions
diff --git a/include/semaphore.h b/include/semaphore.h
index 84742233b..9c283c864 100644
--- a/include/semaphore.h
+++ b/include/semaphore.h
@@ -17,6 +17,10 @@
#include <features.h>
#include <sys/types.h>
+#ifdef __USE_XOPEN2K
+# define __need_timespec
+# include <time.h>
+#endif
#ifndef _PTHREAD_DESCR_DEFINED
/* Thread descriptors. Needed for `sem_t' definition. */
@@ -27,11 +31,7 @@ typedef struct _pthread_descr_struct *_pthread_descr;
/* System specific semaphore definition. */
typedef struct
{
- struct
- {
- long int status;
- int spinlock;
- } __sem_lock;
+ struct _pthread_fastlock __sem_lock;
int __sem_value;
_pthread_descr __sem_waiting;
} sem_t;
@@ -49,31 +49,39 @@ __BEGIN_DECLS
/* Initialize semaphore object SEM to VALUE. If PSHARED then share it
with other processes. */
-extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
+extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW;
/* Free resources associated with semaphore object SEM. */
-extern int sem_destroy __P ((sem_t *__sem));
+extern int sem_destroy (sem_t *__sem) __THROW;
/* Open a named semaphore NAME with open flaot OFLAG. */
-extern sem_t *sem_open __P ((__const char *__name, int __oflag, ...));
+extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW;
/* Close descriptor for named semaphore SEM. */
-extern int sem_close __P ((sem_t *__sem));
+extern int sem_close (sem_t *__sem) __THROW;
/* Remove named semaphore NAME. */
-extern int sem_unlink __P ((__const char *__name));
+extern int sem_unlink (__const char *__name) __THROW;
/* Wait for SEM being posted. */
-extern int sem_wait __P ((sem_t *__sem));
+extern int sem_wait (sem_t *__sem) __THROW;
+
+#ifdef __USE_XOPEN2K
+/* Similar to `sem_wait' but wait only until ABSTIME. */
+extern int sem_timedwait (sem_t *__restrict __sem,
+ __const struct timespec *__restrict __abstime)
+ __THROW;
+#endif
/* Test whether SEM is posted. */
-extern int sem_trywait __P ((sem_t *__sem));
+extern int sem_trywait (sem_t *__sem) __THROW;
/* Post SEM. */
-extern int sem_post __P ((sem_t *__sem));
+extern int sem_post (sem_t *__sem) __THROW;
/* Get current value of SEM and store it in *SVAL. */
-extern int sem_getvalue __P ((sem_t *__sem, int *__sval));
+extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
+ __THROW;
__END_DECLS
diff --git a/libc/sysdeps/linux/common/bits/initspin.h b/libc/sysdeps/linux/common/bits/initspin.h
index 257fed3c5..a19ec077e 100644
--- a/libc/sysdeps/linux/common/bits/initspin.h
+++ b/libc/sysdeps/linux/common/bits/initspin.h
@@ -3,16 +3,16 @@
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
+ 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
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
+ You should have received a copy of the GNU Lesser 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. */
@@ -20,8 +20,9 @@
/* Initial value of a spinlock. Most platforms should use zero,
unless they only implement a "test and clear" operation instead of
the usual "test and set". */
-#define __ATOMIC_LOCK_INIT 0
+#define __LT_SPINLOCK_INIT 0
/* Macros for lock initializers, using the above definition. */
-#define __LOCK_INITIALIZER { 0, 0 }
-#define __ATOMIC_INITIALIZER { 0, 0 }
+#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT }
+#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT }
diff --git a/libc/sysdeps/linux/common/bits/pthreadtypes.h b/libc/sysdeps/linux/common/bits/pthreadtypes.h
index 441734c9d..3ee5c4813 100644
--- a/libc/sysdeps/linux/common/bits/pthreadtypes.h
+++ b/libc/sysdeps/linux/common/bits/pthreadtypes.h
@@ -22,13 +22,11 @@
#define __need_schedparam
#include <bits/sched.h>
-typedef int __atomic_lock_t;
-
/* Fast locks (not abstract because mutexes and conditions aren't abstract). */
struct _pthread_fastlock
{
long int __status; /* "Free" or "taken" or head of waiting list */
- __atomic_lock_t __spinlock; /* Used by compare_and_swap emulation. Also,
+ int __spinlock; /* Used by compare_and_swap emulation. Also,
adaptive SMP lock stores spin count here. */
};
diff --git a/libpthread/Makefile b/libpthread/Makefile
index 567ceb983..89d039246 100644
--- a/libpthread/Makefile
+++ b/libpthread/Makefile
@@ -25,7 +25,7 @@ LIBPTHREAD_SHARED=libpthread.so
LIBPTHREAD_SHARED_FULLNAME=libpthread-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so
LIBTHREAD_DB=libthread_db.a
-LIBTHREAD_DB_SHARED=libthread_db.so
+LIBTHREAD_DB_SHARED=libthread_db.so.1
LIBTHREAD_DB_SHARED_FULLNAME=libthread_db-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so
DIRS=
@@ -101,8 +101,6 @@ shared: all
install -m 644 $(LIBTHREAD_DB_SHARED_FULLNAME) $(TOPDIR)lib; \
(cd $(TOPDIR)lib && ln -sf $(LIBTHREAD_DB_SHARED_FULLNAME) \
$(LIBTHREAD_DB_SHARED)); \
- (cd $(TOPDIR)lib && ln -sf $(LIBTHREAD_DB_SHARED_FULLNAME) \
- $(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION)); \
fi;
tags:
diff --git a/libpthread/linuxthreads/condvar.c b/libpthread/linuxthreads/condvar.c
index 8bc114e3c..f9c46a331 100644
--- a/libpthread/linuxthreads/condvar.c
+++ b/libpthread/linuxthreads/condvar.c
@@ -25,22 +25,6 @@
#include "queue.h"
#include "restart.h"
-static int pthread_cond_timedwait_relative_old(pthread_cond_t *,
- pthread_mutex_t *, const struct timespec *);
-
-static int pthread_cond_timedwait_relative_new(pthread_cond_t *,
- pthread_mutex_t *, const struct timespec *);
-
-static int (*pthread_cond_tw_rel)(pthread_cond_t *, pthread_mutex_t *,
- const struct timespec *) = pthread_cond_timedwait_relative_old;
-
-/* initialize this module */
-void __pthread_init_condvar(int rt_sig_available)
-{
- if (rt_sig_available)
- pthread_cond_tw_rel = pthread_cond_timedwait_relative_new;
-}
-
int pthread_cond_init(pthread_cond_t *cond,
const pthread_condattr_t *cond_attr)
{
@@ -76,12 +60,20 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
volatile pthread_descr self = thread_self();
pthread_extricate_if extr;
int already_canceled = 0;
+ int spurious_wakeup_count;
+
+ /* Check whether the mutex is locked and owned by this thread. */
+ if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
+ && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
+ && mutex->__m_owner != self)
+ return EINVAL;
/* Set up extrication interface */
extr.pu_object = cond;
extr.pu_extricate_func = cond_extricate_func;
/* Register extrication interface */
+ THREAD_SETMEM(self, p_condvar_avail, 0);
__pthread_set_own_extricate_if(self, &extr);
/* Atomically enqueue thread for waiting, but only if it is not
@@ -106,7 +98,21 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
pthread_mutex_unlock(mutex);
- suspend(self);
+ spurious_wakeup_count = 0;
+ while (1)
+ {
+ suspend(self);
+ if (THREAD_GETMEM(self, p_condvar_avail) == 0
+ && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
+ || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
+ {
+ /* Count resumes that don't belong to us. */
+ spurious_wakeup_count++;
+ continue;
+ }
+ break;
+ }
+
__pthread_set_own_extricate_if(self, 0);
/* Check for cancellation again, to provide correct cancellation
@@ -119,31 +125,36 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
pthread_exit(PTHREAD_CANCELED);
}
+ /* Put back any resumes we caught that don't belong to us. */
+ while (spurious_wakeup_count--)
+ restart(self);
+
pthread_mutex_lock(mutex);
return 0;
}
-/* The following function is used on kernels that don't have rt signals.
- SIGUSR1 is used as the restart signal. The different code is needed
- because that ordinary signal does not queue. */
-
static int
-pthread_cond_timedwait_relative_old(pthread_cond_t *cond,
+pthread_cond_timedwait_relative(pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec * abstime)
{
volatile pthread_descr self = thread_self();
- sigset_t unblock, initial_mask;
int already_canceled = 0;
- int was_signalled = 0;
- sigjmp_buf jmpbuf;
pthread_extricate_if extr;
+ int spurious_wakeup_count;
+
+ /* Check whether the mutex is locked and owned by this thread. */
+ if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
+ && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
+ && mutex->__m_owner != self)
+ return EINVAL;
/* Set up extrication interface */
extr.pu_object = cond;
extr.pu_extricate_func = cond_extricate_func;
/* Register extrication interface */
+ THREAD_SETMEM(self, p_condvar_avail, 0);
__pthread_set_own_extricate_if(self, &extr);
/* Enqueue to wait on the condition and check for cancellation. */
@@ -162,202 +173,40 @@ pthread_cond_timedwait_relative_old(pthread_cond_t *cond,
pthread_mutex_unlock(mutex);
- if (atomic_decrement(&self->p_resume_count) == 0) {
- /* Set up a longjmp handler for the restart signal, unblock
- the signal and sleep. */
-
- if (sigsetjmp(jmpbuf, 1) == 0) {
- THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
- THREAD_SETMEM(self, p_signal, 0);
- /* Unblock the restart signal */
- sigemptyset(&unblock);
- sigaddset(&unblock, __pthread_sig_restart);
- sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
-
- while (1) {
- struct timeval now;
- struct timespec reltime;
-
- /* Compute a time offset relative to