Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-3]: src/lib/libpthread Pullup revs 1.8-1.9 (requested by chs in t...



details:   https://anonhg.NetBSD.org/src/rev/07b8448b8f6e
branches:  netbsd-3
changeset: 577428:07b8448b8f6e
user:      jmc <jmc%NetBSD.org@localhost>
date:      Tue Nov 01 20:01:44 2005 +0000

description:
Pullup revs 1.8-1.9 (requested by chs in ticket #926)
 In pthread_mutex_lock_slow(), pthread_rwlock_timedrdlock() and sem_wait(),
 call pthread__start() if it hasn't already been called. this avoids
 an internal assertion from the library if these routines are used
 before any threads are created and they need to sleep.
 PR#20256, PR#24241, PR#25722, PR#26096

 Fix the interaction between sigtimedwait() and pthread_kill(),
 both waking up a sleeping thread and avoiding going to sleep if
 a signal is already pending. PR#30348

 In pthread_kill() and pthread_suspend_np(), return without doing anything
 f the target thread is a zombie.
 In all the functions that didn't do so already, verify a pthread_t before
 dereferencing it (under #ifdef ERRORCHECK, since these checks are not
 mandated by the standard).

 Starting the pthread library (ie. calling pthread__start()) before
 any threads are created turned out to be not such a good idea.
 there are stronger requirements on what has to work in a forked child
 while a process is still single-threaded. so take all that stuff
 back out and fix the problems with single-threaded programs that
 are linked with libpthread differently, by checking if the library
 has been started and doing completely different stuff if it hasn't been:
 - for pthread_rwlock_timedrdlock(), just fail with EDEADLK immediately.
 - for sem_wait(), the only thing that can unlock the semaphore is a
 signal handler, so use sigsuspend() to wait for a signal.
 - for pthread_mutex_lock_slow(), just go into an infinite loop
 waiting for signals.

 If mlock() fails in pthread_create(), return EAGAIN instead of
 failing an assertion.

diffstat:

 lib/libpthread/sem.c |  38 ++++++++++++++++++++++++++++++++++++--
 1 files changed, 36 insertions(+), 2 deletions(-)

diffs (80 lines):

diff -r 6e537e2c4c56 -r 07b8448b8f6e lib/libpthread/sem.c
--- a/lib/libpthread/sem.c      Tue Nov 01 20:01:41 2005 +0000
+++ b/lib/libpthread/sem.c      Tue Nov 01 20:01:44 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sem.c,v 1.7 2003/11/24 23:54:13 cl Exp $       */
+/*     $NetBSD: sem.c,v 1.7.6.1 2005/11/01 20:01:44 jmc Exp $  */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: sem.c,v 1.7 2003/11/24 23:54:13 cl Exp $");
+__RCSID("$NetBSD: sem.c,v 1.7.6.1 2005/11/01 20:01:44 jmc Exp $");
 
 #include <sys/types.h>
 #include <sys/ksem.h>
@@ -286,6 +286,7 @@
 sem_wait(sem_t *sem)
 {
        pthread_t self;
+       extern int pthread__started;
 
 #ifdef ERRORCHECK
        if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) {
@@ -301,6 +302,22 @@
                return (_ksem_wait((*sem)->usem_semid));
        }
 
+       if (pthread__started == 0) {
+               sigset_t set, oset;
+
+               sigfillset(&set);
+               (void) sigprocmask(SIG_SETMASK, &set, &oset);
+               for (;;) {
+                       if ((*sem)->usem_count > 0) {
+                               break;
+                       }
+                       (void) sigsuspend(&oset);
+               }
+               (*sem)->usem_count--;
+               (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+               return 0;
+       }
+
        for (;;) {
                pthread_spinlock(self, &(*sem)->usem_interlock);
                pthread_spinlock(self, &self->pt_statelock);
@@ -339,6 +356,7 @@
 sem_trywait(sem_t *sem)
 {
        pthread_t self;
+       extern int pthread__started;
 
 #ifdef ERRORCHECK
        if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) {
@@ -350,6 +368,22 @@
        if ((*sem)->usem_semid != USEM_USER)
                return (_ksem_trywait((*sem)->usem_semid));
 
+       if (pthread__started == 0) {
+               sigset_t set, oset;
+               int rv = 0;
+
+               sigfillset(&set);
+               (void) sigprocmask(SIG_SETMASK, &set, &oset);
+               if ((*sem)->usem_count > 0) {
+                       (*sem)->usem_count--;
+               } else {
+                       errno = EAGAIN;
+                       rv = -1;
+               }
+               (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+               return rv;
+       }
+
        self = pthread__self();
 
        pthread_spinlock(self, &(*sem)->usem_interlock);



Home | Main Index | Thread Index | Old Index