diff options
Diffstat (limited to 'libpthread/pthread')
-rw-r--r-- | libpthread/pthread/Versions | 15 | ||||
-rw-r--r-- | libpthread/pthread/cthreads-compat.c | 104 | ||||
-rw-r--r-- | libpthread/pthread/pt-alloc.c | 215 | ||||
-rw-r--r-- | libpthread/pthread/pt-cancel.c | 40 | ||||
-rw-r--r-- | libpthread/pthread/pt-cleanup.c | 28 | ||||
-rw-r--r-- | libpthread/pthread/pt-create.c | 217 | ||||
-rw-r--r-- | libpthread/pthread/pt-dealloc.c | 64 | ||||
-rw-r--r-- | libpthread/pthread/pt-detach.c | 92 | ||||
-rw-r--r-- | libpthread/pthread/pt-exit.c | 122 | ||||
-rw-r--r-- | libpthread/pthread/pt-getattr.c | 49 | ||||
-rw-r--r-- | libpthread/pthread/pt-initialize.c | 33 | ||||
-rw-r--r-- | libpthread/pthread/pt-internal.h | 317 | ||||
-rw-r--r-- | libpthread/pthread/pt-join.c | 88 | ||||
-rw-r--r-- | libpthread/pthread/pt-self.c | 32 | ||||
-rw-r--r-- | libpthread/pthread/pt-setcancelstate.c | 43 | ||||
-rw-r--r-- | libpthread/pthread/pt-setcanceltype.c | 43 | ||||
-rw-r--r-- | libpthread/pthread/pt-sigmask.c | 33 | ||||
-rw-r--r-- | libpthread/pthread/pt-spin-inlines.c | 34 | ||||
-rw-r--r-- | libpthread/pthread/pt-testcancel.c | 31 |
19 files changed, 1600 insertions, 0 deletions
diff --git a/libpthread/pthread/Versions b/libpthread/pthread/Versions new file mode 100644 index 00000000..e4b4e8bf --- /dev/null +++ b/libpthread/pthread/Versions @@ -0,0 +1,15 @@ +libc { + GLIBC_2.2 { + # XXX + __vm_deallocate; __mach_port_insert_right; __mach_reply_port; + __mig_init; __vm_allocate; + + # functions used in inline functions or macros + __pthread_spin_destroy; __pthread_spin_init; __pthread_spin_lock; + _pthread_spin_lock; __pthread_spin_trylock; __pthread_spin_unlock; + + # p* + pthread_spin_destroy; pthread_spin_init; pthread_spin_lock; + pthread_spin_trylock; pthread_spin_unlock; + } +} diff --git a/libpthread/pthread/cthreads-compat.c b/libpthread/pthread/cthreads-compat.c new file mode 100644 index 00000000..e0536ef2 --- /dev/null +++ b/libpthread/pthread/cthreads-compat.c @@ -0,0 +1,104 @@ +/* Compatibility routines for cthreads. + Copyright (C) 2000, 2002, 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. */ + +#include <assert.h> +#include <pthread.h> + +typedef void *cthread_t; +typedef void *(*cthread_fn_t) (void *arg); +typedef int cthread_key_t; + +#define CTHREAD_KEY_INVALID (cthread_key_t) -1 + +void +cthread_detach (cthread_t thread) +{ + int err; + + err = pthread_detach ((pthread_t) thread); + assert_perror (err); +} + +cthread_t +cthread_fork (cthread_fn_t func, void *arg) +{ + pthread_t thread; + int err; + + err = pthread_create (&thread, NULL, func, arg); + assert_perror (err); + + return (cthread_t) thread; +} + +int +cthread_keycreate (cthread_key_t *key) +{ + error_t err; + + err = pthread_key_create (key, 0); + if (err) + { + errno = err; + *key = CTHREAD_KEY_INVALID; + err = -1; + } + + return err; +} + +int +cthread_getspecific (cthread_key_t key, void **val) +{ + *val = pthread_getspecific (key); + return 0; +} + +void * +__libc_getspecific (cthread_key_t key) +{ + return pthread_getspecific (key); +} + +int +cthread_setspecific (cthread_key_t key, void *val) +{ + error_t err; + + err = pthread_setspecific (key, (const void *) val); + if (err) + { + errno = err; + err = -1; + } + + return err; +} + +void +__mutex_lock_solid (void *lock) +{ + __pthread_mutex_lock (lock); +} + +void +__mutex_unlock_solid (void *lock) +{ + __pthread_mutex_unlock (lock); +} diff --git a/libpthread/pthread/pt-alloc.c b/libpthread/pthread/pt-alloc.c new file mode 100644 index 00000000..6af2da92 --- /dev/null +++ b/libpthread/pthread/pt-alloc.c @@ -0,0 +1,215 @@ +/* Allocate a new thread structure. + Copyright (C) 2000, 2002, 2005, 2007, 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. */ + +#include <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> +#include <string.h> + +#include <pt-internal.h> + +/* This braindamage is necessary because the standard says that some + of the threads functions "shall fail" if "No thread could be found + corresponding to that specified by the given thread ID." */ + +/* Thread ID lookup table. */ +struct __pthread **__pthread_threads; + +/* The size of the thread ID lookup table. */ +int __pthread_max_threads; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +int __pthread_num_threads; + +/* A lock for the table, and the other variables above. */ +pthread_rwlock_t __pthread_threads_lock; + +/* List of thread structures corresponding to free thread IDs. */ +struct __pthread *__pthread_free_threads; +pthread_mutex_t __pthread_free_threads_lock; + +static inline error_t +initialize_pthread (struct __pthread *new, int recycling) +{ + error_t err; + + err = __pthread_init_specific (new); + if (err) + return err; + + new->cancel_state = PTHREAD_CANCEL_ENABLE; + new->cancel_type = PTHREAD_CANCEL_DEFERRED; + new->cancel_pending = 0; + + if (recycling) + /* Since we are recycling PTHREAD, we can assume certains things + about PTHREAD's current state and save some cycles by not + rewriting the memory. */ + return 0; + + new->stack = 0; + + new->state_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER; + + new->cancelation_handlers = 0; + + new->next = 0; + new->prevp = 0; + + return 0; +} + + +/* Allocate a new thread structure and its pthread thread ID (but not + a kernel thread). */ +int +__pthread_alloc (struct __pthread **pthread) +{ + error_t err; + + struct __pthread *new; + struct __pthread **threads; + struct __pthread **old_threads; + int max_threads; + int new_max_threads; + + pthread_mutex_lock (&__pthread_free_threads_lock); + for (new = __pthread_free_threads; new; new = new->next) + { + /* There is no need to take NEW->STATE_LOCK: if NEW is on this + list, then it is protected by __PTHREAD_FREE_THREADS_LOCK + except in __pthread_dealloc where after it is added to the + list (with the lock held), it drops the lock and then sets + NEW->STATE and immediately stops using NEW. */ + if (new->state == PTHREAD_TERMINATED) + { + __pthread_dequeue (new); + break; + } + } + pthread_mutex_unlock (&__pthread_free_threads_lock); + + if (new) + { + /* The thread may still be running. Make sure it is stopped. + If this is the case, then the thread is either at the end of + __pthread_dealloc or in __pthread_thread_halt. In both + cases, we are interrupt it. */ + __pthread_thread_halt (new); + + err = initialize_pthread (new, 1); + if (! err) + *pthread = new; + return err; + } + + /* Allocate a new thread structure. */ + new = malloc (sizeof (struct __pthread)); + if (new == NULL) + return ENOMEM; + + err = initialize_pthread (new, 0); + if (err) + { + free (new); + return err; + } + + retry: + pthread_rwlock_wrlock (&__pthread_threads_lock); + + if (__pthread_num_threads < __pthread_max_threads) + { + /* We have a free slot. Use the slot number plus one as the + thread ID for the new thread. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + *pthread = new; + return 0; + } +#ifdef PTHREAD_THREADS_MAX + else if (__pthread_num_threads >= PTHREAD_THREADS_MAX) + { + /* We have reached the limit on the number of threads per process. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (new); + return EAGAIN; + } +#endif + + /* We are going to enlarge the threads table. Save its current + size. We're going to release the lock before doing the necessary + memory allocation, since that's a potentially blocking operation. */ + max_threads = __pthread_max_threads; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Allocate a new lookup table that's twice as large. */ + new_max_threads + = max_threads > 0 ? max_threads * 2 : _POSIX_THREAD_THREADS_MAX; + threads = malloc (new_max_threads * sizeof (struct __pthread *)); + if (threads == NULL) + { + free (new); + return ENOMEM; + } + + pthread_rwlock_wrlock (&__pthread_threads_lock); + + /* Check if nobody else has already enlarged the table. */ + if (max_threads != __pthread_max_threads) + { + /* Yep, they did. */ + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* Free the newly allocated table and try again to allocate a slot. */ + free (threads); + goto retry; + } + + /* Copy over the contents of the old table. */ + memcpy (threads, __pthread_threads, + __pthread_max_threads * sizeof (struct __pthread *)); + + /* Save the location of the old table. We want to deallocate its + storage after we released the lock. */ + old_threads = __pthread_threads; + + /* Replace the table with the new one. */ + __pthread_max_threads = new_max_threads; + __pthread_threads = threads; + + /* And allocate ourselves one of the newly created slots. */ + new->thread = 1 + __pthread_num_threads++; + __pthread_threads[new->thread - 1] = NULL; + + pthread_rwlock_unlock (&__pthread_threads_lock); + + free (old_threads); + + *pthread = new; + return 0; +} diff --git a/libpthread/pthread/pt-cancel.c b/libpthread/pthread/pt-cancel.c new file mode 100644 index 00000000..d19c557d --- /dev/null +++ b/libpthread/pthread/pt-cancel.c @@ -0,0 +1,40 @@ +/* Cancel a thread. + Copyright (C) 2002 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 <pt-internal.h> + +int +pthread_cancel (pthread_t t) +{ + int err = 0; + struct __pthread *p; + + p = __pthread_getid (t); + if (! p) + return ESRCH; + + p->cancel_pending = 1; + if (p->cancel_state == PTHREAD_CANCEL_ENABLE + && p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS) + err = __pthread_do_cancel (p); + + return err; +} diff --git a/libpthread/pthread/pt-cleanup.c b/libpthread/pthread/pt-cleanup.c new file mode 100644 index 00000000..58865aa4 --- /dev/null +++ b/libpthread/pthread/pt-cleanup.c @@ -0,0 +1,28 @@ +/* Add a cancelation handler to the stack. + Copyright (C) 2002 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 <pt-internal.h> + +struct __pthread_cancelation_handler ** +__pthread_get_cleanup_stack (void) +{ + return &_pthread_self ()->cancelation_handlers; +} diff --git a/libpthread/pthread/pt-create.c b/libpthread/pthread/pt-create.c new file mode 100644 index 00000000..346c6979 --- /dev/null +++ b/libpthread/pthread/pt-create.c @@ -0,0 +1,217 @@ +/* Thread creation. + Copyright (C) 2000, 2002, 2005, 2007 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include <bits/atomic.h> + +#include <pt-internal.h> + +#ifdef HAVE_USELOCALE +# include <locale.h> +#endif + +/* The total number of pthreads currently active. This is defined + here since it would be really stupid to have a threads-using + program that doesn't call `pthread_create'. */ +__atomic_t __pthread_total; + + +/* The entry-point for new threads. */ +static void +entry_point (void *(*start_routine)(void *), void *arg) +{ +#ifdef HAVE_USELOCALE + /* A fresh thread needs to be bound to the global locale. */ + uselocale (LC_GLOBAL_LOCALE); +#endif + + __pthread_startup (); + + pthread_exit (start_routine (arg)); +} + +/* Create a thread with attributes given by ATTR, executing + START_ROUTINE with argument ARG. */ +int +pthread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + + err = __pthread_create_internal (&pthread, attr, start_routine, arg); + if (! err) + *thread = pthread->thread; + + return err; +} + +/* Internal version of pthread_create. See comment in + pt-internal.h. */ +int +__pthread_create_internal (struct __pthread **thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int err; + struct __pthread *pthread; + const struct __pthread_attr *setup; + sigset_t sigset; + + /* Allocate a new thread structure. */ + err = __pthread_alloc (&pthread); + if (err) + goto failed; + + /* Use the default attributes if ATTR is NULL. */ + setup = attr ? attr : &__pthread_default_attr; + + /* Initialize the thread state. */ + pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED + ? PTHREAD_DETACHED : PTHREAD_JOINABLE); + + /* If the user supplied a stack, it is not our responsibility to + setup a stack guard. */ + if (setup->stackaddr) + pthread->guardsize = 0; + else + pthread->guardsize = (setup->guardsize <= setup->stacksize + ? setup->guardsize : setup->stacksize); + + /* Find a stack. There are several scenarios: if a detached thread + kills itself, it has no way to deallocate its stack, thus it + leaves PTHREAD->stack set to true. We try to reuse it here, + however, if the user supplied a stack, we cannot use the old one. + Right now, we simply deallocate it. */ + if (pthread->stack) + { + if (setup->stackaddr != __pthread_default_attr.stackaddr) + { + __pthread_stack_dealloc (pthread->stackaddr, + pthread->stacksize); + pthread->stackaddr = setup->stackaddr; + pthread->stacksize = setup->stacksize; + } + } + else + { + err = __pthread_stack_alloc (&pthread->stackaddr, + setup->stacksize); + if (err) + goto failed_stack_alloc; + + pthread->stacksize = setup->stacksize; + pthread->stack = 1; + } + + /* Allocate the kernel thread and other required resources. */ + err = __pthread_thread_alloc (pthread); + if (err) + goto failed_thread_alloc; + +#ifdef ENABLE_TLS + pthread->tcb = _dl_allocate_tls (NULL); + if (!pthread->tcb) + goto failed_thread_tls_alloc; + pthread->tcb->tcb = pthread->tcb; +#endif /* ENABLE_TLS */ + + /* And initialize the rest of the machine context. This may include + additional machine- and system-specific initializations that + prove convenient. */ + err = __pthread_setup (pthread, entry_point, start_routine, arg); + if (err) + goto failed_setup; + + /* Initialize the system-specific signal state for the new + thread. */ + err = __pthread_sigstate_init (pthread); + if (err) + goto failed_sigstate; + + /* Set the new thread's signal mask and set the pending signals to + empty. POSIX says: "The signal mask shall be inherited from the + creating thread. The set of signals pending for the new thread + shall be empty." If the currnet thread is not a pthread then we + just inherit the process' sigmask. */ + if (__pthread_num_threads == 1) + err = sigprocmask (0, 0, &sigset); + else + err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0); + assert_perror (err); + + err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1); + assert_perror (err); + + /* Increase the total number of threads. We do this before actually + starting the new thread, since the new thread might immediately + call `pthread_exit' which decreases the number of threads and + calls `exit' if the number of threads reaches zero. Increasing + the number of threads from within the new thread isn't an option + since this thread might return and call `pthread_exit' before the + new thread runs. */ + __atomic_inc (&__pthread_total); + + /* Store a pointer to this thread in the thread ID lookup table. We + could use __thread_setid, however, we only lock for reading as no + other thread should be using this entry (we also assume that the + store is atomic). */ + pthread_rwlock_rdlock (&__pthread_threads_lock); + __pthread_threads[pthread->thread - 1] = pthread; + pthread_rwlock_unlock (&__pthread_threads_lock); + + /* At this point it is possible to guess our pthread ID. We have to + make sure that all functions taking a pthread_t argument can + handle the fact that this thread isn't really running yet. */ + + /* Schedule the new thread. */ + err = __pthread_thread_start (pthread); + if (err) + goto failed_starting; + + /* At this point the new thread is up and running. */ + + *thread = pthread; + + return 0; + + failed_starting: + __pthread_setid (pthread->thread, NULL); + __atomic_dec (&__pthread_total); + failed_sigstate: + __pthread_sigstate_destroy (pthread); + failed_setup: +#ifdef ENABLE_TLS + _dl_deallocate_tls (pthread->tcb, 1); + failed_thread_tls_alloc: +#endif /* ENABLE_TLS */ + __pthread_thread_dealloc (pthread); + __pthread_thread_halt (pthread); + failed_thread_alloc: + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + failed_stack_alloc: + __pthread_dealloc (pthread); + failed: + return err; +} diff --git a/libpthread/pthread/pt-dealloc.c b/libpthread/pthread/pt-dealloc.c new file mode 100644 index 00000000..92fe1fda --- /dev/null +++ b/libpthread/pthread/pt-dealloc.c @@ -0,0 +1,64 @@ +/* Deallocate a thread structure. + Copyright (C) 2000, 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. */ + +#include <assert.h> +#include <pthread.h> +#include <stdlib.h> + +#include <pt-internal.h> + +/* List of thread structures corresponding to free thread IDs. */ +extern struct __pthread *__pthread_free_threads; +extern pthread_mutex_t __pthread_free_threads_lock; + + +/* Deallocate the thread structure for PTHREAD. */ +void +__pthread_dealloc (struct __pthread *pthread) +{ + assert (pthread->state != PTHREAD_TERMINATED); + + /* Withdraw this thread from the thread ID lookup table. */ + __pthread_setid (pthread->thread, NULL); + + /* Mark the thread as terminated. We broadcast the condition + here to prevent pthread_join from waiting for this thread to + exit where it was never really started. Such a call to + pthread_join is completely bogus, but unfortunately allowed + by the standards. */ + __pthread_mutex_lock (&pthread->state_lock); + if (pthread->state != PTHREAD_EXITED) + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + + /* We do not actually deallocate the thread structure, but add it to + a list of re-usable thread structures. */ + pthread_mutex_lock (&__pthread_free_threads_lock); + __pthread_enqueue (&__pthread_free_threads, pthread); + pthread_mutex_unlock (&__pthread_free_threads_lock); + + /* Setting PTHREAD->STATE to PTHREAD_TERMINATED makes this TCB + available for reuse. After that point, we can no longer assume + that PTHREAD is valid. + + Note that it is safe to not lock this update to PTHREAD->STATE: + the only way that it can now be accessed is in __pthread_alloc, + which reads this variable. */ + pthread->state = PTHREAD_TERMINATED; +} diff --git a/libpthread/pthread/pt-detach.c b/libpthread/pthread/pt-detach.c new file mode 100644 index 00000000..1e42c452 --- /dev/null +++ b/libpthread/pthread/pt-detach.c @@ -0,0 +1,92 @@ +/* Detach a thread. + Copyright (C) 2000, 2005 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 <errno.h> +#include <pthread.h> +#include <stddef.h> + +#include <pt-internal.h> + +/* Indicate that the storage for THREAD can be reclaimed when it + terminates. */ +int +pthread_detach (pthread_t thread) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + + switch (pthread->state) + { + case PTHREAD_JOINABLE: + /* THREAD still running. Mark it as detached such that its + resources can be reclaimed as soon as the thread exits. */ + pthread->state = PTHREAD_DETACHED; + + /* Broadcast the condition. This will make threads that are + waiting to join THREAD continue with hopefully disastrous + consequences instead of blocking indefinitely. */ + pthread_cond_broadcast (&pthread->state_cond); + __pthread_mutex_unlock (&pthread->state_lock); + break; + + case PTHREAD_EXITED: + /* THREAD has already exited. Make sure that nobody can + reference it anymore, and mark it as terminated. */ + + __pthread_mutex_unlock (&pthread->state_lock); + + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_thread_dealloc (pthread); + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not detach non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/libpthread/pthread/pt-exit.c b/libpthread/pthread/pt-exit.c new file mode 100644 index 00000000..c01efda0 --- /dev/null +++ b/libpthread/pthread/pt-exit.c @@ -0,0 +1,122 @@ +/* Thread termination. + Copyright (C) 2000, 2002, 2005, 2007, 2011 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> + +#include <pt-internal.h> + +#include <bits/atomic.h> + + +/* Terminate the current thread and make STATUS available to any + thread that might join it. */ +void +pthread_exit (void *status) +{ + struct __pthread *self = _pthread_self (); + struct __pthread_cancelation_handler **handlers; + int oldstate; + + /* Run any cancelation handlers. According to POSIX, the + cancellation cleanup handlers should be called with cancellation + disabled. */ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + + for (handlers = __pthread_get_cleanup_stack (); + *handlers; + *handlers = (*handlers)->next) + (*handlers)->handler ((*handlers)->arg); + + pthread_setcancelstate (oldstate, &oldstate); + + /* Destory any thread specific data. */ + __pthread_destroy_specific (self); + + /* Destroy any signal state. */ + __pthread_sigstate_destroy (self); + + /* Decrease the number of threads. We use an atomic operation to + make sure that only the last thread calls `exit'. */ + if (__atomic_dec_and_test (&__pthread_total)) + /* We are the last thread. */ + exit (0); + + /* Note that after this point the process can be terminated at any + point if another thread calls `pthread_exit' and happens to be + the last thread. */ + + __pthread_mutex_lock (&self->state_lock); + + if (self->cancel_state == PTHREAD_CANCEL_ENABLE && self->cancel_pending) + status = PTHREAD_CANCELED; + +#ifdef ENABLE_TLS + if (self->tcb) + _dl_deallocate_tls (self->tcb, 1); +#endif /* ENABLE_TLS */ + + switch (self->state) + { + default: + assert (! "Consistency error: unexpected self->state"); + abort (); + break; + + case PTHREAD_DETACHED: + /* Make sure that nobody can reference this thread anymore, and + mark it as terminated. Our thread ID will immediately become + available for re-use. For obvious reasons, we cannot + deallocate our own stack. However, it will eventually be + reused when this thread structure is recycled. */ + __pthread_mutex_unlock (&self->state_lock); + + __pthread_dealloc (self); + + break; + + case PTHREAD_JOINABLE: + /* We need to stay around for a while since another thread + might want to join us. */ + self->state = PTHREAD_EXITED; + + /* We need to remember the exit status. A thread joining us + might ask for it. */ + self->status = status; + + /* Broadcast the condition. This will wake up threads that are + waiting to join us. */ + pthread_cond_broadcast (&self->state_cond); + __pthread_mutex_unlock (&self->state_lock); + + break; + } + + /* Note that after this point the resources used by this thread can + be freed at any moment if another thread joins or detaches us. + This means that before freeing any resources, such a thread + should make sure that this thread is really halted. */ + + __pthread_thread_halt (self); + + /* NOTREACHED */ + abort (); +} diff --git a/libpthread/pthread/pt-getattr.c b/libpthread/pthread/pt-getattr.c new file mode 100644 index 00000000..24599c6e --- /dev/null +++ b/libpthread/pthread/pt-getattr.c @@ -0,0 +1,49 @@ +/* Thread attributes retrieval. + 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. */ + +#include <assert.h> +#include <errno.h> +#include <pthread.h> + +#include <pt-internal.h> + +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread THREAD. It shall be called on an uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +int +pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + struct __pthread *pthread; + + pthread = __pthread_getid(thread); + if (pthread == NULL) + return ESRCH; + + /* Some attributes (schedparam, inheritsched, contentionscope and schedpolicy) + are not supported yet, so fill them with our default values. */ + *attr = __pthread_default_attr; + + attr->stackaddr = pthread->stackaddr; + attr->stacksize = pthread->stacksize; + attr->guardsize = pthread->guardsize; + attr->detachstate = (pthread->state == PTHREAD_DETACHED + ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + + return 0; +} diff --git a/libpthread/pthread/pt-initialize.c b/libpthread/pthread/pt-initialize.c new file mode 100644 index 00000000..cf32b8b5 --- /dev/null +++ b/libpthread/pthread/pt-initialize.c @@ -0,0 +1,33 @@ +/* Initialize pthreads library. + Copyright (C) 2000,02 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 <assert.h> +#include <string.h> + +#include <pt-internal.h> +#include <set-hooks.h> + +DEFINE_HOOK (__pthread_init, (void)); + +/* Initialize the pthreads library. */ +void +__pthread_initialize (void) +{ + RUN_HOOK (__pthread_init, ()); +} diff --git a/libpthread/pthread/pt-internal.h b/libpthread/pthread/pt-internal.h new file mode 100644 index 00000000..3f69d2dd --- /dev/null +++ b/libpthread/pthread/pt-internal.h @@ -0,0 +1,317 @@ +/* Internal defenitions for pthreads library. + Copyright (C) 2000, 2005, 2006, 2007, 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. */ + +#ifndef _PT_INTERNAL_H +#define _PT_INTERNAL_H 1 + +#include <pthread.h> +#include <stddef.h> +#include <sched.h> +#include <signal.h> +#include <assert.h> + +#include <bits/atomic.h> + +#include <pt-key.h> + +#include <pt-sysdep.h> +#include <pt-machdep.h> + +/* Thread state. */ +enum pthread_state +{ + /* The thread is running and joinable. */ + PTHREAD_JOINABLE = 0, + /* The thread is running and detached. */ + PTHREAD_DETACHED, + /* A joinable thread exited and its return code is available. */ + PTHREAD_EXITED, + /* The thread structure is unallocated and available for reuse. */ + PTHREAD_TERMINATED +}; + +#ifndef PTHREAD_KEY_MEMBERS +# define PTHREAD_KEY_MEMBERS +#endif + +#ifndef PTHREAD_SYSDEP_MEMBERS +# define PTHREAD_SYSDEP_MEMBERS +#endif + +#ifdef ENABLE_TLS +/* Type of the TCB. */ +typedef struct +{ + void *tcb; /* Points to this structure. */ + void *dtv; /* Vector of pointers to TLS data. */ + thread_t self; /* This thread's control port. */ +} tcbhead_t; +#endif /* ENABLE_TLS */ + +/* This structure describes a POSIX thread. */ +struct __pthread +{ + /* Thread ID. */ + pthread_t thread; + + /* Cancellation. */ + int cancel_state; + int cancel_type; + int cancel_pending; + struct __pthread_cancelation_handler *cancelation_handlers; + + /* Thread stack. */ + void *stackaddr; + size_t stacksize; + size_t guardsize; /* Included in STACKSIZE (i.e. total + stack memory is STACKSIZE, not + STACKSIZE + GUARDSIZE). */ + int stack; /* Nonzero if the stack was allocated. */ + + /* Exit status. */ + void *status; + + /* Thread state. */ + enum pthread_state state; + pthread_mutex_t state_lock; /* Locks the state. */ + pthread_cond_t state_cond; /* Signalled when the state changes. */ + + /* Thread context. */ + struct pthread_mcontext mcontext; + + PTHREAD_KEY_MEMBERS + + PTHREAD_SYSDEP_MEMBERS + +#ifdef ENABLE_TLS + tcbhead_t *tcb; +#endif /* ENABLE_TLS */ + + struct __pthread *next, **prevp; +}; + +/* Enqueue an element THREAD on the queue *HEAD. */ +static inline void +__pthread_enqueue (struct __pthread **head, struct __pthread *thread) +{ + assert (thread->prevp == 0); + + thread->next = *head; + thread->prevp = head; + if (*head) + (*head)->prevp = &thread->next; + *head = thread; +} + +/* Dequeue the element THREAD from the queue it is connected to. */ +static inline void +__pthread_dequeue (struct __pthread *thread) +{ + assert (thread); + + if (thread->next) + thread->next->prevp = thread->prevp; + *thread->prevp = thread->next; + thread->prevp = 0; +} + +/* Iterate over QUEUE storing each element in ELEMENT. */ +#define __pthread_queue_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + 1); \ + ) + +/* Iterate over QUEUE dequeuing each element, storing it in + ELEMENT. */ +#define __pthread_dequeuing_iterate(queue, element) \ + for (struct __pthread *__pdi_next = (queue); \ + ((element) = __pdi_next) \ + && ((__pdi_next = __pdi_next->next), \ + ((element)->prevp = 0), \ + 1); \ + ) + +/* The total number of threads currently active. */ +extern __atomic_t __pthread_total; + +/* The total number of thread IDs currently in use, or on the list of + available thread IDs. */ +extern int __pthread_num_threads; + +/* Concurrency hint. */ +extern int __pthread_concurrency; + +/* Array of __pthread structures and its lock. Indexed by the pthread + id minus one. (Why not just use the pthread id? Because some + brain-dead users of the pthread interface incorrectly assume that 0 + is an invalid pthread id.) */ +extern struct __pthread **__pthread_threads; +extern pthread_rwlock_t __pthread_threads_lock; + +#define __pthread_getid(thread) \ + ({ struct __pthread *__t; \ + pthread_rwlock_rdlock (&__pthread_threads_lock); \ + __t = __pthread_threads[thread - 1]; \ + pthread_rwlock_unlock (&__pthread_threads_lock); \ + __t; }) + +#define __pthread_setid(thread, pthread) \ + pthread_rwlock_wrlock (&__pthread_threads_lock); \ + __pthread_threads[thread - 1] = pthread; \ + pthread_rwlock_unlock (&__pthread_threads_lock); + +/* Similar to pthread_self, but returns the thread descriptor instead + of the thread ID. */ +#ifndef _pthread_self +extern struct __pthread *_pthread_self (void); +#endif + + +/* Initialize the pthreads library. */ +extern void __pthread_initialize (void); + +/* Internal version of pthread_create. Rather than return the new + tid, we return the whole __pthread structure in *PTHREAD. */ +extern int __pthread_create_internal (struct __pthread **__restrict pthread, + const pthread_attr_t *__restrict attr, + void *(*start_routine)(void *), + void *__restrict arg); + +/* Allocate a new thread structure and a pthread thread ID (but not a + kernel thread or a stack). */ +extern int __pthread_alloc (struct __pthread **thread); + +/* Deallocate the thread structure. This is the dual of + __pthread_alloc (N.B. it does not call __pthread_stack_alloc nor + __pthread_thread_halt). */ +extern void __pthread_dealloc (struct __pthread *thread); + + +/* Allocate a stack of size STACKSIZE. The stack base shall be + returned in *STACKADDR. */ +extern int __pthread_stack_alloc (void **stackaddr, size_t stacksize); + +/* Deallocate the stack STACKADDR of size STACKSIZE. */ +extern void __pthread_stack_dealloc (void *stackaddr, size_t stacksize); + + +/* Setup thread THREAD's context. */ +extern int __pthread_setup (struct __pthread *__restrict thread, + void (*entry_point)(void *(*)(void *), + void *), + void *(*start_routine)(void *), + void *__restrict arg); + + +/* Allocate a kernel thread (and any miscellaneous system dependent + resources) for THREAD; it must not be placed on the run queue. */ +extern int __pthread_thread_alloc (struct __pthread *thread); + +/* Deallocate any kernel resources associated with THREAD. The thread + must not be running (that is, if __pthread_thread_start was called, + __pthread_thread_halt must first be called). This function will + never be called by a thread on itself. In the case that a thread + exits, its thread structure will be cached and cleaned up + later. */ +extern void __pthread_thread_dealloc (struct __pthread *thread); + +/* Start THREAD making it eligible to run. */ +extern int __pthread_thread_start (struct __pthread *thread); + +/* Stop the kernel thread associated with THREAD. This function may + be called by two threads in parallel. In particular, by the thread + itself and another thread trying to join it. This function must be + implemented such that this is safe. */ +extern void __pthread_thread_halt (struct __pthread *thread); + + +/* Called by a thread just before it calls the provided start + routine. */ +extern void __pthread_startup (void); + +/* Block THREAD. */ +extern void __pthread_block (struct __pthread *thread); + +/* Block THREAD until *ABSTIME is reached. */ +extern error_t __pthread_timedblock (struct __pthread *__restrict thread, + const struct timespec *__restrict abstime); + +/* Wakeup THREAD. */ +extern void __pthread_wakeup (struct __pthread *thread); + + +/* Perform a cancelation. */ +extern int __pthread_do_cancel (struct __pthread *thread); + + +/* Initialize the thread specific data structures. THREAD must be the + calling thread. */ +extern error_t __pthread_init_specific (struct __pthread *thread); + +/* Call the destructors on all of the thread specific data in THREAD. + THREAD must be the calling thread. */ +extern void __pthread_destroy_specific (struct __pthread *thread); + + +/* Initialize newly create thread *THREAD's signal state data + structures. */ +extern error_t __pthread_sigstate_init (struct __pthread *thread); + +/* Destroy the signal state data structures associcated with thread + *THREAD. */ +extern void __pthread_sigstate_destroy (struct __pthread *thread); + +/* Modify thread *THREAD's signal state. */ +extern error_t __pthread_sigstate (struct __pthread *__restrict thread, int how, + const sigset_t *__restrict set, + sigset_t *__restrict oset, + int clear_pending); + + +/* Default thread attributes. */ +extern const struct __pthread_attr __pthread_default_attr; + +/* Default barrier attributes. */ +extern const struct __pthread_barrierattr __pthread_default_barrierattr; + +/* Default mutex attributes. */ +extern const struct __pthread_mutexattr __pthread_default_mutexattr; + +/* Default rdlock attributes. */ +const struct __pthread_rwlockattr __pthread_default_rwlockattr; + +/* Default condition attributes. */ +const struct __pthread_condattr __pthread_default_condattr; + + +#ifdef ENABLE_TLS + +/* From glibc. */ + +/* Dynamic linker TLS allocation. */ +extern void *_dl_allocate_tls(void *); + +/* Dynamic linker TLS deallocation. */ +extern void _dl_deallocate_tls(void *, int); + +#endif /* ENABLE_TLS */ + +#endif /* pt-internal.h */ diff --git a/libpthread/pthread/pt-join.c b/libpthread/pthread/pt-join.c new file mode 100644 index 00000000..153058b5 --- /dev/null +++ b/libpthread/pthread/pt-join.c @@ -0,0 +1,88 @@ +/* Wait for thread termination. + Copyright (C) 2000 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 <errno.h> +#include <pthread.h> +#include <stddef.h> + +#include <pt-internal.h> + +/* Make calling thread wait for termination of thread THREAD. Return + the exit status of the thread in *STATUS. */ +int +pthread_join (pthread_t thread, void **status) +{ + struct __pthread *pthread; + int err = 0; + + /* Lookup the thread structure for THREAD. */ + pthread = __pthread_getid (thread); + if (pthread == NULL) + return ESRCH; + + __pthread_mutex_lock (&pthread->state_lock); + pthread_cleanup_push ((void (*)(void *)) __pthread_mutex_unlock, + &pthread->state_lock); + + while (pthread->state == PTHREAD_JOINABLE) + pthread_cond_wait (&pthread->state_cond, &pthread->state_lock); + + pthread_cleanup_pop (0); + + switch (pthread->state) + { + case PTHREAD_EXITED: + __pthread_mutex_unlock (&pthread->state_lock); + + /* THREAD has already exited. Salvage its exit status. */ + if (status) + *status = pthread->status; + + /* Make sure the thread is not running before we remove its + stack. (The only possibility is that it is in a call to + __pthread_thread_halt itself, but that is enough to cause a + sigsegv.) */ + __pthread_thread_halt (pthread); + + /* Destroy the stack, the kernel resources and the control + block. */ + assert (pthread->stack); + __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize); + pthread->stack = 0; + + __pthread_thread_dealloc (pthread); + + __pthread_dealloc (pthread); + break; + + case PTHREAD_TERMINATED: + /* Pretend THREAD wasn't there in the first place. */ + __pthread_mutex_unlock (&pthread->state_lock); + err = ESRCH; + break; + + default: + /* Thou shalt not join non-joinable threads! */ + __pthread_mutex_unlock (&pthread->state_lock); + err = EINVAL; + break; + } + + return err; +} diff --git a/libpthread/pthread/pt-self.c b/libpthread/pthread/pt-self.c new file mode 100644 index 00000000..49768643 --- /dev/null +++ b/libpthread/pthread/pt-self.c @@ -0,0 +1,32 @@ +/* Get calling thread's ID. + Copyright (C) 2000, 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. */ + +#include <pthread.h> + +#include <pt-internal.h> + +/* Return the thread ID of the calling thread. */ +pthread_t +pthread_self (void) +{ + struct __pthread *self = _pthread_self (); + assert (self); + + return self->thread; +} diff --git a/libpthread/pthread/pt-setcancelstate.c b/libpthread/pthread/pt-setcancelstate.c new file mode 100644 index 00000000..e2d81833 --- /dev/null +++ b/libpthread/pthread/pt-setcancelstate.c @@ -0,0 +1,43 @@ +/* Set the cancel state for the calling thread. + Copyright (C) 2002 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 <pt-internal.h> + +int +pthread_setcancelstate (int state, int *oldstate) +{ + struct __pthread *p = _pthread_self (); + + switch (state) + { + default: + return EINVAL; + case PTHREAD_CANCEL_ENABLE: + case PTHREAD_CANCEL_DISABLE: + break; + } + + if (oldstate) + *oldstate = p->cancel_state; + p->cancel_state = state; + + return 0; +} diff --git a/libpthread/pthread/pt-setcanceltype.c b/libpthread/pthread/pt-setcanceltype.c new file mode 100644 index 00000000..3ce4259c --- /dev/null +++ b/libpthread/pthread/pt-setcanceltype.c @@ -0,0 +1,43 @@ +/* Set the cancel type for the calling thread. + Copyright (C) 2002 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 <pt-internal.h> + +int +pthread_setcanceltype (int type, int *oldtype) +{ + struct __pthread *p = _pthread_self (); + + switch (type) + { + default: + return EINVAL; + case PTHREAD_CANCEL_DEFERRED: + case PTHREAD_CANCEL_ASYNCHRONOUS: + break; + } + + if (oldtype) + *oldtype = p->cancel_type; + p->cancel_type = type; + + return 0; +} diff --git a/libpthread/pthread/pt-sigmask.c b/libpthread/pthread/pt-sigmask.c new file mode 100644 index 00000000..1b53873e --- /dev/null +++ b/libpthread/pthread/pt-sigmask.c @@ -0,0 +1,33 @@ +/* Get or set a thread's signal mask. + Copyright (C) 2000 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 <signal.h> + +#include <pt-internal.h> + +int +pthread_sigmask (int how, const sigset_t *set, + sigset_t *oset) +{ + struct __pthread *self = _pthread_self (); + + /* Do not clear SELF's pending signals. */ + return __pthread_sigstate (self, how, set, oset, 0); +} diff --git a/libpthread/pthread/pt-spin-inlines.c b/libpthread/pthread/pt-spin-inlines.c new file mode 100644 index 00000000..cfb21dd3 --- /dev/null +++ b/libpthread/pthread/pt-spin-inlines.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2000 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. */ + +/* <bits/spin-lock.h> declares some extern inline functions. These + functions are declared additionally here for use when inlining is + not possible. */ + +#define _FORCE_INLINES +#define __PT_SPIN_INLINE /* empty */ + +#include <pthread.h> + +/* Weak aliases for the spin lock functions. Note that + pthread_spin_lock is left out deliberately. We already provide an + implementation for it in pt-spin.c. */ +weak_alias (__pthread_spin_destroy, pthread_spin_destroy); +weak_alias (__pthread_spin_init, pthread_spin_init); +weak_alias (__pthread_spin_trylock, pthread_spin_trylock); +weak_alias (__pthread_spin_unlock, pthread_spin_unlock); diff --git a/libpthread/pthread/pt-testcancel.c b/libpthread/pthread/pt-testcancel.c new file mode 100644 index 00000000..01f1ac9c --- /dev/null +++ b/libpthread/pthread/pt-testcancel.c @@ -0,0 +1,31 @@ +/* Add an explicit cancelation point. + Copyright (C) 2002 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 <pt-internal.h> + +void +pthread_testcancel (void) +{ + struct __pthread *p = _pthread_self (); + + if (p->cancel_state == PTHREAD_CANCEL_ENABLE && p->cancel_pending) + pthread_exit (PTHREAD_CANCELED); +} |