diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2015-02-14 23:00:19 -0600 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2015-02-14 23:00:19 -0600 |
commit | 6b6ede3d15f04fe825cfa9f697507457e3640344 (patch) | |
tree | efe9bf75eaf2200f89087ed0ef2ef350549ccd6d /libpthread/linuxthreads.old | |
parent | f972c2262fd4efc2bbf9789dce145bb705acec24 (diff) |
resolve merge
Diffstat (limited to 'libpthread/linuxthreads.old')
70 files changed, 0 insertions, 13551 deletions
diff --git a/libpthread/linuxthreads.old/Makefile b/libpthread/linuxthreads.old/Makefile deleted file mode 100644 index f9100219a..000000000 --- a/libpthread/linuxthreads.old/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Makefile for uClibc -# -# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> -# -# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. -# - -top_srcdir=../../ -top_builddir=../../ -include $(top_builddir)Rules.mak -all: libs -include Makefile.in -include $(top_srcdir)Makerules diff --git a/libpthread/linuxthreads.old/Makefile.in b/libpthread/linuxthreads.old/Makefile.in deleted file mode 100644 index 6be2099d2..000000000 --- a/libpthread/linuxthreads.old/Makefile.in +++ /dev/null @@ -1,119 +0,0 @@ -# Makefile for uClibc -# -# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> -# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org> -# -# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. -# - -subdirs += libpthread/linuxthreads.old - -CFLAGS-dir_linuxthreads.old := -DNOT_IN_libc -DIS_IN_libpthread -CFLAGS-libpthread/linuxthreads.old := $(CFLAGS-dir_linuxthreads.old) $(SSP_ALL_CFLAGS) - -ifeq ($(PTHREADS_DEBUG_SUPPORT),y) -LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs -else -LDFLAGS-libpthread.so := $(LDFLAGS) -endif -LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-libpthread.so := -Wl,--dsbt-index=10 - -LIBS-libpthread.so := $(LIBS) $(ldso) - -START_FILE-libpthread.so := $(SHARED_START_FILES) -END_FILE-libpthread.so := $(SHARED_END_FILES) - -libpthread_FULL_NAME := libpthread-$(VERSION).so - -libpthread_DIR := $(top_srcdir)libpthread/linuxthreads.old -libpthread_OUT := $(top_builddir)libpthread/linuxthreads.old - --include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch - -libpthread_SRC := \ - attr.c cancel.c condvar.c errno.c events.c join.c lockfile.c manager.c \ - mutex.c pt-machine.c ptfork.c pthread.c ptlongjmp.c \ - rwlock.c semaphore.c signals.c specific.c spinlock.c wrapsyscall.c -ifeq ($(UCLIBC_HAS_XLOCALE),y) -libpthread_SRC += locale.c -endif - -# remove generic sources, if arch specific version is present -ifneq ($(strip $(libpthread_ARCH_SRC)),) -libpthread_SRC := $(filter-out $(patsubst %.c,$(libpthread_DIR)/%.c,$(notdir $(libpthread_ARCH_SRC))),$(libpthread_SRC)) -endif - -libpthread_SRC := $(patsubst %,$(libpthread_DIR)/%,$(libpthread_SRC)) - -libpthread_OBJ := $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC)) - -# -# Stuff that goes into libc.so, not libpthread.so -# -CFLAGS-OMIT-forward.c := $(CFLAGS-dir_linuxthreads.old) -CFLAGS-OMIT-libc_pthread_init.c := $(CFLAGS-dir_linuxthreads.old) -libpthread_libc_CSRC := forward.c libc_pthread_init.c -libpthread_libc_OBJ := $(patsubst %.c, $(libpthread_OUT)/%.o,$(libpthread_libc_CSRC)) -libc-static-y += $(libpthread_OUT)/libc_pthread_init.o -libc-shared-y += $(libpthread_libc_OBJ:.o=.oS) - -ifeq ($(DOPIC),y) -libpthread-a-y += $(libpthread_OBJ:.o=.os) -else -libpthread-a-y += $(libpthread_OBJ) -endif -libpthread-so-y += $(libpthread_OBJ:.o=.oS) - -lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a -lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so - -#ifeq ($(DOMULTI),n) -$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend) - $(call link.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) -#else -#$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread.oS | $(libc.depend) -# $(call linkm.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) -#endif - -ifeq ($(PTHREADS_DEBUG_SUPPORT),y) -$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) -endif -$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y) - $(Q)$(RM) $@ - $(do_ar) - -ifeq ($(PTHREADS_DEBUG_SUPPORT),y) -$(libpthread_OUT)/libpthread.oS: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) -endif -$(libpthread_OUT)/libpthread.oS: $(libpthread_SRC) - $(Q)$(RM) $@ - $(compile-m) - -ifeq ($(PTHREADS_DEBUG_SUPPORT),y) -$(top_builddir)lib/libpthread.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) -endif -$(top_builddir)lib/libpthread.a: $(libpthread-a-y) - $(Q)$(INSTALL) -d $(dir $@) - $(Q)$(RM) $@ - $(do_ar) - -$(top_builddir)include/pthread.h: - $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/$(@F) $@ -$(top_builddir)include/semaphore.h: - $(do_ln) $(call rel_srcdir)$(PTDIR)/$(@F) $@ -$(top_builddir)include/bits/pthreadtypes.h: | $(top_builddir)include/bits - $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/bits/$(@F) $@ - -linuxthreads_headers := $(top_builddir)include/pthread.h \ - $(top_builddir)include/semaphore.h \ - $(top_builddir)include/bits/pthreadtypes.h -$(linuxthreads_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h)) -headers-$(UCLIBC_HAS_THREADS) += $(linuxthreads_headers) - -objclean-y += CLEAN_libpthread/linuxthreads.old -headers_clean-y += HEADERCLEAN_libpthread/linuxthreads.old -HEADERCLEAN_libpthread/linuxthreads.old: - $(do_rm) $(linuxthreads_headers) - -CLEAN_libpthread/linuxthreads.old: - $(do_rm) $(addprefix $(libpthread_OUT)/*., o os oS a) diff --git a/libpthread/linuxthreads.old/attr.c b/libpthread/linuxthreads.old/attr.c deleted file mode 100644 index 8465c234c..000000000 --- a/libpthread/linuxthreads.old/attr.c +++ /dev/null @@ -1,240 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* changed for uClibc */ -#define __sched_get_priority_min sched_get_priority_min -#define __sched_get_priority_max sched_get_priority_max - -/* Handling of thread attributes */ - -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/param.h> -#include "pthread.h" -#include "internals.h" - -libpthread_hidden_proto(pthread_attr_destroy) -libpthread_hidden_proto(pthread_attr_init) -libpthread_hidden_proto(pthread_attr_getdetachstate) -libpthread_hidden_proto(pthread_attr_setdetachstate) -libpthread_hidden_proto(pthread_attr_getinheritsched) -libpthread_hidden_proto(pthread_attr_setinheritsched) -libpthread_hidden_proto(pthread_attr_setschedparam) -libpthread_hidden_proto(pthread_attr_getschedparam) -libpthread_hidden_proto(pthread_attr_getschedpolicy) -libpthread_hidden_proto(pthread_attr_setschedpolicy) -libpthread_hidden_proto(pthread_attr_getscope) -libpthread_hidden_proto(pthread_attr_setscope) - -/* NOTE: With uClibc I don't think we need this versioning stuff. - * Therefore, define the function pthread_attr_init() here using - * a strong symbol. */ - -/*int __pthread_attr_init_2_1(pthread_attr_t *attr)*/ -int pthread_attr_init(pthread_attr_t *attr) -{ - size_t ps = getpagesize (); - - attr->__detachstate = PTHREAD_CREATE_JOINABLE; - attr->__schedpolicy = SCHED_OTHER; - attr->__schedparam.sched_priority = 0; - attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; - attr->__scope = PTHREAD_SCOPE_SYSTEM; - attr->__guardsize = ps; - attr->__stackaddr = NULL; - attr->__stackaddr_set = 0; - attr->__stacksize = STACK_SIZE - ps; - return 0; -} -libpthread_hidden_def(pthread_attr_init) - -/* uClibc: leave out this for now. */ -#if defined DO_PTHREAD_VERSIONING_WITH_UCLIBC -#if defined __PIC__ && defined DO_VERSIONING -default_symbol_version (__pthread_attr_init_2_1, pthread_attr_init, GLIBC_2.1); - -int __pthread_attr_init_2_0(pthread_attr_t *attr) -{ - attr->__detachstate = PTHREAD_CREATE_JOINABLE; - attr->__schedpolicy = SCHED_OTHER; - attr->__schedparam.sched_priority = 0; - attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; - attr->__scope = PTHREAD_SCOPE_SYSTEM; - return 0; -} -symbol_version (__pthread_attr_init_2_0, pthread_attr_init, GLIBC_2.0); -#else -strong_alias (__pthread_attr_init_2_1, pthread_attr_init) -#endif -#endif /* DO_PTHREAD_VERSIONING_WITH_UCLIBC */ - -int pthread_attr_destroy(pthread_attr_t *attr attribute_unused) -{ - return 0; -} -libpthread_hidden_def(pthread_attr_destroy) - - -int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) -{ - if (detachstate < PTHREAD_CREATE_JOINABLE || - detachstate > PTHREAD_CREATE_DETACHED) - return EINVAL; - attr->__detachstate = detachstate; - return 0; -} -libpthread_hidden_def(pthread_attr_setdetachstate) - -int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) -{ - *detachstate = attr->__detachstate; - return 0; -} -libpthread_hidden_def(pthread_attr_getdetachstate) - -int pthread_attr_setschedparam(pthread_attr_t *attr, - const struct sched_param *param) -{ - int max_prio = __sched_get_priority_max(attr->__schedpolicy); - int min_prio = __sched_get_priority_min(attr->__schedpolicy); - - if (param->sched_priority < min_prio || param->sched_priority > max_prio) - return EINVAL; - memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); - return 0; -} -libpthread_hidden_def(pthread_attr_setschedparam) - -int pthread_attr_getschedparam(const pthread_attr_t *attr, - struct sched_param *param) -{ - memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); - return 0; -} -libpthread_hidden_def(pthread_attr_getschedparam) - -int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) -{ - if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) - return EINVAL; - attr->__schedpolicy = policy; - return 0; -} -libpthread_hidden_def(pthread_attr_setschedpolicy) - -int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) -{ - *policy = attr->__schedpolicy; - return 0; -} -libpthread_hidden_def(pthread_attr_getschedpolicy) - -int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) -{ - if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) - return EINVAL; - attr->__inheritsched = inherit; - return 0; -} -libpthread_hidden_def(pthread_attr_setinheritsched) - -int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) -{ - *inherit = attr->__inheritsched; - return 0; -} -libpthread_hidden_def(pthread_attr_getinheritsched) - -int pthread_attr_setscope(pthread_attr_t *attr, int scope) -{ - switch (scope) { - case PTHREAD_SCOPE_SYSTEM: - attr->__scope = scope; - return 0; - case PTHREAD_SCOPE_PROCESS: - return ENOTSUP; - default: - return EINVAL; - } -} -libpthread_hidden_def(pthread_attr_setscope) - -int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) -{ - *scope = attr->__scope; - return 0; -} -libpthread_hidden_def(pthread_attr_getscope) - -int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) -{ - size_t ps = getpagesize (); - - /* First round up the guard size. */ - guardsize = roundup (guardsize, ps); - - /* The guard size must not be larger than the stack itself */ - if (guardsize >= attr->__stacksize) return EINVAL; - - attr->__guardsize = guardsize; - - return 0; -} -weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize) - -int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) -{ - *guardsize = attr->__guardsize; - return 0; -} -weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize) - -#if 0 /* uClibc: deprecated stuff disabled */ -int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) -{ - attr->__stackaddr = stackaddr; - attr->__stackaddr_set = 1; - return 0; -} -weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) - -int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) -{ - /* XXX This function has a stupid definition. The standard specifies - no error value but what is if no stack address was set? We simply - return the value we have in the member. */ - *stackaddr = attr->__stackaddr; - return 0; -} -weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) -#endif - -int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) -{ - /* We don't accept value smaller than PTHREAD_STACK_MIN. */ - if (stacksize < PTHREAD_STACK_MIN) - return EINVAL; - - attr->__stacksize = stacksize; - return 0; -} -weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) - -int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) -{ - *stacksize = attr->__stacksize; - return 0; -} -weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) diff --git a/libpthread/linuxthreads.old/cancel.c b/libpthread/linuxthreads.old/cancel.c deleted file mode 100644 index 392d1d586..000000000 --- a/libpthread/linuxthreads.old/cancel.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Thread cancellation */ - -#include <errno.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" -#ifdef __UCLIBC_HAS_RPC__ -#include <rpc/rpc.h> -extern void __rpc_thread_destroy(void); -#endif -#include <bits/stackinfo.h> - -#include <stdio.h> - -#ifdef _STACK_GROWS_DOWN -# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other) -#elif defined _STACK_GROWS_UP -# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) -#else -# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" -#endif - -libpthread_hidden_proto(pthread_setcancelstate) -libpthread_hidden_proto(pthread_setcanceltype) - -int pthread_setcancelstate(int state, int * oldstate) -{ - pthread_descr self = thread_self(); - if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) - return EINVAL; - if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate); - THREAD_SETMEM(self, p_cancelstate, state); - if (THREAD_GETMEM(self, p_canceled) && - THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && - THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - return 0; -} -libpthread_hidden_def(pthread_setcancelstate) - -int pthread_setcanceltype(int type, int * oldtype) -{ - pthread_descr self = thread_self(); - if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) - return EINVAL; - if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype); - THREAD_SETMEM(self, p_canceltype, type); - if (THREAD_GETMEM(self, p_canceled) && - THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && - THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - return 0; -} -libpthread_hidden_def(pthread_setcanceltype) - -int pthread_cancel(pthread_t thread) -{ - pthread_handle handle = thread_handle(thread); - int pid; - int dorestart = 0; - pthread_descr th; - pthread_extricate_if *pextricate; - int already_canceled; - - __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, thread)) { - __pthread_unlock(&handle->h_lock); - return ESRCH; - } - - th = handle->h_descr; - - already_canceled = th->p_canceled; - th->p_canceled = 1; - - if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { - __pthread_unlock(&handle->h_lock); - return 0; - } - - pextricate = th->p_extricate; - pid = th->p_pid; - - /* If the thread has registered an extrication interface, then - invoke the interface. If it returns 1, then we succeeded in - dequeuing the thread from whatever waiting object it was enqueued - with. In that case, it is our responsibility to wake it up. - And also to set the p_woken_by_cancel flag so the woken thread - can tell that it was woken by cancellation. */ - - if (pextricate != NULL) { - dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th); - th->p_woken_by_cancel = dorestart; - } - - __pthread_unlock(&handle->h_lock); - - /* If the thread has suspended or is about to, then we unblock it by - issuing a restart, instead of a cancel signal. Otherwise we send - the cancel signal to unblock the thread from a cancellation point, - or to initiate asynchronous cancellation. The restart is needed so - we have proper accounting of restarts; suspend decrements the thread's - resume count, and restart() increments it. This also means that suspend's - handling of the cancel signal is obsolete. */ - - if (dorestart) - restart(th); - else - kill(pid, __pthread_sig_cancel); - - return 0; -} - -void pthread_testcancel(void) -{ - pthread_descr self = thread_self(); - if (THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); -} - -void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, - void (*routine)(void *), void * arg) -{ - pthread_descr self = thread_self(); - buffer->__routine = routine; - buffer->__arg = arg; - buffer->__prev = THREAD_GETMEM(self, p_cleanup); - if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) - buffer->__prev = NULL; - THREAD_SETMEM(self, p_cleanup, buffer); -} - -void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, - int execute) -{ - pthread_descr self = thread_self(); - if (execute) buffer->__routine(buffer->__arg); - THREAD_SETMEM(self, p_cleanup, buffer->__prev); -} - -void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, - void (*routine)(void *), void * arg) -{ - pthread_descr self = thread_self(); - buffer->__routine = routine; - buffer->__arg = arg; - buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); - buffer->__prev = THREAD_GETMEM(self, p_cleanup); - if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) - buffer->__prev = NULL; - THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); - THREAD_SETMEM(self, p_cleanup, buffer); -} -strong_alias(_pthread_cleanup_push_defer,__pthread_cleanup_push_defer) - -void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, - int execute) -{ - pthread_descr self = thread_self(); - if (execute) buffer->__routine(buffer->__arg); - THREAD_SETMEM(self, p_cleanup, buffer->__prev); - THREAD_SETMEM(self, p_canceltype, buffer->__canceltype); - if (THREAD_GETMEM(self, p_canceled) && - THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && - THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); -} -strong_alias(_pthread_cleanup_pop_restore,__pthread_cleanup_pop_restore) - - -void __pthread_perform_cleanup(char *currentframe) -{ - pthread_descr self = thread_self(); - struct _pthread_cleanup_buffer * c; - - for (c = THREAD_GETMEM(self, p_cleanup); c != NULL; c = c->__prev) - { -#ifdef _STACK_GROWS_DOWN - if ((char *) c <= currentframe) - break; -#elif defined _STACK_GROWS_UP - if ((char *) c >= currentframe) - break; -#else -# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" -#endif - c->__routine(c->__arg); - } - -#ifdef __UCLIBC_HAS_RPC__ - /* And the TSD which needs special help. */ - if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL) - __rpc_thread_destroy (); -#endif -} - -#ifndef __PIC__ -/* We need a hook to force the cancellation wrappers to be linked in when - static libpthread is used. */ -extern const char __pthread_provide_wrappers; -static const char *const __pthread_require_wrappers = - &__pthread_provide_wrappers; -#endif diff --git a/libpthread/linuxthreads.old/condvar.c b/libpthread/linuxthreads.old/condvar.c deleted file mode 100644 index 35daacf15..000000000 --- a/libpthread/linuxthreads.old/condvar.c +++ /dev/null @@ -1,304 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* and Pavel Krauz (krauz@fsid.cvut.cz). */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Condition variables */ - -#include <errno.h> -#include <sched.h> -#include <stddef.h> -#include <sys/time.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "queue.h" -#include "restart.h" - -int pthread_cond_init(pthread_cond_t *cond, - const pthread_condattr_t *cond_attr attribute_unused) -{ - __pthread_init_lock(&cond->__c_lock); - cond->__c_waiting = NULL; - return 0; -} -libpthread_hidden_def(pthread_cond_init) - -int pthread_cond_destroy(pthread_cond_t *cond) -{ - if (cond->__c_waiting != NULL) return EBUSY; - return 0; -} -libpthread_hidden_def(pthread_cond_destroy) - -/* Function called by pthread_cancel to remove the thread from - waiting on a condition variable queue. */ - -static int cond_extricate_func(void *obj, pthread_descr th) -{ - volatile pthread_descr self = thread_self(); - pthread_cond_t *cond = obj; - int did_remove = 0; - - __pthread_lock(&cond->__c_lock, self); - did_remove = remove_from_queue(&cond->__c_waiting, th); - __pthread_unlock(&cond->__c_lock); - - return did_remove; -} - -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 - canceled. If the thread is canceled, then it will fall through the - suspend call below, and then call pthread_exit without - having to worry about whether it is still on the condition variable queue. - This depends on pthread_cancel setting p_canceled before calling the - extricate function. */ - - __pthread_lock(&cond->__c_lock, self); - if (!(THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) - enqueue(&cond->__c_waiting, self); - else - already_canceled = 1; - __pthread_unlock(&cond->__c_lock); - - if (already_canceled) { - __pthread_set_own_extricate_if(self, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - __pthread_mutex_unlock(mutex); - - 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 - point behavior */ - - if (THREAD_GETMEM(self, p_woken_by_cancel) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { - THREAD_SETMEM(self, p_woken_by_cancel, 0); - __pthread_mutex_lock(mutex); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - /* Put back any resumes we caught that don't belong to us. */ - while (spurious_wakeup_count--) - restart(self); - - __pthread_mutex_lock(mutex); - return 0; -} -libpthread_hidden_def(pthread_cond_wait) - -static int -pthread_cond_timedwait_relative(pthread_cond_t *cond, - pthread_mutex_t *mutex, - const struct timespec * abstime) -{ - volatile pthread_descr self = thread_self(); - int already_canceled = 0; - 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. */ - __pthread_lock(&cond->__c_lock, self); - if (!(THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) - enqueue(&cond->__c_waiting, self); - else - already_canceled = 1; - __pthread_unlock(&cond->__c_lock); - - if (already_canceled) { - __pthread_set_own_extricate_if(self, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - __pthread_mutex_unlock(mutex); - - spurious_wakeup_count = 0; - while (1) - { - if (!timedsuspend(self, abstime)) { - int was_on_queue; - - /* __pthread_lock will queue back any spurious restarts that - may happen to it. */ - - __pthread_lock(&cond->__c_lock, self); - was_on_queue = remove_from_queue(&cond->__c_waiting, self); - __pthread_unlock(&cond->__c_lock); - - if (was_on_queue) { - __pthread_set_own_extricate_if(self, 0); - __pthread_mutex_lock(mutex); - return ETIMEDOUT; - } - - /* Eat the outstanding restart() from the signaller */ - 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); - - /* The remaining logic is the same as in other cancellable waits, - such as pthread_join sem_wait or pthread_cond wait. */ - - if (THREAD_GETMEM(self, p_woken_by_cancel) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { - THREAD_SETMEM(self, p_woken_by_cancel, 0); - __pthread_mutex_lock(mutex); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - /* Put back any resumes we caught that don't belong to us. */ - while (spurious_wakeup_count--) - restart(self); - - __pthread_mutex_lock(mutex); - return 0; -} - -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); -} -libpthread_hidden_def(pthread_cond_timedwait) - -int pthread_cond_signal(pthread_cond_t *cond) -{ - pthread_descr th; - - __pthread_lock(&cond->__c_lock, NULL); - th = dequeue(&cond->__c_waiting); - __pthread_unlock(&cond->__c_lock); - if (th != NULL) { - th->p_condvar_avail = 1; - WRITE_MEMORY_BARRIER(); - restart(th); - } - return 0; -} -libpthread_hidden_def(pthread_cond_signal) - -int pthread_cond_broadcast(pthread_cond_t *cond) -{ - pthread_descr tosignal, th; - - __pthread_lock(&cond->__c_lock, NULL); - /* Copy the current state of the waiting queue and empty it */ - tosignal = cond->__c_waiting; - cond->__c_waiting = NULL; - __pthread_unlock(&cond->__c_lock); - /* Now signal each process in the queue */ - while ((th = dequeue(&tosignal)) != NULL) { - th->p_condvar_avail = 1; - WRITE_MEMORY_BARRIER(); - restart(th); - } - return 0; -} -libpthread_hidden_def(pthread_cond_broadcast) - -int pthread_condattr_init(pthread_condattr_t *attr attribute_unused) -{ - return 0; -} -libpthread_hidden_def(pthread_condattr_init) - -int pthread_condattr_destroy(pthread_condattr_t *attr attribute_unused) -{ - return 0; -} -libpthread_hidden_def(pthread_condattr_destroy) - -int pthread_condattr_getpshared (const pthread_condattr_t *attr attribute_unused, int *pshared) -{ - *pshared = PTHREAD_PROCESS_PRIVATE; - return 0; -} - -int pthread_condattr_setpshared (pthread_condattr_t *attr attribute_unused, int pshared) -{ - if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) - return EINVAL; - - /* For now it is not possible to shared a conditional variable. */ - if (pshared != PTHREAD_PROCESS_PRIVATE) - return ENOSYS; - - return 0; -} diff --git a/libpthread/linuxthreads.old/debug.h b/libpthread/linuxthreads.old/debug.h deleted file mode 100644 index 76779dad9..000000000 --- a/libpthread/linuxthreads.old/debug.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** -** -** NAME: -** debug.h -** -** DESCRIPTION: -** This header file defines the debug macros used in pthreads. To turn -** debugging on, add -DDEBUG_PT to CFLAGS. It was added to the original -** distribution of linuxthreads. -** -** This program 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. -** -** This program 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. -** -****************************************************************************/ - -#ifndef _PT_DEBUG_H -#define _PT_DEBUG_H - -#include <features.h> - -#ifdef __DODEBUG_PT__ -# define DEBUG_PT -#endif - -/* define the PDEBUG macro here */ -#undef PDEBUG -#ifdef DEBUG_PT -# define PDEBUG(fmt, args...) __pthread_message("%s: " fmt, __FUNCTION__, ## args) -#else -# define PDEBUG(fmt, args...) /* debug switched off */ -#endif - -#endif /* _PT_DEBUG_H */ diff --git a/libpthread/linuxthreads.old/errno.c b/libpthread/linuxthreads.old/errno.c deleted file mode 100644 index 748c1d512..000000000 --- a/libpthread/linuxthreads.old/errno.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Define the location of errno for the remainder of the C library */ - -#include <errno.h> -#include <netdb.h> -#include "pthread.h" -#include "internals.h" -#include <stdio.h> - -int * -__errno_location (void) -{ - pthread_descr self = thread_self(); - return THREAD_GETMEM (self, p_errnop); -} - -int * -__h_errno_location (void) -{ - pthread_descr self = thread_self(); - return THREAD_GETMEM (self, p_h_errnop); -} diff --git a/libpthread/linuxthreads.old/events.c b/libpthread/linuxthreads.old/events.c deleted file mode 100644 index 2a76f91d4..000000000 --- a/libpthread/linuxthreads.old/events.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Event functions used while debugging. - Copyright (C) 1999 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, - see <http://www.gnu.org/licenses/>. */ - -/* The functions contained here do nothing, they just return. */ - -#include "internals.h" - -void -__linuxthreads_create_event (void) -{ -} - -void -__linuxthreads_death_event (void) -{ -} - -void -__linuxthreads_reap_event (void) -{ -} diff --git a/libpthread/linuxthreads.old/forward.c b/libpthread/linuxthreads.old/forward.c deleted file mode 100644 index 5a1771b90..000000000 --- a/libpthread/linuxthreads.old/forward.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright (C) 2002, 2003 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, see - <http://www.gnu.org/licenses/>. */ - -#include <features.h> -#include <stdlib.h> -#include <dlfcn.h> - -/* psm: keep this before internals.h */ -#if 0 -vda: here is why: -headers contain libc_hidden_proto(foo). -In libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h -adding libc_hidden_proto(foo) just before weak_extern (__pthread_initialize) -will not warn: - /* libc_hidden_proto(foo) */ - weak_extern (__pthread_initialize) - /* libc_hidden_proto(foo) */ -but adding after will! Which is extremely strange - -weak_extern expands into just "#pragma weak __pthread_initialize". -TODO: determine whether it is a gcc bug or what -(see gcc.gnu.org/PR36282). -For now, just include all headers before internals.h -(they are again included in internals.h - maybe remove them there later) -#endif - -#include <string.h> -#include <limits.h> -#include <setjmp.h> -#include <signal.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/time.h> - -#include "internals.h" - -/* Pointers to the libc functions. */ -struct pthread_functions __libc_pthread_functions attribute_hidden; - - -# define FORWARD2(name, rettype, decl, params, defaction) \ -rettype \ -name decl \ -{ \ - if (__libc_pthread_functions.ptr_##name == NULL) \ - defaction; \ - \ - return __libc_pthread_functions.ptr_##name params; \ -} - -# define FORWARD(name, decl, params, defretval) \ - FORWARD2 (name, int, decl, params, return defretval) - -FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) - -FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0) - -FORWARD (pthread_attr_getdetachstate, - (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), - 0) -FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), - (attr, detachstate), 0) - -FORWARD (pthread_attr_getinheritsched, - (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) -FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), - (attr, inherit), 0) - -FORWARD (pthread_attr_getschedparam, - (const pthread_attr_t *attr, struct sched_param *param), - (attr, param), 0) -FORWARD (pthread_attr_setschedparam, - (pthread_attr_t *attr, const struct sched_param *param), - (attr, param), 0) - -FORWARD (pthread_attr_getschedpolicy, - (const pthread_attr_t *attr, int *policy), (attr, policy), 0) -FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), - (attr, policy), 0) - -FORWARD (pthread_attr_getscope, - (const pthread_attr_t *attr, int *scope), (attr, scope), 0) -FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), - (attr, scope), 0) - - -FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) -FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) - - -FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) - -FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) - -FORWARD (pthread_cond_init, - (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), - (cond, cond_attr), 0) - -FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) - -FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), - (cond, mutex), 0) - -FORWARD (pthread_cond_timedwait, - (pthread_cond_t *cond, pthread_mutex_t *mutex, - const struct timespec *abstime), (cond, mutex, abstime), 0) - - -FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), - (thread1, thread2), 1) - - -/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ -FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) -strong_alias (__pthread_exit, pthread_exit) - - -FORWARD (pthread_getschedparam, - (pthread_t target_thread, int *policy, struct sched_param *param), - (target_thread, policy, param), 0) -FORWARD (pthread_setschedparam, - (pthread_t target_thread, int policy, - const struct sched_param *param), (target_thread, policy, param), 0) - - -FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) - -FORWARD (pthread_mutex_init, - (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), - (mutex, mutexattr), 0) -strong_alias(pthread_mutex_init, __pthread_mutex_init) - -FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) -strong_alias(pthread_mutex_lock, __pthread_mutex_lock) - -FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) -strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) - -FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) -strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) - -FORWARD2 (pthread_self, pthread_t, (void), (), return 0) - - -FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), - 0) - -FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) - -#if 0 -FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) -#endif -FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) - -#if 0 -FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) -#endif -FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) diff --git a/libpthread/linuxthreads.old/internals.h b/libpthread/linuxthreads.old/internals.h deleted file mode 100644 index ea274d824..000000000 --- a/libpthread/linuxthreads.old/internals.h +++ /dev/null @@ -1,529 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -#ifndef _INTERNALS_H -#define _INTERNALS_H 1 - -/* Internal data structures */ - -/* Includes */ - -#include <bits/libc-tsd.h> /* for _LIBC_TSD_KEY_N */ -#include <limits.h> -#include <setjmp.h> -#include <signal.h> -#include <unistd.h> -#include <bits/stackinfo.h> -#include <sys/types.h> -#include <sys/wait.h> -#include "pt-machine.h" -#include "semaphore.h" -#include "../linuxthreads.old_db/thread_dbP.h" -#ifdef __UCLIBC_HAS_XLOCALE__ -#include <bits/uClibc_locale.h> -#endif /* __UCLIBC_HAS_XLOCALE__ */ - -/* Use a funky version in a probably vein attempt at preventing gdb - * from dlopen()'ing glibc's libthread_db library... */ -#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) - -#ifndef THREAD_GETMEM -# define THREAD_GETMEM(descr, member) descr->member -#endif -#ifndef THREAD_GETMEM_NC -# define THREAD_GETMEM_NC(descr, member) descr->member -#endif -#ifndef THREAD_SETMEM -# define THREAD_SETMEM(descr, member, value) descr->member = (value) -#endif -#ifndef THREAD_SETMEM_NC -# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value) -#endif - -/* Arguments passed to thread creation routine */ - -struct pthread_start_args { - void * (*start_routine)(void *); /* function to run */ - void * arg; /* its argument */ - sigset_t mask; /* initial signal mask for thread */ - int schedpolicy; /* initial scheduling policy (if any) */ - struct sched_param schedparam; /* initial scheduling parameters (if any) */ -}; - - -/* We keep thread specific data in a special data structure, a two-level - array. The top-level array contains pointers to dynamically allocated - arrays of a certain number of data pointers. So we can implement a - sparse array. Each dynamic second-level array has - PTHREAD_KEY_2NDLEVEL_SIZE - entries. This value shouldn't be too large. */ -#define PTHREAD_KEY_2NDLEVEL_SIZE 32 - -/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE - keys in each subarray. */ -#define PTHREAD_KEY_1STLEVEL_SIZE \ - ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ - / PTHREAD_KEY_2NDLEVEL_SIZE) - -typedef void (*destr_function)(void *); - -struct pthread_key_struct { - int in_use; /* already allocated? */ - destr_function destr; /* destruction routine */ -}; - - -#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, {{0, }}, 0, { 0 } } - -/* The type of thread descriptors */ - -typedef struct _pthread_descr_struct * pthread_descr; - -/* Callback interface for removing the thread from waiting on an - object if it is cancelled while waiting or about to wait. - This hold a pointer to the object, and a pointer to a function - which ``extricates'' the thread from its enqueued state. - The function takes two arguments: pointer to the wait object, - and a pointer to the thread. It returns 1 if an extrication - actually occured, and hence the thread must also be signalled. - It returns 0 if the thread had already been extricated. */ - -typedef struct _pthread_extricate_struct { - void *pu_object; - int (*pu_extricate_func)(void *, pthread_descr); -} pthread_extricate_if; - -/* Atomic counter made possible by compare_and_swap */ - -struct pthread_atomic { - long p_count; - int p_spinlock; -}; - -/* Context info for read write locks. The pthread_rwlock_info structure - is information about a lock that has been read-locked by the thread - in whose list this structure appears. The pthread_rwlock_context - is embedded in the thread context and contains a pointer to the - head of the list of lock info structures, as well as a count of - read locks that are untracked, because no info structure could be - allocated for them. */ - -struct _pthread_rwlock_t; - -typedef struct _pthread_rwlock_info { - struct _pthread_rwlock_info *pr_next; - struct _pthread_rwlock_t *pr_lock; - int pr_lock_count; -} pthread_readlock_info; - -struct _pthread_descr_struct { - pthread_descr p_nextlive, p_prevlive; - /* Double chaining of active threads */ - pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */ - pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */ - pthread_t p_tid; /* Thread identifier */ - int p_pid; /* PID of Unix process */ - int p_priority; /* Thread priority (== 0 if not realtime) */ - struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */ - int p_signal; /* last signal received */ - sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */ - sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */ - char p_terminated; /* true if terminated e.g. by pthread_exit */ - char p_detached; /* true if detached */ - char p_exited; /* true if the assoc. process terminated */ - void * p_retval; /* placeholder for return value */ - int p_retcode; /* placeholder for return code */ - pthread_descr p_joining; /* thread joining on that thread or NULL */ - struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */ - char p_cancelstate; /* cancellation state */ - char p_canceltype; /* cancellation type (deferred/async) */ - char p_canceled; /* cancellation request pending */ - int * p_errnop; /* pointer to used errno variable */ - int p_errno; /* error returned by last system call */ - int * p_h_errnop; /* pointer to used h_errno variable */ - int p_h_errno; /* error returned by last netdb function */ - char * p_in_sighandler; /* stack address of sighandler, or NULL */ - char p_sigwaiting; /* true if a sigwait() is in progress */ - struct pthread_start_args p_start_args; /* arguments for thread creation */ - void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ - void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ - int p_userstack; /* nonzero if the user provided the stack */ - void *p_guardaddr; /* address of guard area or NULL */ - size_t p_guardsize; /* size of guard area */ - pthread_descr p_self; /* Pointer to this structure */ - int p_nr; /* Index of descriptor in __pthread_handles */ - int p_report_events; /* Nonzero if events must be reported. */ - td_eventbuf_t p_eventbuf; /* Data for event. */ - struct pthread_atomic p_resume_count; /* number of times restart() was - called on thread */ - char p_woken_by_cancel; /* cancellation performed wakeup */ - char p_condvar_avail; /* flag if conditional variable became avail */ - char p_sem_avail; /* flag if semaphore became available */ - pthread_extricate_if *p_extricate; /* See above */ - pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ - pthread_readlock_info *p_readlock_free; /* Free list of structs */ - int p_untracked_readlock_count; /* Readlocks not tracked by list */ - /* New elements must be added at the end. */ -#ifdef __UCLIBC_HAS_XLOCALE__ - __locale_t locale; /* thread-specific locale from uselocale() only! */ -#endif /* __UCLIBC_HAS_XLOCALE__ */ -} __attribute__ ((aligned(32))); /* We need to align the structure so that - doubles are aligned properly. This is 8 - bytes on MIPS and 16 bytes on MIPS64. - 32 bytes might give better cache - utilization. */ - -/* The type of thread handles. */ - -typedef struct pthread_handle_struct * pthread_handle; - -struct pthread_handle_struct { - struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */ - pthread_descr h_descr; /* Thread descriptor or NULL if invalid */ - char * h_bottom; /* Lowest address in the stack thread */ -}; - -/* The type of messages sent to the thread manager thread */ - -struct pthread_request { - pthread_descr req_thread; /* Thread doing the request */ - enum { /* Request kind */ - REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, - REQ_POST, REQ_DEBUG, REQ_KICK - } req_kind; - union { /* Arguments for request */ - struct { /* For REQ_CREATE: */ - const pthread_attr_t * attr; /* thread attributes */ - void * (*fn)(void *); /* start function */ - void * arg; /* argument to start function */ - sigset_t mask; /* signal mask */ - } create; - struct { /* For REQ_FREE: */ - pthread_t thread_id; /* identifier of thread to free */ - } free; - struct { /* For REQ_PROCESS_EXIT: */ - int code; /* exit status */ - } exit; - void * post; /* For REQ_POST: the semaphore */ - } req_args; -}; - - -/* Signals used for suspend/restart and for cancellation notification. */ - -extern int __pthread_sig_restart; -extern int __pthread_sig_cancel; - -/* Signal used for interfacing with gdb */ - -extern int __pthread_sig_debug; - -/* Global array of thread handles, used for validating a thread id - and retrieving the corresponding thread descriptor. Also used for - mapping the available stack segments. */ - -extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; - -/* Descriptor of the initial thread */ - -extern struct _pthread_descr_struct __pthread_initial_thread; - -/* Descriptor of the manager thread */ - -extern struct _pthread_descr_struct __pthread_manager_thread; - -/* Descriptor of the main thread */ - -extern pthread_descr __pthread_main_thread; - -/* Limit between the stack of the initial thread (above) and the - stacks of other threads (below). Aligned on a STACK_SIZE boundary. - Initially 0, meaning that the current thread is (by definition) - the initial thread. */ - -extern char *__pthread_initial_thread_bos; -#ifndef __ARCH_USE_MMU__ -/* For non-MMU systems, we have no idea the bounds of the initial thread - * stack, so we have to track it on the fly relative to other stacks. Do - * so by scaling back our assumptions on the limits of the bos/tos relative - * to the known mid point. See also the comments in pthread_initialize(). */ -extern char *__pthread_initial_thread_tos, *__pthread_initial_thread_mid; -#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) \ - do { \ - char *__tos = (tos); \ - char *__bos = (bos); \ - if (__tos >= __pthread_initial_thread_bos && \ - __bos < __pthread_initial_thread_tos) { \ - if (__bos < __pthread_initial_thread_mid) \ - __pthread_initial_thread_bos = __tos; \ - else \ - __pthread_initial_thread_tos = __bos; \ - } \ - } while (0) -#else -#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) /* empty */ -#endif /* __ARCH_USE_MMU__ */ - - -/* Indicate whether at least one thread has a user-defined stack (if 1), - or all threads have stacks supplied by LinuxThreads (if 0). */ - -extern int __pthread_nonstandard_stacks; - -/* File descriptor for sending requests to the thread manager. - Initially -1, meaning that __pthread_initialize_manager must be called. */ - -extern int __pthread_manager_request; - -/* Other end of the pipe for sending requests to the thread manager. */ - -extern int __pthread_manager_reader; - -/* Limits of the thread manager stack. */ - -extern char *__pthread_manager_thread_bos; -extern char *__pthread_manager_thread_tos; - -/* Pending request for a process-wide exit */ - -extern int __pthread_exit_requested, __pthread_exit_code; - -/* Set to 1 by gdb if we're debugging */ - -extern volatile int __pthread_threads_debug; - -/* Globally enabled events. */ -extern volatile td_thr_events_t __pthread_threads_events; - -/* Pointer to descriptor of thread with last event. */ -extern volatile pthread_descr __pthread_last_event; - -/* Return the handle corresponding to a thread id */ - -static __inline__ pthread_handle thread_handle(pthread_t id) -{ - return &__pthread_handles[id % PTHREAD_THREADS_MAX]; -} - -/* Validate a thread handle. Must have acquired h->h_spinlock before. */ - -static __inline__ int invalid_handle(pthread_handle h, pthread_t id) -{ - return h->h_descr == NULL || h->h_descr->p_tid != id; -} - -/* Fill in defaults left unspecified by pt-machine.h. */ - -/* The page size we can get from the system. This should likely not be - changed by the machine file but, you never know. */ -#define __PAGE_SIZE (sysconf (_SC_PAGESIZE)) - -/* The max size of the thread stack segments. If the default - THREAD_SELF implementation is used, this must be a power of two and - a multiple of __PAGE_SIZE. */ -#ifndef STACK_SIZE -#ifdef __ARCH_USE_MMU__ -#define STACK_SIZE (2 * 1024 * 1024) -#else -#define STACK_SIZE (4 * __PAGE_SIZE) -#endif -#endif - -/* The initial size of the thread stack. Must be a multiple of __PAGE_SIZE. */ -#ifndef INITIAL_STACK_SIZE -#define INITIAL_STACK_SIZE (4 * __PAGE_SIZE) -#endif - -/* Size of the thread manager stack. The "- 32" avoids wasting space - with some malloc() implementations. */ -#ifndef THREAD_MANAGER_STACK_SIZE -#define THREAD_MANAGER_STACK_SIZE (2 * __PAGE_SIZE - 32) -#endif - -/* The base of the "array" of thread stacks. The array will grow down from - here. Defaults to the calculated bottom of the initial application - stack. */ -#ifndef THREAD_STACK_START_ADDRESS -#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos -#endif - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#ifndef CURRENT_STACK_FRAME -#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) -#endif - -/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the - architecture doesn't need a memory barrier instruction (e.g. Intel - x86). Still we need the compiler to respect the barrier and emit - all outstanding operations which modify memory. Some architectures - distinguish between full, read and write barriers. */ -#ifndef MEMORY_BARRIER -#define MEMORY_BARRIER() __asm__ ("" : : : "memory") -#endif -#ifndef READ_MEMORY_BARRIER -#define READ_MEMORY_BARRIER() MEMORY_BARRIER() -#endif -#ifndef WRITE_MEMORY_BARRIER -#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER() -#endif - -/* Recover thread descriptor for the current thread */ - -extern pthread_descr __pthread_find_self (void) __attribute__ ((const)) attribute_hidden; - -static __inline__ pthread_descr thread_self (void) __attribute__ ((const)); -static __inline__ pthread_descr thread_self (void) -{ -#ifdef THREAD_SELF - return THREAD_SELF; -#else - char *sp = CURRENT_STACK_FRAME; -#ifdef __ARCH_USE_MMU__ - if (sp >= __pthread_initial_thread_bos) - return &__pthread_initial_thread; - else if (sp >= __pthread_manager_thread_bos - && sp < __pthread_manager_thread_tos) - return &__pthread_manager_thread; - else if (__pthread_nonstandard_stacks) - return __pthread_find_self(); - else - return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; -#else - /* For non-MMU we need to be more careful about the initial thread stack. - * We refine the initial thread stack bounds dynamically as we allocate - * the other stack frame such that it doesn't overlap with them. Then - * we can be sure to pick the right thread according to the current SP */ - - /* Since we allow other stack frames to be above or below, we need to - * treat this case special. When pthread_initialize() wasn't called yet, - * only the initial thread is there. */ - if (__pthread_initial_thread_bos == NULL) { - return &__pthread_initial_thread; - } - else if (sp >= __pthread_initial_thread_bos - && sp < __pthread_initial_thread_tos) { - return &__pthread_initial_thread; - } - else if (sp >= __pthread_manager_thread_bos - && sp < __pthread_manager_thread_tos) { - return &__pthread_manager_thread; - } - else { - return __pthread_find_self(); - } -#endif /* __ARCH_USE_MMU__ */ -#endif -} - -/* Max number of times we must spin on a spinlock calling sched_yield(). - After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ - -#ifndef MAX_SPIN_COUNT -#define MAX_SPIN_COUNT 50 -#endif - -/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock - after MAX_SPIN_COUNT iterations of sched_yield(). - With the 2.0 and 2.1 kernels, this MUST BE > 2ms. - (Otherwise the kernel does busy-waiting for realtime threads, - giving other threads no chance to run.) */ - -#ifndef SPIN_SLEEP_DURATION -#define SPIN_SLEEP_DURATION 2000001 -#endif - -/* Defined and used in libc.so. */ -extern int __libc_multiple_threads attribute_hidden; -extern int __librt_multiple_threads; - -/* Internal global functions */ - -void __pthread_do_exit (void *retval, char *currentframe) - __attribute__ ((__noreturn__)) attribute_hidden; -void __pthread_destroy_specifics(void) attribute_hidden; -void __pthread_perform_cleanup(char *currentframe) attribute_hidden; -int __pthread_initialize_manager(void) attribute_hidden; -void __pthread_message(char * fmt, ...) - __attribute__ ((__format__ (printf, 1, 2))) attribute_hidden; -int __pthread_manager(void *reqfd) attribute_hidden; -int __pthread_manager_event(void *reqfd) attribute_hidden; -void __pthread_manager_sighandler(int sig) attribute_hidden; -void __pthread_reset_main_thread(void) attribute_hidden; -void __fresetlockfiles(void) attribute_hidden; -void __pthread_manager_adjust_prio(int thread_prio) attribute_hidden; -void __pthread_initialize_minimal (void); - -extern void __pthread_exit (void *retval) -#if defined NOT_IN_libc && defined IS_IN_libpthread - attribute_noreturn -#endif - ; - -extern int __pthread_attr_setguardsize(pthread_attr_t *__attr, - size_t __guardsize) attribute_hidden; -extern int __pthread_attr_getguardsize(const pthread_attr_t *__attr, - size_t *__guardsize) attribute_hidden; -extern int __pthread_attr_setstackaddr(pthread_attr_t *__attr, - void *__stackaddr) attribute_hidden; -extern int __pthread_attr_getstackaddr(const pthread_attr_t *__attr, - void **__stackaddr) attribute_hidden; -extern int __pthread_attr_setstacksize(pthread_attr_t *__attr, - size_t __stacksize) attribute_hidden; -extern int __pthread_attr_getstacksize(const pthread_attr_t *__attr, - size_t *__stacksize) attribute_hidden; -extern int __pthread_getconcurrency(void) attribute_hidden; -extern int __pthread_setconcurrency(int __level) attribute_hidden; -extern void __pthread_kill_other_threads_np(void) attribute_hidden; - -extern void __pthread_restart_old(pthread_descr th) attribute_hidden; -extern void __pthread_suspend_old(pthread_descr self) attribute_hidden; -extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) attribute_hidden; - -extern void __pthread_restart_new(pthread_descr th) attribute_hidden; -extern void __pthread_suspend_new(pthread_descr self) attribute_hidden; -extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) attribute_hidden; - -extern void __pthread_wait_for_restart_signal(pthread_descr self) attribute_hidden; - -/* Global pointers to old or new suspend functions */ - -extern void (*__pthread_restart)(pthread_descr) attribute_hidden; -extern void (*__pthread_suspend)(pthread_descr) attribute_hidden; - -#if defined NOT_IN_libc && defined IS_IN_libpthread -extern __typeof(pthread_mutex_init) __pthread_mutex_init attribute_hidden; -extern __typeof(pthread_mutex_destroy) __pthread_mutex_destroy attribute_hidden; -extern __typeof(pthread_mutex_lock) __pthread_mutex_lock attribute_hidden; -extern __typeof(pthread_mutex_trylock) __pthread_mutex_trylock attribute_hidden; -extern __typeof(pthread_mutex_unlock) __pthread_mutex_unlock attribute_hidden; -#endif - -/* Prototypes for some of the new semaphore functions. */ -/*extern int __new_sem_post (sem_t * sem);*/ - -/* TSD. */ -extern int __pthread_internal_tsd_set (int key, const void * pointer); -extern void * __pthread_internal_tsd_get (int key); -extern void ** __attribute__ ((__const__)) - __pthread_internal_tsd_address (int key); - -/* The functions called the signal events. */ -extern void __linuxthreads_create_event (void) attribute_hidden; -extern void __linuxthreads_death_event (void) attribute_hidden; -extern void __linuxthreads_reap_event (void) attribute_hidden; - -#include <pthread-functions.h> - -#endif /* internals.h */ diff --git a/libpthread/linuxthreads.old/join.c b/libpthread/linuxthreads.old/join.c deleted file mode 100644 index 4a7c0d8ac..000000000 --- a/libpthread/linuxthreads.old/join.c +++ /dev/null @@ -1,231 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Thread termination and joining */ - -#include <features.h> -#include <errno.h> -#include <sched.h> -#include <unistd.h> -#include <stdlib.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" -#include "debug.h" /* PDEBUG, added by StS */ - -libpthread_hidden_proto(pthread_exit) -void pthread_exit(void * retval) -{ - __pthread_do_exit (retval, CURRENT_STACK_FRAME); -} -libpthread_hidden_def (pthread_exit) - -void __pthread_do_exit(void *retval, char *currentframe) -{ - pthread_descr self = thread_self(); - pthread_descr joining; - struct pthread_request request; - PDEBUG("self=%p, pid=%d\n", self, self->p_pid); - - /* obey POSIX behavior and prevent cancellation functions from - * being called more than once. - * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html - */ - THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE); - THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); - - /* Call cleanup functions and destroy the thread-specific data */ - __pthread_perform_cleanup(currentframe); - __pthread_destroy_specifics(); - /* Store return value */ - __pthread_lock(THREAD_GETMEM(self, p_lock), self); - THREAD_SETMEM(self, p_retval, retval); - /* See whether we have to signal the death. */ - if (THREAD_GETMEM(self, p_report_events)) - { - /* See whether TD_DEATH is in any of the mask. */ - int idx = __td_eventword (TD_DEATH); - uint32_t mask = __td_eventmask (TD_DEATH); - - if ((mask & (__pthread_threads_events.event_bits[idx] - | THREAD_GETMEM_NC(self, - p_eventbuf.eventmask).event_bits[idx])) - != 0) - { - /* Yep, we have to signal the death. */ - THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH); - THREAD_SETMEM(self, p_eventbuf.eventdata, self); - __pthread_last_event = self; - - /* Now call the function to signal the event. */ - __linuxthreads_death_event(); - } - } - /* Say that we've terminated */ - THREAD_SETMEM(self, p_terminated, 1); - /* See if someone is joining on us */ - joining = THREAD_GETMEM(self, p_joining); - PDEBUG("joining = %p, pid=%d\n", joining, joining ? joining->p_pid : 0); - __pthread_unlock(THREAD_GETMEM(self, p_lock)); - /* Restart joining thread if any */ - if (joining != NULL) restart(joining); - /* If this is the initial thread, block until all threads have terminated. - If another thread calls exit, we'll be terminated from our signal - handler. */ - if (self == __pthread_main_thread && __pthread_manager_request >= 0) { - request.req_thread = self; - request.req_kind = REQ_MAIN_THREAD_EXIT; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *)&request, sizeof(request))); - suspend(self); - /* Main thread flushes stdio streams and runs atexit functions. - * It also calls a handler within LinuxThreads which sends a process exit - * request to the thread manager. */ - exit(0); - } - /* Exit the process (but don't flush stdio streams, and don't run - atexit functions). */ - _exit(0); -} - -/* Function called by pthread_cancel to remove the thread from - waiting on a condition variable queue. */ - -static int join_extricate_func(void *obj, pthread_descr th attribute_unused) -{ - volatile pthread_descr self = thread_self(); - pthread_handle handle = obj; - pthread_descr jo; - int did_remove = 0; - - __pthread_lock(&handle->h_lock, self); - jo = handle->h_descr; - did_remove = jo->p_joining != NULL; - jo->p_joining = NULL; - __pthread_unlock(&handle->h_lock); - - return did_remove; -} - -int pthread_join(pthread_t thread_id, void ** thread_return) -{ - volatile pthread_descr self = thread_self(); - struct pthread_request request; - pthread_handle handle = thread_handle(thread_id); - pthread_descr th; - pthread_extricate_if extr; - int already_canceled = 0; - PDEBUG("\n"); - - /* Set up extrication interface */ - extr.pu_object = handle; - extr.pu_extricate_func = join_extricate_func; - - __pthread_lock(&handle->h_lock, self); - if (invalid_handle(handle, thread_id)) { - __pthread_unlock(&handle->h_lock); - return ESRCH; - } - th = handle->h_descr; - if (th == self) { - __pthread_unlock(&handle->h_lock); - return EDEADLK; - } - /* If detached or already joined, error */ - if (th->p_detached || th->p_joining != NULL) { - __pthread_unlock(&handle->h_lock); - return EINVAL; - } - /* If not terminated yet, suspend ourselves. */ - if (! th->p_terminated) { - /* Register extrication interface */ - __pthread_set_own_extricate_if(self, &extr); - if (!(THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) - th->p_joining = self; - else - already_canceled = 1; - __pthread_unlock(&handle->h_lock); - - if (already_canceled) { - __pthread_set_own_extricate_if(self, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - PDEBUG("before suspend\n"); - suspend(self); - PDEBUG("after suspend\n"); - /* Deregister extrication interface */ - __pthread_set_own_extricate_if(self, 0); - - /* This is a cancellation point */ - if (THREAD_GETMEM(self, p_woken_by_cancel) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { - THREAD_SETMEM(self, p_woken_by_cancel, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - __pthread_lock(&handle->h_lock, self); - } - /* Get return value */ - if (thread_return != NULL) *thread_return = th->p_retval; - __pthread_unlock(&handle->h_lock); - /* Send notification to thread manager */ - if (__pthread_manager_request >= 0) { - request.req_thread = self; - request.req_kind = REQ_FREE; - request.req_args.free.thread_id = thread_id; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - } - return 0; -} - -int pthread_detach(pthread_t thread_id) -{ - int terminated; - struct pthread_request request; - pthread_handle handle = thread_handle(thread_id); - pthread_descr th; - - __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, thread_id)) { - __pthread_unlock(&handle->h_lock); - return ESRCH; - } - th = handle->h_descr; - /* If already detached, error */ - if (th->p_detached) { - __pthread_unlock(&handle->h_lock); - return EINVAL; - } - /* If already joining, don't do anything. */ - if (th->p_joining != NULL) { - __pthread_unlock(&handle->h_lock); - return 0; - } - /* Mark as detached */ - th->p_detached = 1; - terminated = th->p_terminated; - __pthread_unlock(&handle->h_lock); - /* If already terminated, notify thread manager to reclaim resources */ - if (terminated && __pthread_manager_request >= 0) { - request.req_thread = thread_self(); - request.req_kind = REQ_FREE; - request.req_args.free.thread_id = thread_id; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - } - return 0; -} diff --git a/libpthread/linuxthreads.old/libc_pthread_init.c b/libpthread/linuxthreads.old/libc_pthread_init.c deleted file mode 100644 index dfdcbcccc..000000000 --- a/libpthread/linuxthreads.old/libc_pthread_init.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek <jakub@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, see - <http://www.gnu.org/licenses/>. */ - -#include <locale.h> -#include <string.h> -#include <linuxthreads.old/sysdeps/pthread/pthread-functions.h> - - -int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); - -int * __libc_pthread_init (const struct pthread_functions *functions) -{ -#ifdef SHARED - /* We copy the content of the variable pointed to by the FUNCTIONS - parameter to one in libc.so since this means access to the array - can be done with one memory access instead of two. */ - memcpy (&__libc_pthread_functions, functions, - sizeof (__libc_pthread_functions)); -#endif - -#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_XLOCALE__ - /* Initialize thread-locale current locale to point to the global one. - With __thread support, the variable's initializer takes care of this. */ - uselocale (LC_GLOBAL_LOCALE); -#endif - - return &__libc_multiple_threads; -} diff --git a/libpthread/linuxthreads.old/linuxthreads.texi b/libpthread/linuxthreads.old/linuxthreads.texi deleted file mode 100644 index 795fb7097..000000000 --- a/libpthread/linuxthreads.old/linuxthreads.texi +++ /dev/null @@ -1,1627 +0,0 @@ -@node POSIX Threads -@c @node POSIX Threads, , Top, Top -@chapter POSIX Threads -@c %MENU% The standard threads library - -@c This chapter needs more work bigtime. -zw - -This chapter describes the pthreads (POSIX threads) library. This -library provides support functions for multithreaded programs: thread -primitives, synchronization objects, and so forth. It also implements -POSIX 1003.1b semaphores (not to be confused with System V semaphores). - -The threads operations (@samp{pthread_*}) do not use @var{errno}. -Instead they return an error code directly. The semaphore operations do -use @var{errno}. - -@menu -* Basic Thread Operations:: Creating, terminating, and waiting for threads. -* Thread Attributes:: Tuning thread scheduling. -* Cancellation:: Stopping a thread before it's done. -* Cleanup Handlers:: Deallocating resources when a thread is - canceled. -* Mutexes:: One way to synchronize threads. -* Condition Variables:: Another way. -* POSIX Semaphores:: And a third way. -* Thread-Specific Data:: Variables with different values in - different threads. -* Threads and Signal Handling:: Why you should avoid mixing the two, and - how to do it if you must. -* Threads and Fork:: Interactions between threads and the - @code{fork} function. -* Streams and Fork:: Interactions between stdio streams and - @code{fork}. -* Miscellaneous Thread Functions:: A grab bag of utility routines. -@end menu - -@node Basic Thread Operations -@section Basic Thread Operations - -These functions are the thread equivalents of @code{fork}, @code{exit}, -and @code{wait}. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_create (pthread_t * @var{thread}, pthread_attr_t * @var{attr}, void * (*@var{start_routine})(void *), void * @var{arg}) -@code{pthread_create} creates a new thread of control that executes -concurrently with the calling thread. The new thread calls the -function @var{start_routine}, passing it @var{arg} as first argument. The -new thread terminates either explicitly, by calling @code{pthread_exit}, -or implicitly, by returning from the @var{start_routine} function. The -latter case is equivalent to calling @code{pthread_exit} with the result -returned by @var{start_routine} as exit code. - -The @var{attr} argument specifies thread attributes to be applied to the -new thread. @xref{Thread Attributes}, for details. The @var{attr} -argument can also be @code{NULL}, in which case default attributes are -used: the created thread is joinable (not detached) and has an ordinary -(not realtime) scheduling policy. - -On success, the identifier of the newly created thread is stored in the -location pointed by the @var{thread} argument, and a 0 is returned. On -error, a non-zero error code is returned. - -This function may return the following errors: -@table @code -@item EAGAIN -Not enough system resources to create a process for the new thread, -or more than @code{PTHREAD_THREADS_MAX} threads are already active. -@end table -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun void pthread_exit (void *@var{retval}) -@code{pthread_exit} terminates the execution of the calling thread. All -cleanup handlers (@pxref{Cleanup Handlers}) that have been set for the -calling thread with @code{pthread_cleanup_push} are executed in reverse -order (the most recently pushed handler is executed first). Finalization -functions for thread-specific data are then called for all keys that -have non-@code{NULL} values associated with them in the calling thread -(@pxref{Thread-Specific Data}). Finally, execution of the calling -thread is stopped. - -The @var{retval} argument is the return value of the thread. It can be -retrieved from another thread using @code{pthread_join}. - -The @code{pthread_exit} function never returns. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cancel (pthread_t @var{thread}) - -@code{pthread_cancel} sends a cancellation request to the thread denoted -by the @var{thread} argument. If there is no such thread, -@code{pthread_cancel} fails and returns @code{ESRCH}. Otherwise it -returns 0. @xref{Cancellation}, for details. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return}) -@code{pthread_join} suspends the execution of the calling thread until -the thread identified by @var{th} terminates, either by calling -@code{pthread_exit} or by being canceled. - -If @var{thread_return} is not @code{NULL}, the return value of @var{th} -is stored in the location pointed to by @var{thread_return}. The return -value of @var{th} is either the argument it gave to @code{pthread_exit}, -or @code{PTHREAD_CANCELED} if @var{th} was canceled. - -The joined thread @code{th} must be in the joinable state: it must not -have been detached using @code{pthread_detach} or the -@code{PTHREAD_CREATE_DETACHED} attribute to @code{pthread_create}. - -When a joinable thread terminates, its memory resources (thread -descriptor and stack) are not deallocated until another thread performs -@code{pthread_join} on it. Therefore, @code{pthread_join} must be called -once for each joinable thread created to avoid memory leaks. - -At most one thread can wait for the termination of a given -thread. Calling @code{pthread_join} on a thread @var{th} on which -another thread is already waiting for termination returns an error. - -@code{pthread_join} is a cancellation point. If a thread is canceled -while suspended in @code{pthread_join}, the thread execution resumes -immediately and the cancellation is executed without waiting for the -@var{th} thread to terminate. If cancellation occurs during -@code{pthread_join}, the @var{th} thread remains not joined. - -On success, the return value of @var{th} is stored in the location -pointed to by @var{thread_return}, and 0 is returned. On error, one of -the following values is returned: -@table @code -@item ESRCH -No thread could be found corresponding to that specified by @var{th}. -@item EINVAL -The @var{th} thread has been detached, or another thread is already -waiting on termination of @var{th}. -@item EDEADLK -The @var{th} argument refers to the calling thread. -@end table -@end deftypefun - -@node Thread Attributes -@section Thread Attributes - -@comment pthread.h -@comment POSIX - -Threads have a number of attributes that may be set at creation time. -This is done by filling a thread attribute object @var{attr} of type -@code{pthread_attr_t}, then passing it as second argument to -@code{pthread_create}. Passing @code{NULL} is equivalent to passing a -thread attribute object with all attributes set to their default values. - -Attribute objects are consulted only when creating a new thread. The -same attribute object can be used for creating several threads. -Modifying an attribute object after a call to @code{pthread_create} does -not change the attributes of the thread previously created. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_attr_init (pthread_attr_t *@var{attr}) -@code{pthread_attr_init} initializes the thread attribute object -@var{attr} and fills it with default values for the attributes. (The -default values are listed below for each attribute.) - -Each attribute @var{attrname} (see below for a list of all attributes) -can be individually set using the function -@code{pthread_attr_set@var{attrname}} and retrieved using the function -@code{pthread_attr_get@var{attrname}}. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_attr_destroy (pthread_attr_t *@var{attr}) -@code{pthread_attr_destroy} destroys the attribute object pointed to by -@var{attr} releasing any resources associated with it. @var{attr} is -left in an undefined state, and you must not use it again in a call to -any pthreads function until it has been reinitialized. -@end deftypefun - -@findex pthread_attr_setdetachstate -@findex pthread_attr_setguardsize -@findex pthread_attr_setinheritsched -@findex pthread_attr_setschedparam -@findex pthread_attr_setschedpolicy -@findex pthread_attr_setscope -@findex pthread_attr_setstack -@findex pthread_attr_setstackaddr -@findex pthread_attr_setstacksize -@comment pthread.h -@comment POSIX -@deftypefun int pthread_attr_setattr (pthread_attr_t *@var{obj}, int @var{value}) -Set attribute @var{attr} to @var{value} in the attribute object pointed -to by @var{obj}. See below for a list of possible attributes and the -values they can take. - -On success, these functions return 0. If @var{value} is not meaningful -for the @var{attr} being modified, they will return the error code -@code{EINVAL}. Some of the functions have other failure modes; see -below. -@end deftypefun - -@findex pthread_attr_getdetachstate -@findex pthread_attr_getguardsize -@findex pthread_attr_getinheritsched -@findex pthread_attr_getschedparam -@findex pthread_attr_getschedpolicy -@findex pthread_attr_getscope -@findex pthread_attr_getstack -@findex pthread_attr_getstackaddr -@findex pthread_attr_getstacksize -@comment pthread.h -@comment POSIX -@deftypefun int pthread_attr_getattr (const pthread_attr_t *@var{obj}, int *@var{value}) -Store the current setting of @var{attr} in @var{obj} into the variable -pointed to by @var{value}. - -These functions always return 0. -@end deftypefun - -The following thread attributes are supported: -@table @samp -@item detachstate -Choose whether the thread is created in the joinable state (value -@code{PTHREAD_CREATE_JOINABLE}) or in the detached state -(@code{PTHREAD_CREATE_DETACHED}). The default is -@code{PTHREAD_CREATE_JOINABLE}. - -In the joinable state, another thread can synchronize on the thread -termination and recover its termination code using @code{pthread_join}, -but some of the thread resources are kept allocated after the thread -terminates, and reclaimed only when another thread performs -@code{pthread_join} on that thread. - -In the detached state, the thread resources are immediately freed when -it terminates, but @code{pthread_join} cannot be used to synchronize on -the thread termination. - -A thread created in the joinable state can later be put in the detached -thread using @code{pthread_detach}. - -@item schedpolicy -Select the scheduling policy for the thread: one of @code{SCHED_OTHER} -(regular, non-realtime scheduling), @code{SCHED_RR} (realtime, -round-robin) or @code{SCHED_FIFO} (realtime, first-in first-out). -The default is @code{SCHED_OTHER}. -@c Not doc'd in our manual: FIXME. -@c See @code{sched_setpolicy} for more information on scheduling policies. - -The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO} -are available only to processes with superuser privileges. -@code{pthread_attr_setschedparam} will fail and return @code{ENOTSUP} if -you try to set a realtime policy when you are unprivileged. - -The scheduling policy of a thread can be changed after creation with -@code{pthread_setschedparam}. - -@item schedparam -Change the scheduling parameter (the scheduling priority) -for the thread. The default is 0. - -This attribute is not significant if the scheduling policy is -@code{SCHED_OTHER}; it only matters for the realtime policies -@code{SCHED_RR} and @code{SCHED_FIFO}. - -The scheduling priority of a thread can be changed after creation with -@code{pthread_setschedparam}. - -@item inheritsched -Choose whether the scheduling policy and scheduling parameter for the -newly created thread are determined by the values of the -@var{schedpolicy} and @var{schedparam} attributes (value -@code{PTHREAD_EXPLICIT_SCHED}) or are inherited from the parent thread -(value @code{PTHREAD_INHERIT_SCHED}). The default is -@code{PTHREAD_EXPLICIT_SCHED}. - -@item scope -Choose the scheduling contention scope for the created thread. The -default is @code{PTHREAD_SCOPE_SYSTEM}, meaning that the threads contend -for CPU time with all processes running on the machine. In particular, -thread priorities are interpreted relative to the priorities of all -other processes on the machine. The other possibility, -@code{PTHREAD_SCOPE_PROCESS}, means that scheduling contention occurs -only between the threads of the running process: thread priorities are -interpreted relative to the priorities of the other threads of the -process, regardless of the priorities of other processes. - -@code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads. If you -try to set the scope to this value, @code{pthread_attr_setscope} will -fail and return @code{ENOTSUP}. - -@item stackaddr -Provide an address for an application managed stack. The size of the -stack must be at least @code{PTHREAD_STACK_MIN}. - -@item stacksize -Change the size of the stack created for the thread. The value defines -the minimum stack size, in bytes. - -If the value exceeds the system's maximum stack size, or is smaller -than @code{PTHREAD_STACK_MIN}, @code{pthread_attr_setstacksize} will -fail and return @code{EINVAL}. - -@item stack -Provide both the address and size of an application managed stack to -use for the new thread. The base of the memory area is @var{stackaddr} -with the size of the memory area, @var{stacksize}, measured in bytes. - -If the value of @var{stacksize} is less than @code{PTHREAD_STACK_MIN}, -or greater than the system's maximum stack size, or if the value of -@var{stackaddr} lacks the proper alignment, @code{pthread_attr_setstack} -will fail and return @code{EINVAL}. - -@item guardsize -Change the minimum size in bytes of the guard area for the thread's -stack. The default size is a single page. If this value is set, it -will be rounded up to the nearest page size. If the value is set to 0, -a guard area will not be created for this thread. The space allocated -for the guard area is used to catch stack overflow. Therefore, when -allocating large structures on the stack, a larger guard area may be -required to catch a stack overflow. - -If the caller is managing their own stacks (if the @code{stackaddr} -attribute has been set), then the @code{guardsize} attribute is ignored. - -If the value exceeds the @code{stacksize}, @code{pthread_atrr_setguardsize} -will fail and return @code{EINVAL}. -@end table - -@node Cancellation -@section Cancellation - -Cancellation is the mechanism by which a thread can terminate the -execution of another thread. More precisely, a thread can send a -cancellation request to another thread. Depending on its settings, the -target thread can then either ignore the request, honor it immediately, -or defer it till it reaches a cancellation point. When threads are -first created by @code{pthread_create}, they always defer cancellation -requests. - -When a thread eventually honors a cancellation request, it behaves as if -@code{pthread_exit(PTHREAD_CANCELED)} was called. All cleanup handlers -are executed in reverse order, finalization functions for -thread-specific data are called, and finally the thread stops executing. -If the canceled thread was joinable, the return value -@code{PTHREAD_CANCELED} is provided to whichever thread calls -@var{pthread_join} on it. See @code{pthread_exit} for more information. - -Cancellation points are the points where the thread checks for pending -cancellation requests and performs them. The POSIX threads functions -@code{pthread_join}, @code{pthread_cond_wait}, -@code{pthread_cond_timedwait}, @code{pthread_testcancel}, -@code{sem_wait}, and @code{sigwait} are cancellation points. In -addition, these system calls are cancellation points: - -@multitable @columnfractions .33 .33 .33 -@item @t{accept} @tab @t{open} @tab @t{sendmsg} -@item @t{close} @tab @t{pause} @tab @t{sendto} -@item @t{connect} @tab @t{read} @tab @t{system} -@item @t{fcntl} @tab @t{recv} @tab @t{tcdrain} -@item @t{fsync} @tab @t{recvfrom} @tab @t{wait} -@item @t{lseek} @tab @t{recvmsg} @tab @t{waitpid} -@item @t{msync} @tab @t{send} @tab @t{write} -@item @t{nanosleep} -@end multitable - -@noindent -All library functions that call these functions (such as -@code{printf}) are also cancellation points. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_setcancelstate (int @var{state}, int *@var{oldstate}) -@code{pthread_setcancelstate} changes the cancellation state for the -calling thread -- that is, whether cancellation requests are ignored or -not. The @var{state} argument is the new cancellation state: either -@code{PTHREAD_CANCEL_ENABLE} to enable cancellation, or -@code{PTHREAD_CANCEL_DISABLE} to disable cancellation (cancellation -requests are ignored). - -If @var{oldstate} is not @code{NULL}, the previous cancellation state is -stored in the location pointed to by @var{oldstate}, and can thus be -restored later by another call to @code{pthread_setcancelstate}. - -If the @var{state} argument is not @code{PTHREAD_CANCEL_ENABLE} or -@code{PTHREAD_CANCEL_DISABLE}, @code{pthread_setcancelstate} fails and -returns @code{EINVAL}. Otherwise it returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_setcanceltype (int @var{type}, int *@var{oldtype}) -@code{pthread_setcanceltype} changes the type of responses to -cancellation requests for the calling thread: asynchronous (immediate) -or deferred. The @var{type} argument is the new cancellation type: -either @code{PTHREAD_CANCEL_ASYNCHRONOUS} to cancel the calling thread -as soon as the cancellation request is received, or -@code{PTHREAD_CANCEL_DEFERRED} to keep the cancellation request pending -until the next cancellation point. If @var{oldtype} is not @code{NULL}, -the previous cancellation state is stored in the location pointed to by -@var{oldtype}, and can thus be restored later by another call to -@code{pthread_setcanceltype}. - -If the @var{type} argument is not @code{PTHREAD_CANCEL_DEFERRED} or -@code{PTHREAD_CANCEL_ASYNCHRONOUS}, @code{pthread_setcanceltype} fails -and returns @code{EINVAL}. Otherwise it returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun void pthread_testcancel (@var{void}) -@code{pthread_testcancel} does nothing except testing for pending -cancellation and executing it. Its purpose is to introduce explicit -checks for cancellation in long sequences of code that do not call -cancellation point functions otherwise. -@end deftypefun - -@node Cleanup Handlers -@section Cleanup Handlers - -Cleanup handlers are functions that get called when a thread terminates, -either by calling @code{pthread_exit} or because of -cancellation. Cleanup handlers are installed and removed following a -stack-like discipline. - -The purpose of cleanup handlers is to free the resources that a thread -may hold at the time it terminates. In particular, if a thread exits or -is canceled while it owns a locked mutex, the mutex will remain locked -forever and prevent other threads from executing normally. The best way -to avoid this is, just before locking the mutex, to install a cleanup -handler whose effect is to unlock the mutex. Cleanup handlers can be -used similarly to free blocks allocated with @code{malloc} or close file -descriptors on thread termination. - -Here is how to lock a mutex @var{mut} in such a way that it will be -unlocked if the thread is canceled while @var{mut} is locked: - -@smallexample -pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); -pthread_mutex_lock(&mut); -/* do some work */ -pthread_mutex_unlock(&mut); -pthread_cleanup_pop(0); -@end smallexample - -Equivalently, the last two lines can be replaced by - -@smallexample -pthread_cleanup_pop(1); -@end smallexample - -Notice that the code above is safe only in deferred cancellation mode -(see @code{pthread_setcanceltype}). In asynchronous cancellation mode, a -cancellation can occur between @code{pthread_cleanup_push} and -@code{pthread_mutex_lock}, or between @code{pthread_mutex_unlock} and -@code{pthread_cleanup_pop}, resulting in both cases in the thread trying -to unlock a mutex not locked by the current thread. This is the main -reason why asynchronous cancellation is difficult to use. - -If the code above must also work in asynchronous cancellation mode, -then it must switch to deferred mode for locking and unlocking the -mutex: - -@smallexample -pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); -pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); -pthread_mutex_lock(&mut); -/* do some work */ -pthread_cleanup_pop(1); -pthread_setcanceltype(oldtype, NULL); -@end smallexample - -The code above can be rewritten in a more compact and efficient way, -using the non-portable functions @code{pthread_cleanup_push_defer_np} -and @code{pthread_cleanup_pop_restore_np}: - -@smallexample -pthread_cleanup_push_defer_np(pthread_mutex_unlock, (void *) &mut); -pthread_mutex_lock(&mut); -/* do some work */ -pthread_cleanup_pop_restore_np(1); -@end smallexample - -@comment pthread.h -@comment POSIX -@deftypefun void pthread_cleanup_push (void (*@var{routine}) (void *), void *@var{arg}) - -@code{pthread_cleanup_push} installs the @var{routine} function with -argument @var{arg} as a cleanup handler. From this point on to the -matching @code{pthread_cleanup_pop}, the function @var{routine} will be -called with arguments @var{arg} when the thread terminates, either -through @code{pthread_exit} or by cancellation. If several cleanup -handlers are active at that point, they are called in LIFO order: the -most recently installed handler is called first. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun void pthread_cleanup_pop (int @var{execute}) -@code{pthread_cleanup_pop} removes the most recently installed cleanup -handler. If the @var{execute} argument is not 0, it also executes the -handler, by calling the @var{routine} function with arguments -@var{arg}. If the @var{execute} argument is 0, the handler is only -removed but not executed. -@end deftypefun - -Matching pairs of @code{pthread_cleanup_push} and -@code{pthread_cleanup_pop} must occur in the same function, at the same -level of block nesting. Actually, @code{pthread_cleanup_push} and -@code{pthread_cleanup_pop} are macros, and the expansion of -@code{pthread_cleanup_push} introduces an open brace @code{@{} with the -matching closing brace @code{@}} being introduced by the expansion of the -matching @code{pthread_cleanup_pop}. - -@comment pthread.h -@comment GNU -@deftypefun void pthread_cleanup_push_defer_np (void (*@var{routine}) (void *), void *@var{arg}) -@code{pthread_cleanup_push_defer_np} is a non-portable extension that -combines @code{pthread_cleanup_push} and @code{pthread_setcanceltype}. -It pushes a cleanup handler just as @code{pthread_cleanup_push} does, -but also saves the current cancellation type and sets it to deferred -cancellation. This ensures that the cleanup mechanism is effective even -if the thread was initially in asynchronous cancellation mode. -@end deftypefun - -@comment pthread.h -@comment GNU -@deftypefun void pthread_cleanup_pop_restore_np (int @var{execute}) -@code{pthread_cleanup_pop_restore_np} pops a cleanup handler introduced -by @code{pthread_cleanup_push_defer_np}, and restores the cancellation -type to its value at the time @code{pthread_cleanup_push_defer_np} was -called. -@end deftypefun - -@code{pthread_cleanup_push_defer_np} and -@code{pthread_cleanup_pop_restore_np} must occur in matching pairs, at -the same level of block nesting. - -The sequence - -@smallexample -pthread_cleanup_push_defer_np(routine, arg); -... -pthread_cleanup_pop_restore_np(execute); -@end smallexample - -@noindent -is functionally equivalent to (but more compact and efficient than) - -@smallexample -@{ - int oldtype; - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); - pthread_cleanup_push(routine, arg); - ... - pthread_cleanup_pop(execute); - pthread_setcanceltype(oldtype, NULL); -@} -@end smallexample - - -@node Mutexes -@section Mutexes - -A mutex is a MUTual EXclusion device, and is useful for protecting -shared data structures from concurrent modifications, and implementing -critical sections and monitors. - -A mutex has two possible states: unlocked (not owned by any thread), -and locked (owned by one thread). A mutex can never be owned by two -different threads simultaneously. A thread attempting to lock a mutex -that is already locked by another thread is suspended until the owning -thread unlocks the mutex first. - -None of the mutex functions is a cancellation point, not even -@code{pthread_mutex_lock}, in spite of the fact that it can suspend a -thread for arbitrary durations. This way, the status of mutexes at -cancellation points is predictable, allowing cancellation handlers to -unlock precisely those mutexes that need to be unlocked before the -thread stops executing. Consequently, threads using deferred -cancellation should never hold a mutex for extended periods of time. - -It is not safe to call mutex functions from a signal handler. In -particular, calling @code{pthread_mutex_lock} or -@code{pthread_mutex_unlock} from a signal handler may deadlock the -calling thread. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutex_init (pthread_mutex_t *@var{mutex}, const pthread_mutexattr_t *@var{mutexattr}) - -@code{pthread_mutex_init} initializes the mutex object pointed to by -@var{mutex} according to the mutex attributes specified in @var{mutexattr}. -If @var{mutexattr} is @code{NULL}, default attributes are used instead. - -The LinuxThreads implementation supports only one mutex attribute, -the @var{mutex type}, which is either ``fast'', ``recursive'', or -``error checking''. The type of a mutex determines whether -it can be locked again by a thread that already owns it. -The default type is ``fast''. - -Variables of type @code{pthread_mutex_t} can also be initialized -statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for -timed mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for -recursive mutexes), @code{PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP} -(for fast mutexes(, and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP} -(for error checking mutexes). - -@code{pthread_mutex_init} always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutex_lock (pthread_mutex_t *mutex)) -@code{pthread_mutex_lock} locks the given mutex. If the mutex is -currently unlocked, it becomes locked and owned by the calling thread, -and @code{pthread_mutex_lock} returns immediately. If the mutex is -already locked by another thread, @code{pthread_mutex_lock} suspends the -calling thread until the mutex is unlocked. - -If the mutex is already locked by the calling thread, the behavior of -@code{pthread_mutex_lock} depends on the type of the mutex. If the mutex -is of the ``fast'' type, the calling thread is suspended. It will -remain suspended forever, because no other thread can unlock the mutex. -If the mutex is of the ``error checking'' type, @code{pthread_mutex_lock} -returns immediately with the error code @code{EDEADLK}. If the mutex is -of the ``recursive'' type, @code{pthread_mutex_lock} succeeds and -returns immediately, recording the number of times the calling thread -has locked the mutex. An equal number of @code{pthread_mutex_unlock} -operations must be performed before the mutex returns to the unlocked -state. -@c This doesn't discuss PTHREAD_MUTEX_TIMED_NP mutex attributes. FIXME -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutex_trylock (pthread_mutex_t *@var{mutex}) -@code{pthread_mutex_trylock} behaves identically to -@code{pthread_mutex_lock}, except that it does not block the calling -thread if the mutex is already locked by another thread (or by the -calling thread in the case of a ``fast'' mutex). Instead, -@code{pthread_mutex_trylock} returns immediately with the error code -@code{EBUSY}. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutex_timedlock (pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime}) -The @code{pthread_mutex_timedlock} is similar to the -@code{pthread_mutex_lock} function but instead of blocking for in -indefinite time if the mutex is locked by another thread, it returns -when the time specified in @var{abstime} is reached. - -This function can only be used on standard (``timed'') and ``error -checking'' mutexes. It behaves just like @code{pthread_mutex_lock} for -all other types. - -If the mutex is successfully locked, the function returns zero. If the -time specified in @var{abstime} is reached without the mutex being locked, -@code{ETIMEDOUT} is returned. - -This function was introduced in the POSIX.1d revision of the POSIX standard. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex}) -@code{pthread_mutex_unlock} unlocks the given mutex. The mutex is -assumed to be locked and owned by the calling thread on entrance to -@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' type, -@code{pthread_mutex_unlock} always returns it to the unlocked state. If -it is of the ``recursive'' type, it decrements the locking count of the -mutex (number of @code{pthread_mutex_lock} operations performed on it by -the calling thread), and only when this count reaches zero is the mutex -actually unlocked. - -On ``error checking'' mutexes, @code{pthread_mutex_unlock} actually -checks at run-time that the mutex is locked on entrance, and that it was -locked by the same thread that is now calling -@code{pthread_mutex_unlock}. If these conditions are not met, -@code{pthread_mutex_unlock} returns @code{EPERM}, and the mutex remains -unchanged. ``Fast'' and ``recursive'' mutexes perform no such checks, -thus allowing a locked mutex to be unlocked by a thread other than its -owner. This is non-portable behavior and must not be relied upon. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutex_destroy (pthread_mutex_t *@var{mutex}) -@code{pthread_mutex_destroy} destroys a mutex object, freeing the -resources it might hold. The mutex must be unlocked on entrance. In the -LinuxThreads implementation, no resources are associated with mutex -objects, thus @code{pthread_mutex_destroy} actually does nothing except -checking that the mutex is unlocked. - -If the mutex is locked by some thread, @code{pthread_mutex_destroy} -returns @code{EBUSY}. Otherwise it returns 0. -@end deftypefun - -If any of the above functions (except @code{pthread_mutex_init}) -is applied to an uninitialized mutex, they will simply return -@code{EINVAL} and do nothing. - -A shared global variable @var{x} can be protected by a mutex as follows: - -@smallexample -int x; -pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; -@end smallexample - -All accesses and modifications to @var{x} should be bracketed by calls to -@code{pthread_mutex_lock} and @code{pthread_mutex_unlock} as follows: - -@smallexample -pthread_mutex_lock(&mut); -/* operate on x */ -pthread_mutex_unlock(&mut); -@end smallexample - -Mutex attributes can be specified at mutex creation time, by passing a -mutex attribute object as second argument to @code{pthread_mutex_init}. -Passing @code{NULL} is equivalent to passing a mutex attribute object -with all attributes set to their default values. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutexattr_init (pthread_mutexattr_t *@var{attr}) -@code{pthread_mutexattr_init} initializes the mutex attribute object -@var{attr} and fills it with default values for the attributes. - -This function always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutexattr_destroy (pthread_mutexattr_t *@var{attr}) -@code{pthread_mutexattr_destroy} destroys a mutex attribute object, -which must not be reused until it is -reinitialized. @code{pthread_mutexattr_destroy} does nothing in the -LinuxThreads implementation. - -This function always returns 0. -@end deftypefun - -LinuxThreads supports only one mutex attribute: the mutex type, which is -either @code{PTHREAD_MUTEX_ADAPTIVE_NP} for ``fast'' mutexes, -@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes, -@code{PTHREAD_MUTEX_TIMED_NP} for ``timed'' mutexes, or -@code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes. As -the @code{NP} suffix indicates, this is a non-portable extension to the -POSIX standard and should not be employed in portable programs. - -The mutex type determines what happens if a thread attempts to lock a -mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of -the ``fast'' type, @code{pthread_mutex_lock} simply suspends the calling -thread forever. If the mutex is of the ``error checking'' type, -@code{pthread_mutex_lock} returns immediately with the error code -@code{EDEADLK}. If the mutex is of the ``recursive'' type, the call to -@code{pthread_mutex_lock} returns immediately with a success return -code. The number of times the thread owning the mutex has locked it is -recorded in the mutex. The owning thread must call -@code{pthread_mutex_unlock} the same number of times before the mutex -returns to the unlocked state. - -The default mutex type is ``timed'', that is, @code{PTHREAD_MUTEX_TIMED_NP}. -@c This doesn't describe how a ``timed'' mutex behaves. FIXME - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutexattr_settype (pthread_mutexattr_t *@var{attr}, int @var{type}) -@code{pthread_mutexattr_settype} sets the mutex type attribute in -@var{attr} to the value specified by @var{type}. - -If @var{type} is not @code{PTHREAD_MUTEX_ADAPTIVE_NP}, -@code{PTHREAD_MUTEX_RECURSIVE_NP}, @code{PTHREAD_MUTEX_TIMED_NP}, or -@code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return -@code{EINVAL} and leave @var{attr} unchanged. - -The standard Unix98 identifiers @code{PTHREAD_MUTEX_DEFAULT}, -@code{PTHREAD_MUTEX_NORMAL}, @code{PTHREAD_MUTEX_RECURSIVE}, -and @code{PTHREAD_MUTEX_ERRORCHECK} are also permitted. - -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_mutexattr_gettype (const pthread_mutexattr_t *@var{attr}, int *@var{type}) -@code{pthread_mutexattr_gettype} retrieves the current value of the -mutex type attribute in @var{attr} and stores it in the location pointed -to by @var{type}. - -This function always returns 0. -@end deftypefun - -@node Condition Variables -@section Condition Variables - -A condition (short for ``condition variable'') is a synchronization -device that allows threads to suspend execution until some predicate on -shared data is satisfied. The basic operations on conditions are: signal -the condition (when the predicate becomes true), and wait for the -condition, suspending the thread execution until another thread signals -the condition. - -A condition variable must always be associated with a mutex, to avoid -the race condition where a thread prepares to wait on a condition -variable and another thread signals the condition just before the first -thread actually waits on it. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cond_init (pthread_cond_t *@var{cond}, pthread_condattr_t *cond_@var{attr}) - -@code{pthread_cond_init} initializes the condition variable @var{cond}, -using the condition attributes specified in @var{cond_attr}, or default -attributes if @var{cond_attr} is @code{NULL}. The LinuxThreads -implementation supports no attributes for conditions, hence the -@var{cond_attr} parameter is actually ignored. - -Variables of type @code{pthread_cond_t} can also be initialized -statically, using the constant @code{PTHREAD_COND_INITIALIZER}. - -This function always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cond_signal (pthread_cond_t *@var{cond}) -@code{pthread_cond_signal} restarts one of the threads that are waiting -on the condition variable @var{cond}. If no threads are waiting on -@var{cond}, nothing happens. If several threads are waiting on -@var{cond}, exactly one is restarted, but it is not specified which. - -This function always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cond_broadcast (pthread_cond_t *@var{cond}) -@code{pthread_cond_broadcast} restarts all the threads that are waiting -on the condition variable @var{cond}. Nothing happens if no threads are -waiting on @var{cond}. - -This function always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cond_wait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}) -@code{pthread_cond_wait} atomically unlocks the @var{mutex} (as per -@code{pthread_unlock_mutex}) and waits for the condition variable -@var{cond} to be signaled. The thread execution is suspended and does -not consume any CPU time until the condition variable is signaled. The -@var{mutex} must be locked by the calling thread on entrance to -@code{pthread_cond_wait}. Before returning to the calling thread, -@code{pthread_cond_wait} re-acquires @var{mutex} (as per -@code{pthread_lock_mutex}). - -Unlocking the mutex and suspending on the condition variable is done -atomically. Thus, if all threads always acquire the mutex before -signaling the condition, this guarantees that the condition cannot be -signaled (and thus ignored) between the time a thread locks the mutex -and the time it waits on the condition variable. - -This function always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cond_timedwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime}) -@code{pthread_cond_timedwait} atomically unlocks @var{mutex} and waits -on @var{cond}, as @code{pthread_cond_wait} does, but it also bounds the -duration of the wait. If @var{cond} has not been signaled before time -@var{abstime}, the mutex @var{mutex} is re-acquired and -@code{pthread_cond_timedwait} returns the error code @code{ETIMEDOUT}. -The wait can also be interrupted by a signal; in that case -@code{pthread_cond_timedwait} returns @code{EINTR}. - -The @var{abstime} parameter specifies an absolute time, with the same -origin as @code{time} and @code{gettimeofday}: an @var{abstime} of 0 -corresponds to 00:00:00 GMT, January 1, 1970. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_cond_destroy (pthread_cond_t *@var{cond}) -@code{pthread_cond_destroy} destroys the condition variable @var{cond}, -freeing the resources it might hold. If any threads are waiting on the -condition variable, @code{pthread_cond_destroy} leaves @var{cond} -untouched and returns @code{EBUSY}. Otherwise it returns 0, and -@var{cond} must not be used again until it is reinitialized. - -In the LinuxThreads implementation, no resources are associated with -condition variables, so @code{pthread_cond_destroy} actually does -nothing. -@end deftypefun - -@code{pthread_cond_wait} and @code{pthread_cond_timedwait} are -cancellation points. If a thread is canceled while suspended in one of -these functions, the thread immediately resumes execution, relocks the -mutex specified by @var{mutex}, and finally executes the cancellation. -Consequently, cleanup handlers are assured that @var{mutex} is locked -when they are called. - -It is not safe to call the condition variable functions from a signal -handler. In particular, calling @code{pthread_cond_signal} or -@code{pthread_cond_broadcast} from a signal handler may deadlock the -calling thread. - -Consider two shared variables @var{x} and @var{y}, protected by the -mutex @var{mut}, and a condition variable @var{cond} that is to be -signaled whenever @var{x} becomes greater than @var{y}. - -@smallexample -int x,y; -pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -@end smallexample - -Waiting until @var{x} is greater than @var{y} is performed as follows: - -@smallexample -pthread_mutex_lock(&mut); -while (x <= y) @{ - pthread_cond_wait(&cond, &mut); -@} -/* operate on x and y */ -pthread_mutex_unlock(&mut); -@end smallexample - -Modifications on @var{x} and @var{y} that may cause @var{x} to become greater than -@var{y} should signal the condition if needed: - -@smallexample -pthread_mutex_lock(&mut); -/* modify x and y */ -if (x > y) pthread_cond_broadcast(&cond); -pthread_mutex_unlock(&mut); -@end smallexample - -If it can be proved that at most one waiting thread needs to be waken -up (for instance, if there are only two threads communicating through -@var{x} and @var{y}), @code{pthread_cond_signal} can be used as a slightly more -efficient alternative to @code{pthread_cond_broadcast}. In doubt, use -@code{pthread_cond_broadcast}. - -To wait for @var{x} to becomes greater than @var{y} with a timeout of 5 -seconds, do: - -@smallexample -struct timeval now; -struct timespec timeout; -int retcode; - -pthread_mutex_lock(&mut); -gettimeofday(&now); -timeout.tv_sec = now.tv_sec + 5; -timeout.tv_nsec = now.tv_usec * 1000; -retcode = 0; -while (x <= y && retcode != ETIMEDOUT) @{ - retcode = pthread_cond_timedwait(&cond, &mut, &timeout); -@} -if (retcode == ETIMEDOUT) @{ - /* timeout occurred */ -@} else @{ - /* operate on x and y */ -@} -pthread_mutex_unlock(&mut); -@end smallexample - -Condition attributes can be specified at condition creation time, by -passing a condition attribute object as second argument to -@code{pthread_cond_init}. Passing @code{NULL} is equivalent to passing -a condition attribute object with all attributes set to their default -values. - -The LinuxThreads implementation supports no attributes for -conditions. The functions on condition attributes are included only for -compliance with the POSIX standard. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_condattr_init (pthread_condattr_t *@var{attr}) -@deftypefunx int pthread_condattr_destroy (pthread_condattr_t *@var{attr}) -@code{pthread_condattr_init} initializes the condition attribute object -@var{attr} and fills it with default values for the attributes. -@code{pthread_condattr_destroy} destroys the condition attribute object -@var{attr}. - -Both functions do nothing in the LinuxThreads implementation. - -@code{pthread_condattr_init} and @code{pthread_condattr_destroy} always -return 0. -@end deftypefun - -@node POSIX Semaphores -@section POSIX Semaphores - -@vindex SEM_VALUE_MAX -Semaphores are counters for resources shared between threads. The -basic operations on semaphores are: increment the counter atomically, -and wait until the counter is non-null and decrement it atomically. - -Semaphores have a maximum value past which they cannot be incremented. -The macro @code{SEM_VALUE_MAX} is defined to be this maximum value. In -the GNU C library, @code{SEM_VALUE_MAX} is equal to @code{INT_MAX} -(@pxref{Range of Type}), but it may be much smaller on other systems. - -The pthreads library implements POSIX 1003.1b semaphores. These should -not be confused with System V semaphores (@code{ipc}, @code{semctl} and -@code{semop}). -@c !!! SysV IPC is not doc'd at all in our manual - -All the semaphore functions and macros are defined in @file{semaphore.h}. - -@comment semaphore.h -@comment POSIX -@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value}) -@code{sem_init} initializes the semaphore object pointed to by -@var{sem}. The count associated with the semaphore is set initially to -@var{value}. The @var{pshared} argument indicates whether the semaphore -is local to the current process (@var{pshared} is zero) or is to be -shared between several processes (@var{pshared} is not zero). - -On success @code{sem_init} returns 0. On failure it returns -1 and sets -@var{errno} to one of the following values: - -@table @code -@item EINVAL -@var{value} exceeds the maximal counter value @code{SEM_VALUE_MAX} - -@item ENOSYS -@var{pshared} is not zero. LinuxThreads currently does not support -process-shared semaphores. (This will eventually change.) -@end table -@end deftypefun - -@comment semaphore.h -@comment POSIX -@deftypefun int sem_destroy (sem_t * @var{sem}) -@code{sem_destroy} destroys a semaphore object, freeing the resources it -might hold. If any threads are waiting on the semaphore when -@code{sem_destroy} is called, it fails and sets @var{errno} to -@code{EBUSY}. - -In the LinuxThreads implementation, no resources are associated with -semaphore objects, thus @code{sem_destroy} actually does nothing except -checking that no thread is waiting on the semaphore. This will change -when process-shared semaphores are implemented. -@end deftypefun - -@comment semaphore.h -@comment POSIX -@deftypefun int sem_wait (sem_t * @var{sem}) -@code{sem_wait} suspends the calling thread until the semaphore pointed -to by @var{sem} has non-zero count. It then atomically decreases the -semaphore count. - -@code{sem_wait} is a cancellation point. It always returns 0. -@end deftypefun - -@comment semaphore.h -@comment POSIX -@deftypefun int sem_trywait (sem_t * @var{sem}) -@code{sem_trywait} is a non-blocking variant of @code{sem_wait}. If the -semaphore pointed to by @var{sem} has non-zero count, the count is -atomically decreased and @code{sem_trywait} immediately returns 0. If -the semaphore count is zero, @code{sem_trywait} immediately returns -1 -and sets errno to @code{EAGAIN}. -@end deftypefun - -@comment semaphore.h -@comment POSIX -@deftypefun int sem_post (sem_t * @var{sem}) -@code{sem_post} atomically increases the count of the semaphore pointed to -by @var{sem}. This function never blocks. - -@c !!! This para appears not to agree with the code. -On processors supporting atomic compare-and-swap (Intel 486, Pentium and -later, Alpha, PowerPC, MIPS II, Motorola 68k, Ultrasparc), the -@code{sem_post} function is can safely be called from signal handlers. -This is the only thread synchronization function provided by POSIX -threads that is async-signal safe. On the Intel 386 and earlier Sparc -chips, the current LinuxThreads implementation of @code{sem_post} is not -async-signal safe, because the hardware does not support the required -atomic operations. - -@code{sem_post} always succeeds and returns 0, unless the semaphore -count would exceed @code{SEM_VALUE_MAX} after being incremented. In -that case @code{sem_post} returns -1 and sets @var{errno} to -@code{EINVAL}. The semaphore count is left unchanged. -@end deftypefun - -@comment semaphore.h -@comment POSIX -@deftypefun int sem_getvalue (sem_t * @var{sem}, int * @var{sval}) -@code{sem_getvalue} stores in the location pointed to by @var{sval} the -current count of the semaphore @var{sem}. It always returns 0. -@end deftypefun - -@node Thread-Specific Data -@section Thread-Specific Data - -Programs often need global or static variables that have different -values in different threads. Since threads share one memory space, this -cannot be achieved with regular variables. Thread-specific data is the -POSIX threads answer to this need. - -Each thread possesses a private memory block, the thread-specific data -area, or TSD area for short. This area is indexed by TSD keys. The TSD -area associates values of type @code{void *} to TSD keys. TSD keys are -common to all threads, but the value associated with a given TSD key can -be different in each thread. - -For concreteness, the TSD areas can be viewed as arrays of @code{void *} -pointers, TSD keys as integer indices into these arrays, and the value -of a TSD key as the value of the corresponding array element in the -calling thread. - -When a thread is created, its TSD area initially associates @code{NULL} -with all keys. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_key_create (pthread_key_t *@var{key}, void (*destr_function) (void *)) -@code{pthread_key_create} allocates a new TSD key. The key is stored in -the location pointed to by @var{key}. There is a limit of -@code{PTHREAD_KEYS_MAX} on the number of keys allocated at a given -time. The value initially associated with the returned key is -@code{NULL} in all currently executing threads. - -The @var{destr_function} argument, if not @code{NULL}, specifies a -destructor function associated with the key. When a thread terminates -via @code{pthread_exit} or by cancellation, @var{destr_function} is -called on the value associated with the key in that thread. The -@var{destr_function} is not called if a key is deleted with -@code{pthread_key_delete} or a value is changed with -@code{pthread_setspecific}. The order in which destructor functions are -called at thread termination time is unspecified. - -Before the destructor function is called, the @code{NULL} value is -associated with the key in the current thread. A destructor function -might, however, re-associate non-@code{NULL} values to that key or some -other key. To deal with this, if after all the destructors have been -called for all non-@code{NULL} values, there are still some -non-@code{NULL} values with associated destructors, then the process is -repeated. The LinuxThreads implementation stops the process after -@code{PTHREAD_DESTRUCTOR_ITERATIONS} iterations, even if some -non-@code{NULL} values with associated descriptors remain. Other -implementations may loop indefinitely. - -@code{pthread_key_create} returns 0 unless @code{PTHREAD_KEYS_MAX} keys -have already been allocated, in which case it fails and returns -@code{EAGAIN}. -@end deftypefun - - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_key_delete (pthread_key_t @var{key}) -@code{pthread_key_delete} deallocates a TSD key. It does not check -whether non-@code{NULL} values are associated with that key in the -currently executing threads, nor call the destructor function associated -with the key. - -If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise -it returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_setspecific (pthread_key_t @var{key}, const void *@var{pointer}) -@code{pthread_setspecific} changes the value associated with @var{key} -in the calling thread, storing the given @var{pointer} instead. - -If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise -it returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun {void *} pthread_getspecific (pthread_key_t @var{key}) -@code{pthread_getspecific} returns the value currently associated with -@var{key} in the calling thread. - -If there is no such key @var{key}, it returns @code{NULL}. -@end deftypefun - -The following code fragment allocates a thread-specific array of 100 -characters, with automatic reclaimation at thread exit: - -@smallexample -/* Key for the thread-specific buffer */ -static pthread_key_t buffer_key; - -/* Once-only initialisation of the key */ -static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT; - -/* Allocate the thread-specific buffer */ -void buffer_alloc(void) -@{ - pthread_once(&buffer_key_once, buffer_key_alloc); - pthread_setspecific(buffer_key, malloc(100)); -@} - -/* Return the thread-specific buffer */ -char * get_buffer(void) -@{ - return (char *) pthread_getspecific(buffer_key); -@} - -/* Allocate the key */ -static void buffer_key_alloc() -@{ - pthread_key_create(&buffer_key, buffer_destroy); -@} - -/* Free the thread-specific buffer */ -static void buffer_destroy(void * buf) -@{ - free(buf); -@} -@end smallexample - -@node Threads and Signal Handling -@section Threads and Signal Handling - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_sigmask (int @var{how}, const sigset_t *@var{newmask}, sigset_t *@var{oldmask}) -@code{pthread_sigmask} changes the signal mask for the calling thread as -described by the @var{how} and @var{newmask} arguments. If @var{oldmask} -is not @code{NULL}, the previous signal mask is stored in the location -pointed to by @var{oldmask}. - -The meaning of the @var{how} and @var{newmask} arguments is the same as -for @code{sigprocmask}. If @var{how} is @code{SIG_SETMASK}, the signal -mask is set to @var{newmask}. If @var{how} is @code{SIG_BLOCK}, the -signals specified to @var{newmask} are added to the current signal mask. -If @var{how} is @code{SIG_UNBLOCK}, the signals specified to -@var{newmask} are removed from the current signal mask. - -Recall that signal masks are set on a per-thread basis, but signal -actions and signal handlers, as set with @code{sigaction}, are shared -between all threads. - -The @code{pthread_sigmask} function returns 0 on success, and one of the -following error codes on error: -@table @code -@item EINVAL -@var{how} is not one of @code{SIG_SETMASK}, @code{SIG_BLOCK}, or @code{SIG_UNBLOCK} - -@item EFAULT -@var{newmask} or @var{oldmask} point to invalid addresses -@end table -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_kill (pthread_t @var{thread}, int @var{signo}) -@code{pthread_kill} sends signal number @var{signo} to the thread -@var{thread}. The signal is delivered and handled as described in -@ref{Signal Handling}. - -@code{pthread_kill} returns 0 on success, one of the following error codes -on error: -@table @code -@item EINVAL -@var{signo} is not a valid signal number - -@item ESRCH -The thread @var{thread} does not exist (e.g. it has already terminated) -@end table -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int sigwait (const sigset_t *@var{set}, int *@var{sig}) -@code{sigwait} suspends the calling thread until one of the signals in -@var{set} is delivered to the calling thread. It then stores the number -of the signal received in the location pointed to by @var{sig} and -returns. The signals in @var{set} must be blocked and not ignored on -entrance to @code{sigwait}. If the delivered signal has a signal handler -function attached, that function is @emph{not} called. - -@code{sigwait} is a cancellation point. It always returns 0. -@end deftypefun - -For @code{sigwait} to work reliably, the signals being waited for must be -blocked in all threads, not only in the calling thread, since -otherwise the POSIX semantics for signal delivery do not guarantee -that it's the thread doing the @code{sigwait} that will receive the signal. -The best way to achieve this is block those signals before any threads -are created, and never unblock them in the program other than by -calling @code{sigwait}. - -Signal handling in LinuxThreads departs significantly from the POSIX -standard. According to the standard, ``asynchronous'' (external) signals -are addressed to the whole process (the collection of all threads), -which then delivers them to one particular thread. The thread that -actually receives the signal is any thread that does not currently block -the signal. - -In LinuxThreads, each thread is actually a kernel process with its own -PID, so external signals are always directed to one particular thread. -If, for instance, another thread is blocked in @code{sigwait} on that -signal, it will not be restarted. - -The LinuxThreads implementation of @code{sigwait} installs dummy signal -handlers for the signals in @var{set} for the duration of the -wait. Since signal handlers are shared between all threads, other -threads must not attach their own signal handlers to these signals, or -alternatively they should all block these signals (which is recommended -anyway). - -@node Threads and Fork -@section Threads and Fork - -It's not intuitively obvious what should happen when a multi-threaded POSIX -process calls @code{fork}. Not only are the semantics tricky, but you may -need to write code that does the right thing at fork time even if that code -doesn't use the @code{fork} function. Moreover, you need to be aware of -interaction between @code{fork} and some library features like -@code{pthread_once} and stdio streams. - -When @code{fork} is called by one of the threads of a process, it creates a new -process which is copy of the calling process. Effectively, in addition to -copying certain system objects, the function takes a snapshot of the memory -areas of the parent process, and creates identical areas in the child. -To make matters more complicated, with threads it's possible for two or more -threads to concurrently call fork to create two or more child processes. - -The child process has a copy of the address space of the parent, but it does -not inherit any of its threads. Execution of the child process is carried out -by a new thread which returns from @code{fork} function with a return value of -zero; it is the only thread in the child process. Because threads are not -inherited across fork, issues arise. At the time of the call to @code{fork}, -threads in the parent process other than the one calling @code{fork} may have -been executing critical regions of code. As a result, the child process may -get a copy of objects that are not in a well-defined state. This potential -problem affects all components of the program. - -Any program component which will continue being used in a child process must -correctly handle its state during @code{fork}. For this purpose, the POSIX -interface provides the special function @code{pthread_atfork} for installing -pointers to handler functions which are called from within @code{fork}. - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void)) - -@code{pthread_atfork} registers handler functions to be called just -before and just after a new process is created with @code{fork}. The -@var{prepare} handler will be called from the parent process, just -before the new process is created. The @var{parent} handler will be -called from the parent process, just before @code{fork} returns. The -@var{child} handler will be called from the child process, just before -@code{fork} returns. - -@code{pthread_atfork} returns 0 on success and a non-zero error code on -error. - -One or more of the three handlers @var{prepare}, @var{parent} and -@var{child} can be given as @code{NULL}, meaning that no handler needs -to be called at the corresponding point. - -@code{pthread_atfork} can be called several times to install several -sets of handlers. At @code{fork} time, the @var{prepare} handlers are -called in LIFO order (last added with @code{pthread_atfork}, first -called before @code{fork}), while the @var{parent} and @var{child} -handlers are called in FIFO order (first added, first called). - -If there is insufficient memory available to register the handlers, -@code{pthread_atfork} fails and returns @code{ENOMEM}. Otherwise it -returns 0. - -The functions @code{fork} and @code{pthread_atfork} must not be regarded as -reentrant from the context of the handlers. That is to say, if a -@code{pthread_atfork} handler invoked from within @code{fork} calls -@code{pthread_atfork} or @code{fork}, the behavior is undefined. - -Registering a triplet of handlers is an atomic operation with respect to fork. -If new handlers are registered at about the same time as a fork occurs, either -all three handlers will be called, or none of them will be called. - -The handlers are inherited by the child process, and there is no -way to remove them, short of using @code{exec} to load a new -pocess image. - -@end deftypefun - -To understand the purpose of @code{pthread_atfork}, recall that -@code{fork} duplicates the whole memory space, including mutexes in -their current locking state, but only the calling thread: other threads -are not running in the child process. The mutexes are not usable after -the @code{fork} and must be initialized with @code{pthread_mutex_init} -in the child process. This is a limitation of the current -implementation and might or might not be present in future versions. - -To avoid this, install handlers with @code{pthread_atfork} as follows: have the -@var{prepare} handler lock the mutexes (in locking order), and the -@var{parent} handler unlock the mutexes. The @var{child} handler should reset -the mutexes using @code{pthread_mutex_init}, as well as any other -synchronization objects such as condition variables. - -Locking the global mutexes before the fork ensures that all other threads are -locked out of the critical regions of code protected by those mutexes. Thus -when @code{fork} takes a snapshot of the parent's address space, that snapshot -will copy valid, stable data. Resetting the synchronization objects in the -child process will ensure they are properly cleansed of any artifacts from the -threading subsystem of the parent process. For example, a mutex may inherit -a wait queue of threads waiting for the lock; this wait queue makes no sense -in the child process. Initializing the mutex takes care of this. - -@node Streams and Fork -@section Streams and Fork - -The GNU standard I/O library has an internal mutex which guards the internal -linked list of all standard C FILE objects. This mutex is properly taken care -of during @code{fork} so that the child receives an intact copy of the list. -This allows the @code{fopen} function, and related stream-creating functions, -to work correctly in the child process, since these functions need to insert -into the list. - -However, the individual stream locks are not completely taken care of. Thus -unless the multithreaded application takes special precautions in its use of -@code{fork}, the child process might not be able to safely use the streams that -it inherited from the parent. In general, for any given open stream in the -parent that is to be used by the child process, the application must ensure -that that stream is not in use by another thread when @code{fork} is called. -Otherwise an inconsistent copy of the stream object be produced. An easy way to -ensure this is to use @code{flockfile} to lock the stream prior to calling -@code{fork} and then unlock it with @code{funlockfile} inside the parent -process, provided that the parent's threads properly honor these locks. -Nothing special needs to be done in the child process, since the library -internally resets all stream locks. - -Note that the stream locks are not shared between the parent and child. -For example, even if you ensure that, say, the stream @code{stdout} is properly -treated and can be safely used in the child, the stream locks do not provide -an exclusion mechanism between the parent and child. If both processes write -to @code{stdout}, strangely interleaved output may result regardless of -the explicit use of @code{flockfile} or implicit locks. - -Also note that these provisions are a GNU extension; other systems might not -provide any way for streams to be used in the child of a multithreaded process. -POSIX requires that such a child process confines itself to calling only -asynchronous safe functions, which excludes much of the library, including -standard I/O. - -@node Miscellaneous Thread Functions -@section Miscellaneous Thread Functions - -@comment pthread.h -@comment POSIX -@deftypefun {pthread_t} pthread_self (@var{void}) -@code{pthread_self} returns the thread identifier for the calling thread. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2) -@code{pthread_equal} determines if two thread identifiers refer to the same -thread. - -A non-zero value is returned if @var{thread1} and @var{thread2} refer to -the same thread. Otherwise, 0 is returned. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_detach (pthread_t @var{th}) -@code{pthread_detach} puts the thread @var{th} in the detached -state. This guarantees that the memory resources consumed by @var{th} -will be freed immediately when @var{th} terminates. However, this -prevents other threads from synchronizing on the termination of @var{th} -using @code{pthread_join}. - -A thread can be created initially in the detached state, using the -@code{detachstate} attribute to @code{pthread_create}. In contrast, -@code{pthread_detach} applies to threads created in the joinable state, -and which need to be put in the detached state later. - -After @code{pthread_detach} completes, subsequent attempts to perform -@code{pthread_join} on @var{th} will fail. If another thread is already -joining the thread @var{th} at the time @code{pthread_detach} is called, -@code{pthread_detach} does nothing and leaves @var{th} in the joinable -state. - -On success, 0 is returned. On error, one of the following codes is -returned: -@table @code -@item ESRCH -No thread could be found corresponding to that specified by @var{th} -@item EINVAL -The thread @var{th} is already in the detached state -@end table -@end deftypefun - -@comment pthread.h -@comment GNU -@deftypefun void pthread_kill_other_threads_np (@var{void}) -@code{pthread_kill_other_threads_np} is a non-portable LinuxThreads extension. -It causes all threads in the program to terminate immediately, except -the calling thread which proceeds normally. It is intended to be -called just before a thread calls one of the @code{exec} functions, -e.g. @code{execve}. - -Termination of the other threads is not performed through -@code{pthread_cancel} and completely bypasses the cancellation -mechanism. Hence, the current settings for cancellation state and -cancellation type are ignored, and the cleanup handlers are not -executed in the terminated threads. - -According to POSIX 1003.1c, a successful @code{exec*} in one of the -threads should automatically terminate all other threads in the program. -This behavior is not yet implemented in LinuxThreads. Calling -@code{pthread_kill_other_threads_np} before @code{exec*} achieves much -of the same behavior, except that if @code{exec*} ultimately fails, then -all other threads are already killed. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_once (pthread_once_t *once_@var{control}, void (*@var{init_routine}) (void)) - -The purpose of @code{pthread_once} is to ensure that a piece of -initialization code is executed at most once. The @var{once_control} -argument points to a static or extern variable statically initialized -to @code{PTHREAD_ONCE_INIT}. - -The first time @code{pthread_once} is called with a given -@var{once_control} argument, it calls @var{init_routine} with no -argument and changes the value of the @var{once_control} variable to -record that initialization has been performed. Subsequent calls to -@code{pthread_once} with the same @code{once_control} argument do -nothing. - -If a thread is cancelled while executing @var{init_routine} -the state of the @var{once_control} variable is reset so that -a future call to @code{pthread_once} will call the routine again. - -If the process forks while one or more threads are executing -@code{pthread_once} initialization routines, the states of their respective -@var{once_control} variables will appear to be reset in the child process so -that if the child calls @code{pthread_once}, the routines will be executed. - -@code{pthread_once} always returns 0. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_setschedparam (pthread_t target_@var{thread}, int @var{policy}, const struct sched_param *@var{param}) - -@code{pthread_setschedparam} sets the scheduling parameters for the -thread @var{target_thread} as indicated by @var{policy} and -@var{param}. @var{policy} can be either @code{SCHED_OTHER} (regular, -non-realtime scheduling), @code{SCHED_RR} (realtime, round-robin) or -@code{SCHED_FIFO} (realtime, first-in first-out). @var{param} specifies -the scheduling priority for the two realtime policies. See -@code{sched_setpolicy} for more information on scheduling policies. - -The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO} -are available only to processes with superuser privileges. - -On success, @code{pthread_setschedparam} returns 0. On error it returns -one of the following codes: -@table @code -@item EINVAL -@var{policy} is not one of @code{SCHED_OTHER}, @code{SCHED_RR}, -@code{SCHED_FIFO}, or the priority value specified by @var{param} is not -valid for the specified policy - -@item EPERM -Realtime scheduling was requested but the calling process does not have -sufficient privileges. - -@item ESRCH -The @var{target_thread} is invalid or has already terminated - -@item EFAULT -@var{param} points outside the process memory space -@end table -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_getschedparam (pthread_t target_@var{thread}, int *@var{policy}, struct sched_param *@var{param}) - -@code{pthread_getschedparam} retrieves the scheduling policy and -scheduling parameters for the thread @var{target_thread} and stores them -in the locations pointed to by @var{policy} and @var{param}, -respectively. - -@code{pthread_getschedparam} returns 0 on success, or one of the -following error codes on failure: -@table @code -@item ESRCH -The @var{target_thread} is invalid or has already terminated. - -@item EFAULT -@var{policy} or @var{param} point outside the process memory space. - -@end table -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_setconcurrency (int @var{level}) -@code{pthread_setconcurrency} is unused in LinuxThreads due to the lack -of a mapping of user threads to kernel threads. It exists for source -compatibility. It does store the value @var{level} so that it can be -returned by a subsequent call to @code{pthread_getconcurrency}. It takes -no other action however. -@end deftypefun - -@comment pthread.h -@comment POSIX -@deftypefun int pthread_getconcurrency () -@code{pthread_getconcurrency} is unused in LinuxThreads due to the lack -of a mapping of user threads to kernel threads. It exists for source -compatibility. However, it will return the value that was set by the -last call to @code{pthread_setconcurrency}. -@end deftypefun diff --git a/libpthread/linuxthreads.old/locale.c b/libpthread/linuxthreads.old/locale.c deleted file mode 100644 index 12497182d..000000000 --- a/libpthread/linuxthreads.old/locale.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2003 Manuel Novoa III - * - * This 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. - * - * This 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 this library; if not, see - * <http://www.gnu.org/licenses/>. - */ - -#include <features.h> -#include "pthread.h" -#include "internals.h" -#include <locale.h> -#include <assert.h> -#include <stdlib.h> - -extern struct _pthread_descr_struct __pthread_initial_thread; - -__locale_t __curlocale(void) -{ - pthread_descr self = thread_self(); - -#ifdef NDEBUG - return THREAD_GETMEM (self, locale); -#else - { - __locale_t r = THREAD_GETMEM (self, locale); - - assert(r); - - return r; - } -#endif -} - -__locale_t __curlocale_set(__locale_t newloc) -{ - __locale_t oldloc; - pthread_descr self = thread_self(); - - oldloc = THREAD_GETMEM (self, locale); - - assert(newloc != LC_GLOBAL_LOCALE); - assert(oldloc); - - THREAD_SETMEM (self, locale, newloc); - - return oldloc; -} diff --git a/libpthread/linuxthreads.old/lockfile.c b/libpthread/linuxthreads.old/lockfile.c deleted file mode 100644 index de834c476..000000000 --- a/libpthread/linuxthreads.old/lockfile.c +++ /dev/null @@ -1,42 +0,0 @@ -/* lockfile - Handle locking and unlocking of stream. - Copyright (C) 1996, 1998, 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 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <stdio.h> -#include <pthread.h> - -extern __typeof(pthread_mutexattr_init) __pthread_mutexattr_init attribute_hidden; -extern __typeof(pthread_mutexattr_settype) __pthread_mutexattr_settype attribute_hidden; -extern __typeof(pthread_mutexattr_destroy) __pthread_mutexattr_destroy attribute_hidden; - -/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both - * libc and libpthread. In uClibc, they are now in libc only. */ - -void __fresetlockfiles (void); -void __fresetlockfiles (void) -{ - FILE *fp; - pthread_mutexattr_t attr; - - __pthread_mutexattr_init(&attr); - __pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); - - for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) - __pthread_mutex_init(&fp->__lock, &attr); - - __pthread_mutexattr_destroy(&attr); -} diff --git a/libpthread/linuxthreads.old/manager.c b/libpthread/linuxthreads.old/manager.c deleted file mode 100644 index e4022f8ea..000000000 --- a/libpthread/linuxthreads.old/manager.c +++ /dev/null @@ -1,933 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* The "thread manager" thread: manages creation and termination of threads */ - -#include <features.h> -#include <errno.h> -#include <sched.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/poll.h> /* for poll */ -#include <sys/mman.h> /* for mmap */ -#include <sys/param.h> -#include <sys/time.h> -#include <sys/wait.h> /* for waitpid macros */ - -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" -#include "semaphore.h" -#include "debug.h" /* PDEBUG, added by StS */ - -#ifndef THREAD_STACK_OFFSET -#define THREAD_STACK_OFFSET 0 -#endif - -/* poll() is not supported in kernel <= 2.0, therefore is __NR_poll is - * not available, we assume an old Linux kernel is in use and we will - * use select() instead. */ -#include <sys/syscall.h> -#ifndef __NR_poll -# define USE_SELECT -#endif - -libpthread_hidden_proto(waitpid) -libpthread_hidden_proto(raise) - -/* Array of active threads. Entry 0 is reserved for the initial thread. */ -struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] = -{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0}, - { __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ }; - -/* For debugging purposes put the maximum number of threads in a variable. */ -const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; - -/* Indicate whether at least one thread has a user-defined stack (if 1), - or if all threads have stacks supplied by LinuxThreads (if 0). */ -int __pthread_nonstandard_stacks; - -/* Number of active entries in __pthread_handles (used by gdb) */ -volatile int __pthread_handles_num = 2; - -/* Whether to use debugger additional actions for thread creation - (set to 1 by gdb) */ -volatile int __pthread_threads_debug; - -/* Globally enabled events. */ -volatile td_thr_events_t __pthread_threads_events; - -/* Pointer to thread descriptor with last event. */ -volatile pthread_descr __pthread_last_event; - -/* Mapping from stack segment to thread descriptor. */ -/* Stack segment numbers are also indices into the __pthread_handles array. */ -/* Stack segment number 0 is reserved for the initial thread. */ - -static __inline__ pthread_descr thread_segment(int seg) -{ - return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE) - - 1; -} - -/* Flag set in signal handler to record child termination */ - -static volatile int terminated_children = 0; - -/* Flag set when the initial thread is blocked on pthread_exit waiting - for all other threads to terminate */ - -static int main_thread_exiting = 0; - -/* Counter used to generate unique thread identifier. - Thread identifier is pthread_threads_counter + segment. */ - -static pthread_t pthread_threads_counter = 0; - -/* Forward declarations */ - -static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, - void * (*start_routine)(void *), void *arg, - sigset_t *mask, int father_pid, - int report_events, - td_thr_events_t *event_maskp); -static void pthread_handle_free(pthread_t th_id); -static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) attribute_noreturn; -static void pthread_reap_children(void); -static void pthread_kill_all_threads(int sig, int main_thread_also); - -/* The server thread managing requests for thread creation and termination */ - -int attribute_noreturn __pthread_manager(void *arg) -{ - int reqfd = (int) (long int) arg; -#ifdef USE_SELECT - struct timeval tv; - fd_set fd; -#else - struct pollfd ufd; -#endif - sigset_t manager_mask; - int n; - struct pthread_request request; - - /* If we have special thread_self processing, initialize it. */ -#ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(&__pthread_manager_thread, 1); -#endif - /* Set the error variable. */ - __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno; - __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno; - -#ifdef __UCLIBC_HAS_XLOCALE__ - /* Initialize thread's locale to the global locale. */ - __pthread_manager_thread.locale = __global_locale; -#endif /* __UCLIBC_HAS_XLOCALE__ */ - - /* Block all signals except __pthread_sig_cancel and SIGTRAP */ - __sigfillset(&manager_mask); - sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ - sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */ - if (__pthread_threads_debug && __pthread_sig_debug > 0) - sigdelset(&manager_mask, __pthread_sig_debug); - sigprocmask(SIG_SETMASK, &manager_mask, NULL); - /* Raise our priority to match that of main thread */ - __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); - /* Synchronize debugging of the thread manager */ - n = TEMP_FAILURE_RETRY(read(reqfd, (char *)&request, - sizeof(request))); -#ifndef USE_SELECT - ufd.fd = reqfd; - ufd.events = POLLIN; -#endif - /* Enter server loop */ - while(1) { -#ifdef USE_SELECT - tv.tv_sec = 2; - tv.tv_usec = 0; - FD_ZERO (&fd); - FD_SET (reqfd, &fd); - n = select (reqfd + 1, &fd, NULL, NULL, &tv); -#else - PDEBUG("before poll\n"); - n = poll(&ufd, 1, 2000); - PDEBUG("after poll\n"); -#endif - /* Check for termination of the main thread */ - if (getppid() == 1) { - pthread_kill_all_threads(SIGKILL, 0); - _exit(0); - } - /* Check for dead children */ - if (terminated_children) { - terminated_children = 0; - pthread_reap_children(); - } - /* Read and execute request */ -#ifdef USE_SELECT - if (n == 1) -#else - if (n == 1 && (ufd.revents & POLLIN)) -#endif - { - - PDEBUG("before read\n"); - n = read(reqfd, (char *)&request, sizeof(request)); - PDEBUG("after read, n=%d\n", n); - switch(request.req_kind) { - case REQ_CREATE: - PDEBUG("got REQ_CREATE\n"); - request.req_thread->p_retcode = - pthread_handle_create((pthread_t *) &request.req_thread->p_retval, - request.req_args.create.attr, - request.req_args.create.fn, - request.req_args.create.arg, - &request.req_args.create.mask, - request.req_thread->p_pid, - request.req_thread->p_report_events, - &request.req_thread->p_eventbuf.eventmask); - PDEBUG("restarting %p\n", request.req_thread); - restart(request.req_thread); - break; - case REQ_FREE: - PDEBUG("got REQ_FREE\n"); - pthread_handle_free(request.req_args.free.thread_id); - break; - case REQ_PROCESS_EXIT: - PDEBUG("got REQ_PROCESS_EXIT from %p, exit code = %d\n", - request.req_thread, request.req_args.exit.code); - pthread_handle_exit(request.req_thread, - request.req_args.exit.code); - break; - case REQ_MAIN_THREAD_EXIT: - PDEBUG("got REQ_MAIN_THREAD_EXIT\n"); - main_thread_exiting = 1; - /* Reap children in case all other threads died and the signal handler - went off before we set main_thread_exiting to 1, and therefore did - not do REQ_KICK. */ - pthread_reap_children(); - - if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { - restart(__pthread_main_thread); - /* The main thread will now call exit() which will trigger an - __on_exit handler, which in turn will send REQ_PROCESS_EXIT - to the thread manager. In case you are wondering how the - manager terminates from its loop here. */ - } - break; - case REQ_POST: - PDEBUG("got REQ_POST\n"); - sem_post(request.req_args.post); - break; - case REQ_DEBUG: - PDEBUG("got REQ_DEBUG\n"); - /* Make gdb aware of new thread and gdb will restart the - new thread when it is ready to handle the new thread. */ - if (__pthread_threads_debug && __pthread_sig_debug > 0) { - PDEBUG("about to call raise(__pthread_sig_debug)\n"); - raise(__pthread_sig_debug); - } - case REQ_KICK: - /* This is just a prod to get the manager to reap some - threads right away, avoiding a potential delay at shutdown. */ - break; - } - } - } -} - -int attribute_noreturn __pthread_manager_event(void *arg) -{ - /* If we have special thread_self processing, initialize it. */ -#ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(&__pthread_manager_thread, 1); -#endif - - /* Get the lock the manager will free once all is correctly set up. */ - __pthread_lock (THREAD_GETMEM((&__pthread_manager_thread), p_lock), NULL); - /* Free it immediately. */ - __pthread_unlock (THREAD_GETMEM((&__pthread_manager_thread), p_lock)); - - __pthread_manager(arg); -} - -/* Process creation */ -static int -attribute_noreturn -pthread_start_thread(void *arg) -{ - pthread_descr self = (pthread_descr) arg; - struct pthread_request request; - void * outcome; - /* Initialize special thread_self processing, if any. */ -#ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(self, self->p_nr); -#endif - PDEBUG("\n"); - /* Make sure our pid field is initialized, just in case we get there - before our father has initialized it. */ - THREAD_SETMEM(self, p_pid, getpid()); - /* Initial signal mask is that of the creating thread. (Otherwise, - we'd just inherit the mask of the thread manager.) */ - sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL); - /* Set the scheduling policy and priority for the new thread, if needed */ - if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) - /* Explicit scheduling attributes were provided: apply them */ - sched_setscheduler(THREAD_GETMEM(self, p_pid), - THREAD_GETMEM(self, p_start_args.schedpolicy), - &self->p_start_args.schedparam); - else if (__pthread_manager_thread.p_priority > 0) - /* Default scheduling required, but thread manager runs in realtime - scheduling: switch new thread to SCHED_OTHER policy */ - { - struct sched_param default_params; - default_params.sched_priority = 0; - sched_setscheduler(THREAD_GETMEM(self, p_pid), - SCHED_OTHER, &default_params); - } - /* Make gdb aware of new thread */ - if (__pthread_threads_debug && __pthread_sig_debug > 0) { - request.req_thread = self; - request.req_kind = REQ_DEBUG; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - suspend(self); - } - /* Run the thread code */ - outcome = self->p_start_args.start_routine(THREAD_GETMEM(self, - p_start_args.arg)); - /* Exit with the given return value */ - __pthread_do_exit(outcome, CURRENT_STACK_FRAME); -} - -static int -attribute_noreturn -pthread_start_thread_event(void *arg) -{ - pthread_descr self = (pthread_descr) arg; - -#ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(self, self->p_nr); -#endif - /* Make sure our pid field is initialized, just in case we get there - before our father has initialized it. */ - THREAD_SETMEM(self, p_pid, getpid()); - /* Get the lock the manager will free once all is correctly set up. */ - __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); - /* Free it immediately. */ - __pthread_unlock (THREAD_GETMEM(self, p_lock)); - - /* Continue with the real function. */ - pthread_start_thread (arg); -} - -static int pthread_allocate_stack(const pthread_attr_t *attr, - pthread_descr default_new_thread, - int pagesize, - pthread_descr * out_new_thread, - char ** out_new_thread_bottom, - char ** out_guardaddr, - size_t * out_guardsize) -{ - pthread_descr new_thread; - char * new_thread_bottom; - char * guardaddr; - size_t stacksize, guardsize; - - if (attr != NULL && attr->__stackaddr_set) - { - /* The user provided a stack. */ - new_thread = (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; - new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; - guardaddr = NULL; - guardsize = 0; - __pthread_nonstandard_stacks = 1; -#ifndef __ARCH_USE_MMU__ - /* check the initial thread stack boundaries so they don't overlap */ - NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom); - - PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos, - __pthread_initial_thread_tos); -#endif - } - else - { -#ifdef __ARCH_USE_MMU__ - stacksize = STACK_SIZE - pagesize; - if (attr != NULL) - stacksize = MIN(stacksize, roundup(attr->__stacksize, pagesize)); - /* Allocate space for stack and thread descriptor at default address */ - new_thread = default_new_thread; - new_thread_bottom = (char *) (new_thread + 1) - stacksize; - if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE), - INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, - -1, 0) == MAP_FAILED) - /* Bad luck, this segment is already mapped. */ - return -1; - /* We manage to get a stack. Now see whether we need a guard - and allocate it if necessary. Notice that the default - attributes (stack_size = STACK_SIZE - pagesize) do not need - a guard page, since the RLIMIT_STACK soft limit prevents stacks - from running into one another. */ - if (stacksize == (size_t) (STACK_SIZE - pagesize)) - { - /* We don't need a guard page. */ - guardaddr = NULL; - guardsize = 0; - } - else - { - /* Put a bad page at the bottom of the stack */ - guardsize = attr->__guardsize; - guardaddr = (void *)new_thread_bottom - guardsize; - if (mmap((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0) - == MAP_FAILED) - { - /* We don't make this an error. */ - guardaddr = NULL; - guardsize = 0; - } - } -#else - /* We cannot mmap to this huge chunk of stack space when we don't have - * an MMU. Pretend we are using a user provided stack even if there was - * none provided by the user. Thus, we get around the mmap and reservation - * of a huge stack segment. -StS */ - - stacksize = INITIAL_STACK_SIZE; - /* The user may want to use a non-default stacksize */ - if (attr != NULL) - { - stacksize = attr->__stacksize; - } - - /* malloc a stack - memory from the bottom up */ - if ((new_thread_bottom = malloc(stacksize)) == NULL) - { - /* bad luck, we cannot malloc any more */ - return -1 ; - } - PDEBUG("malloced chunk: base=%p, size=0x%04x\n", new_thread_bottom, stacksize); - - /* Set up the pointers. new_thread marks the TOP of the stack frame and - * the address of the pthread_descr struct at the same time. Therefore we - * must account for its size and fit it in the malloc()'ed block. The - * value of `new_thread' is then passed to clone() as the stack argument. - * - * ^ +------------------------+ - * | | pthread_descr struct | - * | +------------------------+ <- new_thread - * malloc block | | | - * | | thread stack | - * | | | - * v +------------------------+ <- new_thread_bottom - * - * Note: The calculated value of new_thread must be word aligned otherwise - * the kernel chokes on a non-aligned stack frame. Choose the lower - * available word boundary. - */ - new_thread = ((pthread_descr) ((int)(new_thread_bottom + stacksize) & -sizeof(void*))) - 1; - guardaddr = NULL; - guardsize = 0; - - PDEBUG("thread stack: bos=%p, tos=%p\n", new_thread_bottom, new_thread); - - /* check the initial thread stack boundaries so they don't overlap */ - NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom); - - PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos, - __pthread_initial_thread_tos); - - /* on non-MMU systems we always have non-standard stack frames */ - __pthread_nonstandard_stacks = 1; - -#endif /* __ARCH_USE_MMU__ */ - } - - /* Clear the thread data structure. */ - memset (new_thread, '\0', sizeof (*new_thread)); - *out_new_thread = new_thread; - *out_new_thread_bottom = new_thread_bottom; - *out_guardaddr = guardaddr; - *out_guardsize = guardsize; - return 0; -} - -static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, - void * (*start_routine)(void *), void *arg, - sigset_t * mask, int father_pid, - int report_events, - td_thr_events_t *event_maskp) -{ - size_t sseg; - int pid; - pthread_descr new_thread; - char * new_thread_bottom; - char * new_thread_top; - pthread_t new_thread_id; - char *guardaddr = NULL; - size_t guardsize = 0; - int pagesize = getpagesize(); - int saved_errno = 0; - - /* First check whether we have to change the policy and if yes, whether - we can do this. Normally this should be done by examining the - return value of the sched_setscheduler call in pthread_start_thread - but this is hard to implement. FIXME */ - if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0) - return EPERM; - /* Find a free segment for the thread, and allocate a stack if needed */ - for (sseg = 2; ; sseg++) - { - if (sseg >= PTHREAD_THREADS_MAX) - return EAGAIN; - if (__pthread_handles[sseg].h_descr != NULL) - continue; - if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize, - &new_thread, &new_thread_bottom, - &guardaddr, &guardsize) == 0) - break; -#ifndef __ARCH_USE_MMU__ - else - /* When there is MMU, mmap () is used to allocate the stack. If one - * segment is already mapped, we should continue to see if we can - * use the next one. However, when there is no MMU, malloc () is used. - * It's waste of CPU cycles to continue to try if it fails. */ - return EAGAIN; -#endif - } - __pthread_handles_num++; - /* Allocate new thread identifier */ - pthread_threads_counter += PTHREAD_THREADS_MAX; - new_thread_id = sseg + pthread_threads_counter; - /* Initialize the thread descriptor. Elements which have to be - initialized to zero already have this value. */ - new_thread->p_tid = new_thread_id; - new_thread->p_lock = &(__pthread_handles[sseg].h_lock); - new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; - new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; - new_thread->p_errnop = &new_thread->p_errno; - new_thread->p_h_errnop = &new_thread->p_h_errno; -#ifdef __UCLIBC_HAS_XLOCALE__ - /* Initialize thread's locale to the global locale. */ - new_thread->locale = __global_locale; -#endif /* __UCLIBC_HAS_XLOCALE__ */ - new_thread->p_guardaddr = guardaddr; - new_thread->p_guardsize = guardsize; - new_thread->p_self = new_thread; - new_thread->p_nr = sseg; - /* Initialize the thread handle */ - __pthread_init_lock(&__pthread_handles[sseg].h_lock); - __pthread_handles[sseg].h_descr = new_thread; - __pthread_handles[sseg].h_bottom = new_thread_bottom; - /* Determine scheduling parameters for the thread */ - new_thread->p_start_args.schedpolicy = -1; - if (attr != NULL) { - new_thread->p_detached = attr->__detachstate; - new_thread->p_userstack = attr->__stackaddr_set; - - switch(attr->__inheritsched) { - case PTHREAD_EXPLICIT_SCHED: - new_thread->p_start_args.schedpolicy = attr->__schedpolicy; - memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam, - sizeof (struct sched_param)); - break; - case PTHREAD_INHERIT_SCHED: - new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid); - sched_getparam(father_pid, &new_thread->p_start_args.schedparam); - break; - } - new_thread->p_priority = - new_thread->p_start_args.schedparam.sched_priority; - } - /* Finish setting up arguments to pthread_start_thread */ - new_thread->p_start_args.start_routine = start_routine; - new_thread->p_start_args.arg = arg; - new_thread->p_start_args.mask = *mask; - /* Raise priority of thread manager if needed */ - __pthread_manager_adjust_prio(new_thread->p_priority); - /* Do the cloning. We have to use two different functions depending - on whether we are debugging or not. */ - pid = 0; /* Note that the thread never can have PID zero. */ - new_thread_top = ((char *)new_thread - THREAD_STACK_OFFSET); - - /* ******************************************************** */ - /* This code was moved from below to cope with running threads - * on uClinux systems. See comment below... - * Insert new thread in doubly linked list of active threads */ - new_thread->p_prevlive = __pthread_main_thread; - new_thread->p_nextlive = __pthread_main_thread->p_nextlive; - __pthread_main_thread->p_nextlive->p_prevlive = new_thread; - __pthread_main_thread->p_nextlive = new_thread; - /* ********************************************************* */ - - if (report_events) - { - /* See whether the TD_CREATE event bit is set in any of the - masks. */ - int idx = __td_eventword (TD_CREATE); - uint32_t m = __td_eventmask (TD_CREATE); - - if ((m & (__pthread_threads_events.event_bits[idx] - | event_maskp->event_bits[idx])) != 0) - { - /* Lock the mutex the child will use now so that it will stop. */ - __pthread_lock(new_thread->p_lock, NULL); - - /* We have to report this event. */ -#ifdef __ia64__ - pid = __clone2(pthread_start_thread_event, new_thread_top, - new_thread_top - new_thread_bottom, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | - __pthread_sig_cancel, new_thread); -#else - pid = clone(pthread_start_thread_event, new_thread_top, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | - __pthread_sig_cancel, new_thread); -#endif - - saved_errno = errno; - if (pid != -1) - { - /* Now fill in the information about the new thread in - the newly created thread's data structure. We cannot let - the new thread do this since we don't know whether it was - already scheduled when we send the event. */ - new_thread->p_eventbuf.eventdata = new_thread; - new_thread->p_eventbuf.eventnum = TD_CREATE; - __pthread_last_event = new_thread; - - /* We have to set the PID here since the callback function - in the debug library will need it and we cannot guarantee - the child got scheduled before the debugger. */ - new_thread->p_pid = pid; - - /* Now call the function which signals the event. */ - __linuxthreads_create_event (); - - /* Now restart the thread. */ - __pthread_unlock(new_thread->p_lock); - } - } - } - if (pid == 0) - { - PDEBUG("cloning new_thread = %p\n", new_thread); -#ifdef __ia64__ - pid = __clone2(pthread_start_thread, new_thread_top, - new_thread_top - new_thread_bottom, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | - __pthread_sig_cancel, new_thread); -#else - pid = clone(pthread_start_thread, new_thread_top, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | - __pthread_sig_cancel, new_thread); -#endif - saved_errno = errno; - } - /* Check if cloning succeeded */ - if (pid == -1) { - /******************************************************** - * Code inserted to remove the thread from our list of active - * threads in case of failure (needed to cope with uClinux), - * See comment below. */ - new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive; - new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive; - /********************************************************/ - - /* Free the stack if we allocated it */ - if (attr == NULL || !attr->__stackaddr_set) - { -#ifdef __ARCH_USE_MMU__ - if (new_thread->p_guardsize != 0) - munmap(new_thread->p_guardaddr, new_thread->p_guardsize); - munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE), - INITIAL_STACK_SIZE); -#else - free(new_thread_bottom); -#endif /* __ARCH_USE_MMU__ */ - } - __pthread_handles[sseg].h_descr = NULL; - __pthread_handles[sseg].h_bottom = NULL; - __pthread_handles_num--; - return saved_errno; - } - PDEBUG("new thread pid = %d\n", pid); - -#if 0 - /* *********************************************************** - This code has been moved before the call to clone(). In uClinux, - the use of wait on a semaphore is dependant upon that the child so - the child must be in the active threads list. This list is used in - pthread_find_self() to get the pthread_descr of self. So, if the - child calls sem_wait before this code is executed , it will hang - forever and initial_thread will instead be posted by a sem_post - call. */ - - /* Insert new thread in doubly linked list of active threads */ - new_thread->p_prevlive = __pthread_main_thread; - new_thread->p_nextlive = __pthread_main_thread->p_nextlive; - __pthread_main_thread->p_nextlive->p_prevlive = new_thread; - __pthread_main_thread->p_nextlive = new_thread; - /************************************************************/ -#endif - - /* Set pid field of the new thread, in case we get there before the - child starts. */ - new_thread->p_pid = pid; - /* We're all set */ - *thread = new_thread_id; - return 0; -} - - -/* Try to free the resources of a thread when requested by pthread_join - or pthread_detach on a terminated thread. */ - -static void pthread_free(pthread_descr th) -{ - pthread_handle handle; - pthread_readlock_info *iter, *next; -#ifndef __ARCH_USE_MMU__ - char *h_bottom_save; -#endif - - /* Make the handle invalid */ - handle = thread_handle(th->p_tid); - __pthread_lock(&handle->h_lock, NULL); -#ifndef __ARCH_USE_MMU__ - h_bottom_save = handle->h_bottom; -#endif - handle->h_descr = NULL; - handle->h_bottom = (char *)(-1L); - __pthread_unlock(&handle->h_lock); -#ifdef FREE_THREAD_SELF - FREE_THREAD_SELF(th, th->p_nr); -#endif - /* One fewer threads in __pthread_handles */ - __pthread_handles_num--; - - /* Destroy read lock list, and list of free read lock structures. - If the former is not empty, it means the thread exited while - holding read locks! */ - - for (iter = th->p_readlock_list; iter != NULL; iter = next) - { - next = iter->pr_next; - free(iter); - } - - for (iter = th->p_readlock_free; iter != NULL; iter = next) - { - next = iter->pr_next; - free(iter); - } - - /* If initial thread, nothing to free */ - if (th == &__pthread_initial_thread) return; - if (!th->p_userstack) - { -#ifdef __ARCH_USE_MMU__ - /* Free the stack and thread descriptor area */ - if (th->p_guardsize != 0) - munmap(th->p_guardaddr, th->p_guardsize); - munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE); -#else - /* For non-MMU systems we always malloc the stack, so free it here. -StS */ - free(h_bottom_save); -#endif /* __ARCH_USE_MMU__ */ - } -} - -/* Handle threads that have exited */ - -static void pthread_exited(pid_t pid) -{ - pthread_descr th; - int detached; - /* Find thread with that pid */ - for (th = __pthread_main_thread->p_nextlive; - th != __pthread_main_thread; - th = th->p_nextlive) { - if (th->p_pid == pid) { - /* Remove thread from list of active threads */ - th->p_nextlive->p_prevlive = th->p_prevlive; - th->p_prevlive->p_nextlive = th->p_nextlive; - /* Mark thread as exited, and if detached, free its resources */ - __pthread_lock(th->p_lock, NULL); - th->p_exited = 1; - /* If we have to signal this event do it now. */ - if (th->p_report_events) - { - /* See whether TD_REAP is in any of the mask. */ - int idx = __td_eventword (TD_REAP); - uint32_t mask = __td_eventmask (TD_REAP); - - if ((mask & (__pthread_threads_events.event_bits[idx] - | th->p_eventbuf.eventmask.event_bits[idx])) != 0) - { - /* Yep, we have to signal the reapage. */ - th->p_eventbuf.eventnum = TD_REAP; - th->p_eventbuf.eventdata = th; - __pthread_last_event = th; - - /* Now call the function to signal the event. */ - __linuxthreads_reap_event(); - } - } - detached = th->p_detached; - __pthread_unlock(th->p_lock); - if (detached) - pthread_free(th); - break; - } - } - /* If all threads have exited and the main thread is pending on a - pthread_exit, wake up the main thread and terminate ourselves. */ - if (main_thread_exiting && - __pthread_main_thread->p_nextlive == __pthread_main_thread) { - restart(__pthread_main_thread); - /* Same logic as REQ_MAIN_THREAD_EXIT. */ - } -} - -static void pthread_reap_children(void) -{ - pid_t pid; - int status; - PDEBUG("\n"); - - while ((pid = waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) { - pthread_exited(pid); - if (WIFSIGNALED(status)) { - /* If a thread died due to a signal, send the same signal to - all other threads, including the main thread. */ - pthread_kill_all_threads(WTERMSIG(status), 1); - _exit(0); - } - } -} - -/* Try to free the resources of a thread when requested by pthread_join - or pthread_detach on a terminated thread. */ - -static void pthread_handle_free(pthread_t th_id) -{ - pthread_handle handle = thread_handle(th_id); - pthread_descr th; - - __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, th_id)) { - /* pthread_reap_children has deallocated the thread already, - nothing needs to be done */ - __pthread_unlock(&handle->h_lock); - return; - } - th = handle->h_descr; - if (th->p_exited) { - __pthread_unlock(&handle->h_lock); - pthread_free(th); - } else { - /* The Unix process of the thread is still running. - Mark the thread as detached so that the thread manager will - deallocate its resources when the Unix process exits. */ - th->p_detached = 1; - __pthread_unlock(&handle->h_lock); - } -} - -/* Send a signal to all running threads */ - -static void pthread_kill_all_threads(int sig, int main_thread_also) -{ - pthread_descr th; - for (th = __pthread_main_thread->p_nextlive; - th != __pthread_main_thread; - th = th->p_nextlive) { - kill(th->p_pid, sig); - } - if (main_thread_also) { - kill(__pthread_main_thread->p_pid, sig); - } -} - -/* Process-wide exit() */ - -static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) -{ - pthread_descr th; - __pthread_exit_requested = 1; - __pthread_exit_code = exitcode; - /* Send the CANCEL signal to all running threads, including the main - thread, but excluding the thread from which the exit request originated - (that thread must complete the exit, e.g. calling atexit functions - and flushing stdio buffers). */ - for (th = issuing_thread->p_nextlive; - th != issuing_thread; - th = th->p_nextlive) { - kill(th->p_pid, __pthread_sig_cancel); - } - /* Now, wait for all these threads, so that they don't become zombies - and their times are properly added to the thread manager's times. */ - for (th = issuing_thread->p_nextlive; - th != issuing_thread; - th = th->p_nextlive) { - waitpid(th->p_pid, NULL, __WCLONE); - } - restart(issuing_thread); - _exit(0); -} - -/* Handler for __pthread_sig_cancel in thread manager thread */ - -void __pthread_manager_sighandler(int sig attribute_unused) -{ - int kick_manager = terminated_children == 0 && main_thread_exiting; - terminated_children = 1; - - /* If the main thread is terminating, kick the thread manager loop - each time some threads terminate. This eliminates a two second - shutdown delay caused by the thread manager sleeping in the - call to __poll(). Instead, the thread manager is kicked into - action, reaps the outstanding threads and resumes the main thread - so that it can complete the shutdown. */ - - if (kick_manager) { - struct pthread_request request; - request.req_thread = 0; - request.req_kind = REQ_KICK; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - } -} - -/* Adjust priority of thread manager so that it always run at a priority - higher than all threads */ - -void __pthread_manager_adjust_prio(int thread_prio) -{ - struct sched_param param; - - if (thread_prio <= __pthread_manager_thread.p_priority) return; - param.sched_priority = - thread_prio < sched_get_priority_max(SCHED_FIFO) - ? thread_prio + 1 : thread_prio; - sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, ¶m); - __pthread_manager_thread.p_priority = thread_prio; -} diff --git a/libpthread/linuxthreads.old/mutex.c b/libpthread/linuxthreads.old/mutex.c deleted file mode 100644 index 890841452..000000000 --- a/libpthread/linuxthreads.old/mutex.c +++ /dev/null @@ -1,362 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Mutexes */ - -#include <errno.h> -#include <sched.h> -#include <stddef.h> -#include <limits.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "queue.h" -#include "restart.h" - -int attribute_hidden __pthread_mutex_init(pthread_mutex_t * mutex, - const pthread_mutexattr_t * mutex_attr) -{ - __pthread_init_lock(&mutex->__m_lock); - mutex->__m_kind = - mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind; - mutex->__m_count = 0; - mutex->__m_owner = NULL; - return 0; -} -strong_alias (__pthread_mutex_init, pthread_mutex_init) - -int attribute_hidden __pthread_mutex_destroy(pthread_mutex_t * mutex) -{ - switch (mutex->__m_kind) { - case PTHREAD_MUTEX_ADAPTIVE_NP: - case PTHREAD_MUTEX_RECURSIVE_NP: - if ((mutex->__m_lock.__status & 1) != 0) - return EBUSY; - return 0; - case PTHREAD_MUTEX_ERRORCHECK_NP: - case PTHREAD_MUTEX_TIMED_NP: - if (mutex->__m_lock.__status != 0) - return EBUSY; - return 0; - default: - return EINVAL; - } -} -strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) - -int attribute_hidden __pthread_mutex_trylock(pthread_mutex_t * mutex) -{ - pthread_descr self; - int retcode; - - switch(mutex->__m_kind) { - case PTHREAD_MUTEX_ADAPTIVE_NP: - retcode = __pthread_trylock(&mutex->__m_lock); - return retcode; - case PTHREAD_MUTEX_RECURSIVE_NP: - self = thread_self(); - if (mutex->__m_owner == self) { - mutex->__m_count++; - return 0; - } - retcode = __pthread_trylock(&mutex->__m_lock); - if (retcode == 0) { - mutex->__m_owner = self; - mutex->__m_count = 0; - } - return retcode; - case PTHREAD_MUTEX_ERRORCHECK_NP: - retcode = __pthread_alt_trylock(&mutex->__m_lock); - if (retcode == 0) { - mutex->__m_owner = thread_self(); - } - return retcode; - case PTHREAD_MUTEX_TIMED_NP: - retcode = __pthread_alt_trylock(&mutex->__m_lock); - return retcode; - default: - return EINVAL; - } -} -strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) - -int attribute_hidden __pthread_mutex_lock(pthread_mutex_t * mutex) -{ - pthread_descr self; - - switch(mutex->__m_kind) { - case PTHREAD_MUTEX_ADAPTIVE_NP: - __pthread_lock(&mutex->__m_lock, NULL); - return 0; - case PTHREAD_MUTEX_RECURSIVE_NP: - self = thread_self(); - if (mutex->__m_owner == self) { - mutex->__m_count++; - return 0; - } - __pthread_lock(&mutex->__m_lock, self); - mutex->__m_owner = self; - mutex->__m_count = 0; - return 0; - case PTHREAD_MUTEX_ERRORCHECK_NP: - self = thread_self(); - if (mutex->__m_owner == self) return EDEADLK; - __pthread_alt_lock(&mutex->__m_lock, self); - mutex->__m_owner = self; - return 0; - case PTHREAD_MUTEX_TIMED_NP: - __pthread_alt_lock(&mutex->__m_lock, NULL); - return 0; - default: - return EINVAL; - } -} -strong_alias (__pthread_mutex_lock, pthread_mutex_lock) - -int pthread_mutex_timedlock (pthread_mutex_t *mutex, - const struct timespec *abstime) -{ - pthread_descr self; - int res; - - if (__builtin_expect (abstime->tv_nsec, 0) < 0 - || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000) - return EINVAL; - - switch(mutex->__m_kind) { - case PTHREAD_MUTEX_ADAPTIVE_NP: - __pthread_lock(&mutex->__m_lock, NULL); - return 0; - case PTHREAD_MUTEX_RECURSIVE_NP: - self = thread_self(); - if (mutex->__m_owner == self) { - mutex->__m_count++; - return 0; - } - __pthread_lock(&mutex->__m_lock, self); - mutex->__m_owner = self; - mutex->__m_count = 0; - return 0; - case PTHREAD_MUTEX_ERRORCHECK_NP: - self = thread_self(); - if (mutex->__m_owner == self) return EDEADLK; - res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime); - if (res != 0) - { - mutex->__m_owner = self; - return 0; - } - return ETIMEDOUT; - case PTHREAD_MUTEX_TIMED_NP: - /* Only this type supports timed out lock. */ - return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime) - ? 0 : ETIMEDOUT); - default: - return EINVAL; - } -} - -int attribute_hidden __pthread_mutex_unlock(pthread_mutex_t * mutex) -{ - switch (mutex->__m_kind) { - case PTHREAD_MUTEX_ADAPTIVE_NP: - __pthread_unlock(&mutex->__m_lock); - return 0; - case PTHREAD_MUTEX_RECURSIVE_NP: - if (mutex->__m_owner != thread_self()) - return EPERM; - if (mutex->__m_count > 0) { - mutex->__m_count--; - return 0; - } - mutex->__m_owner = NULL; - __pthread_unlock(&mutex->__m_lock); - return 0; - case PTHREAD_MUTEX_ERRORCHECK_NP: - if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0) - return EPERM; - mutex->__m_owner = NULL; - __pthread_alt_unlock(&mutex->__m_lock); - return 0; - case PTHREAD_MUTEX_TIMED_NP: - __pthread_alt_unlock(&mutex->__m_lock); - return 0; - default: - return EINVAL; - } -} -strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) - -int attribute_hidden __pthread_mutexattr_init(pthread_mutexattr_t *attr) -{ - attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP; - return 0; -} -strong_alias(__pthread_mutexattr_init,pthread_mutexattr_init) - -int attribute_hidden __pthread_mutexattr_destroy(pthread_mutexattr_t *attr attribute_unused) -{ - return 0; -} -strong_alias(__pthread_mutexattr_destroy,pthread_mutexattr_destroy) - -int attribute_hidden __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) -{ - if (kind != PTHREAD_MUTEX_ADAPTIVE_NP - && kind != PTHREAD_MUTEX_RECURSIVE_NP - && kind != PTHREAD_MUTEX_ERRORCHECK_NP - && kind != PTHREAD_MUTEX_TIMED_NP) - return EINVAL; - attr->__mutexkind = kind; - return 0; -} -strong_alias(__pthread_mutexattr_settype,pthread_mutexattr_settype) -strong_alias (__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np) -weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np) - -int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) attribute_hidden; -int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) -{ - *kind = attr->__mutexkind; - return 0; -} -weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype) -strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np) -weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np) - -int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused, - int *pshared) attribute_hidden; -int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused, - int *pshared) -{ - *pshared = PTHREAD_PROCESS_PRIVATE; - return 0; -} -weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared) - -int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) attribute_hidden; -int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) -{ - if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) - return EINVAL; - - /* For now it is not possible to shared a conditional variable. */ - if (pshared != PTHREAD_PROCESS_PRIVATE) - return ENOSYS; - - return 0; -} -weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared) - -/* Once-only execution */ - -static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER; -static int fork_generation = 0; /* Child process increments this after fork. */ - -enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 }; - -/* If a thread is canceled while calling the init_routine out of - pthread once, this handler will reset the once_control variable - to the NEVER state. */ - -static void pthread_once_cancelhandler(void *arg) -{ - pthread_once_t *once_control = arg; - - __pthread_mutex_lock(&once_masterlock); - *once_control = NEVER; - __pthread_mutex_unlock(&once_masterlock); - pthread_cond_broadcast(&once_finished); -} - -int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) -{ - /* flag for doing the condition broadcast outside of mutex */ - int state_changed; - - /* Test without locking first for speed */ - if (*once_control == DONE) { - READ_MEMORY_BARRIER(); - return 0; - } - /* Lock and test again */ - - state_changed = 0; - - __pthread_mutex_lock(&once_masterlock); - - /* If this object was left in an IN_PROGRESS state in a parent - process (indicated by stale generation field), reset it to NEVER. */ - if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation) - *once_control = NEVER; - - /* If init_routine is being called from another routine, wait until - it completes. */ - while ((*once_control & 3) == IN_PROGRESS) { - pthread_cond_wait(&once_finished, &once_masterlock); - } - /* Here *once_control is stable and either NEVER or DONE. */ - if (*once_control == NEVER) { - *once_control = IN_PROGRESS | fork_generation; - __pthread_mutex_unlock(&once_masterlock); - pthread_cleanup_push(pthread_once_cancelhandler, once_control); - init_routine(); - pthread_cleanup_pop(0); - __pthread_mutex_lock(&once_masterlock); - WRITE_MEMORY_BARRIER(); - *once_control = DONE; - state_changed = 1; - } - __pthread_mutex_unlock(&once_masterlock); - - if (state_changed) - pthread_cond_broadcast(&once_finished); - - return 0; -} -strong_alias (__pthread_once, pthread_once) - -/* - * Handle the state of the pthread_once mechanism across forks. The - * once_masterlock is acquired in the parent process prior to a fork to ensure - * that no thread is in the critical region protected by the lock. After the - * fork, the lock is released. In the child, the lock and the condition - * variable are simply reset. The child also increments its generation - * counter which lets pthread_once calls detect stale IN_PROGRESS states - * and reset them back to NEVER. - */ - -void __pthread_once_fork_prepare(void); -void __pthread_once_fork_prepare(void) -{ - __pthread_mutex_lock(&once_masterlock); -} - -void __pthread_once_fork_parent(void); -void __pthread_once_fork_parent(void) -{ - __pthread_mutex_unlock(&once_masterlock); -} - -void __pthread_once_fork_child(void); -void __pthread_once_fork_child(void) -{ - __pthread_mutex_init(&once_masterlock, NULL); - pthread_cond_init(&once_finished, NULL); - if (fork_generation <= INT_MAX - 4) - fork_generation += 4; /* leave least significant two bits zero */ - else - fork_generation = 0; -} diff --git a/libpthread/linuxthreads.old/pt-machine.c b/libpthread/linuxthreads.old/pt-machine.c deleted file mode 100644 index 6963dfcab..000000000 --- a/libpthread/linuxthreads.old/pt-machine.c +++ /dev/null @@ -1,21 +0,0 @@ -/* "Instantiation of machine-dependent pthreads inline functions. - Copyright (C) 1998 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, - see <http://www.gnu.org/licenses/>. */ - -#define PT_EI - -#include <pt-machine.h> diff --git a/libpthread/linuxthreads.old/ptfork.c b/libpthread/linuxthreads.old/ptfork.c deleted file mode 100644 index 6f1e2d3c9..000000000 --- a/libpthread/linuxthreads.old/ptfork.c +++ /dev/null @@ -1,167 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* mods for uClibc: removed strong alias and defined funcs properly */ - -/* The "atfork" stuff */ - -#include <errno.h> - -#ifdef __ARCH_USE_MMU__ - -#include <bits/uClibc_mutex.h> -#include <stddef.h> -#include <stdlib.h> -#include <unistd.h> -#include "pthread.h" -#include "internals.h" - -struct handler_list { - void (*handler)(void); - struct handler_list * next; -}; - -static pthread_mutex_t pthread_atfork_lock = PTHREAD_MUTEX_INITIALIZER; -static struct handler_list * pthread_atfork_prepare = NULL; -static struct handler_list * pthread_atfork_parent = NULL; -static struct handler_list * pthread_atfork_child = NULL; - -#ifdef __MALLOC__ -__UCLIBC_MUTEX_EXTERN(__malloc_heap_lock); -__UCLIBC_MUTEX_EXTERN(__malloc_sbrk_lock); -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ -__UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock); -#endif -#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) -__UCLIBC_MUTEX_EXTERN(__malloc_lock); -#endif - -static void pthread_insert_list(struct handler_list ** list, - void (*handler)(void), - struct handler_list * newlist, - int at_end) -{ - if (handler == NULL) return; - if (at_end) { - while(*list != NULL) list = &((*list)->next); - } - newlist->handler = handler; - newlist->next = *list; - *list = newlist; -} - -struct handler_list_block { - struct handler_list prepare, parent, child; -}; - -int pthread_atfork(void (*prepare)(void), - void (*parent)(void), - void (*child)(void)) -{ - struct handler_list_block * block = - (struct handler_list_block *) malloc(sizeof(struct handler_list_block)); - if (block == NULL) return ENOMEM; - __pthread_mutex_lock(&pthread_atfork_lock); - /* "prepare" handlers are called in LIFO */ - pthread_insert_list(&pthread_atfork_prepare, prepare, &block->prepare, 0); - /* "parent" handlers are called in FIFO */ - pthread_insert_list(&pthread_atfork_parent, parent, &block->parent, 1); - /* "child" handlers are called in FIFO */ - pthread_insert_list(&pthread_atfork_child, child, &block->child, 1); - __pthread_mutex_unlock(&pthread_atfork_lock); - return 0; -} -/*strong_alias (__pthread_atfork, pthread_atfork)*/ - -static __inline__ void pthread_call_handlers(struct handler_list * list) -{ - for (/*nothing*/; list != NULL; list = list->next) (list->handler)(); -} - -void __pthread_once_fork_prepare(void); -void __pthread_once_fork_child(void); -void __pthread_once_fork_parent(void); - -static pid_t __fork(void) -{ - pid_t pid; - struct handler_list * prepare, * child, * parent; - - __pthread_mutex_lock(&pthread_atfork_lock); - prepare = pthread_atfork_prepare; - child = pthread_atfork_child; - parent = pthread_atfork_parent; - pthread_call_handlers(prepare); - - __pthread_once_fork_prepare(); -#ifdef __MALLOC__ - __pthread_mutex_lock(&__malloc_sbrk_lock); - __pthread_mutex_lock(&__malloc_heap_lock); -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ - __pthread_mutex_lock(&__malloc_mmb_heap_lock); -#endif -#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) - __pthread_mutex_lock(&__malloc_lock); -#endif - - pid = __libc_fork(); - if (pid == 0) { -#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) - __libc_lock_init_recursive(__malloc_lock); -#elif defined(__MALLOC__) -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ - __libc_lock_init_adaptive(__malloc_mmb_heap_lock); -#endif - __libc_lock_init_adaptive(__malloc_heap_lock); - __libc_lock_init(__malloc_sbrk_lock); -#endif - __libc_lock_init_adaptive(pthread_atfork_lock); - __pthread_reset_main_thread(); - __fresetlockfiles(); - __pthread_once_fork_child(); - pthread_call_handlers(child); - } else { -#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) - __pthread_mutex_unlock(&__malloc_lock); -#elif defined(__MALLOC__) -#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ - __pthread_mutex_unlock(&__malloc_mmb_heap_lock); -#endif - __pthread_mutex_unlock(&__malloc_heap_lock); - __pthread_mutex_unlock(&__malloc_sbrk_lock); -#endif - __pthread_mutex_unlock(&pthread_atfork_lock); - __pthread_once_fork_parent(); - pthread_call_handlers(parent); - } - return pid; -} -strong_alias(__fork,fork) -strong_alias(__fork,vfork) - -#else - -/* We can't support pthread_atfork without MMU, since we don't have - fork(), and we can't offer the correct semantics for vfork(). */ -int pthread_atfork(void (*prepare)(void), - void (*parent)(void), - void (*child)(void)) -{ - /* ENOMEM is probably pushing it a little bit. - Take it as `no *virtual* memory' :-) */ - errno = ENOMEM; - return -1; -} - -#endif diff --git a/libpthread/linuxthreads.old/pthread.c b/libpthread/linuxthreads.old/pthread.c deleted file mode 100644 index 00197b158..000000000 --- a/libpthread/linuxthreads.old/pthread.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Thread creation, initialization, and basic low-level routines */ - -#include <errno.h> -#include <netdb.h> /* for h_errno */ -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" -#include "debug.h" /* added to linuxthreads -StS */ - - -/* Mods for uClibc: Some includes */ -#include <signal.h> -#include <sys/types.h> -#include <sys/syscall.h> - -libpthread_hidden_proto(waitpid) -libpthread_hidden_proto(raise) - -/* These variables are used by the setup code. */ -extern int _errno; -extern int _h_errno; - - -/* Descriptor of the initial thread */ - -struct _pthread_descr_struct __pthread_initial_thread = { - &__pthread_initial_thread, /* pthread_descr p_nextlive */ - &__pthread_initial_thread, /* pthread_descr p_prevlive */ - NULL, /* pthread_descr p_nextwaiting */ - NULL, /* pthread_descr p_nextlock */ - PTHREAD_THREADS_MAX, /* pthread_t p_tid */ - 0, /* int p_pid */ - 0, /* int p_priority */ - &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */ - 0, /* int p_signal */ - NULL, /* sigjmp_buf * p_signal_buf */ - NULL, /* sigjmp_buf * p_cancel_buf */ - 0, /* char p_terminated */ - 0, /* char p_detached */ - 0, /* char p_exited */ - NULL, /* void * p_retval */ - 0, /* int p_retval */ - NULL, /* pthread_descr p_joining */ - NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ - 0, /* char p_cancelstate */ - 0, /* char p_canceltype */ - 0, /* char p_canceled */ - &_errno, /* int *p_errnop */ - 0, /* int p_errno */ - &_h_errno, /* int *p_h_errnop */ - 0, /* int p_h_errno */ - NULL, /* char * p_in_sighandler */ - 0, /* char p_sigwaiting */ - PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */ - {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ - {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ - 0, /* int p_userstack */ - NULL, /* void * p_guardaddr */ - 0, /* size_t p_guardsize */ - &__pthread_initial_thread, /* pthread_descr p_self */ - 0, /* Always index 0 */ - 0, /* int p_report_events */ - {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ - __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ - 0, /* char p_woken_by_cancel */ - 0, /* char p_condvar_avail */ - 0, /* char p_sem_avail */ - NULL, /* struct pthread_extricate_if *p_extricate */ - NULL, /* pthread_readlock_info *p_readlock_list; */ - NULL, /* pthread_readlock_info *p_readlock_free; */ - 0 /* int p_untracked_readlock_count; */ -#ifdef __UCLIBC_HAS_XLOCALE__ - , - &__global_locale_data, /* __locale_t locale; */ -#endif /* __UCLIBC_HAS_XLOCALE__ */ -}; - -/* Descriptor of the manager thread; none of this is used but the error - variables, the p_pid and p_priority fields, - and the address for identification. */ -#define manager_thread (&__pthread_manager_thread) -struct _pthread_descr_struct __pthread_manager_thread = { - NULL, /* pthread_descr p_nextlive */ - NULL, /* pthread_descr p_prevlive */ - NULL, /* pthread_descr p_nextwaiting */ - NULL, /* pthread_descr p_nextlock */ - 0, /* int p_tid */ - 0, /* int p_pid */ - 0, /* int p_priority */ - &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */ - 0, /* int p_signal */ - NULL, /* sigjmp_buf * p_signal_buf */ - NULL, /* sigjmp_buf * p_cancel_buf */ - 0, /* char p_terminated */ - 0, /* char p_detached */ - 0, /* char p_exited */ - NULL, /* void * p_retval */ - 0, /* int p_retval */ - NULL, /* pthread_descr p_joining */ - NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ - 0, /* char p_cancelstate */ - 0, /* char p_canceltype */ - 0, /* char p_canceled */ - &__pthread_manager_thread.p_errno, /* int *p_errnop */ - 0, /* int p_errno */ - NULL, /* int *p_h_errnop */ - 0, /* int p_h_errno */ - NULL, /* char * p_in_sighandler */ - 0, /* char p_sigwaiting */ - PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */ - {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ - {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ - 0, /* int p_userstack */ - NULL, /* void * p_guardaddr */ - 0, /* size_t p_guardsize */ - &__pthread_manager_thread, /* pthread_descr p_self */ - 1, /* Always index 1 */ - 0, /* int p_report_events */ - {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ - __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ - 0, /* char p_woken_by_cancel */ - 0, /* char p_condvar_avail */ - 0, /* char p_sem_avail */ - NULL, /* struct pthread_extricate_if *p_extricate */ - NULL, /* pthread_readlock_info *p_readlock_list; */ - NULL, /* pthread_readlock_info *p_readlock_free; */ - 0 /* int p_untracked_readlock_count; */ -#ifdef __UCLIBC_HAS_XLOCALE__ - , - &__global_locale_data, /* __locale_t locale; */ -#endif /* __UCLIBC_HAS_XLOCALE__ */ -}; - -/* Pointer to the main thread (the father of the thread manager thread) */ -/* Originally, this is the initial thread, but this changes after fork() */ - -pthread_descr __pthread_main_thread = &__pthread_initial_thread; - -/* Limit between the stack of the initial thread (above) and the - stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ - -char *__pthread_initial_thread_bos = NULL; - -#ifndef __ARCH_USE_MMU__ -/* See nommu notes in internals.h and pthread_initialize() below. */ -char *__pthread_initial_thread_tos = NULL; -char *__pthread_initial_thread_mid = NULL; -#endif /* __ARCH_USE_MMU__ */ - -/* File descriptor for sending requests to the thread manager. */ -/* Initially -1, meaning that the thread manager is not running. */ - -int __pthread_manager_request = -1; - -/* Other end of the pipe for sending requests to the thread manager. */ - -int __pthread_manager_reader; - -/* Limits of the thread manager stack */ - -char *__pthread_manager_thread_bos = NULL; -char *__pthread_manager_thread_tos = NULL; - -/* For process-wide exit() */ - -int __pthread_exit_requested = 0; -int __pthread_exit_code = 0; - -/* Communicate relevant LinuxThreads constants to gdb */ - -const int __pthread_threads_max = PTHREAD_THREADS_MAX; -const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct); -const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, h_descr); -const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct, - p_pid); -const int __linuxthreads_pthread_sizeof_descr - = sizeof(struct _pthread_descr_struct); - -const int __linuxthreads_initial_report_events; - -const char __linuxthreads_version[] = VERSION; - -/* Forward declarations */ -static void pthread_onexit_process(int retcode, void *arg); -static void pthread_handle_sigcancel(int sig); -static void pthread_handle_sigrestart(int sig); -static void pthread_handle_sigdebug(int sig); -int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); - -/* Signal numbers used for the communication. - In these variables we keep track of the used variables. If the - platform does not support any real-time signals we will define the - values to some unreasonable value which will signal failing of all - the functions below. */ -#ifndef __NR_rt_sigaction -static int current_rtmin = -1; -static int current_rtmax = -1; -int __pthread_sig_restart = SIGUSR1; -int __pthread_sig_cancel = SIGUSR2; -int __pthread_sig_debug; -#else - -#if __SIGRTMAX - __SIGRTMIN >= 3 -static int current_rtmin = __SIGRTMIN + 3; -static int current_rtmax = __SIGRTMAX; -int __pthread_sig_restart = __SIGRTMIN; -int __pthread_sig_cancel = __SIGRTMIN + 1; -int __pthread_sig_debug = __SIGRTMIN + 2; -void (*__pthread_restart)(pthread_descr) = __pthread_restart_new; -void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal; -int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_new; -#else -static int current_rtmin = __SIGRTMIN; -static int current_rtmax = __SIGRTMAX; -int __pthread_sig_restart = SIGUSR1; -int __pthread_sig_cancel = SIGUSR2; -int __pthread_sig_debug; -void (*__pthread_restart)(pthread_descr) = __pthread_restart_old; -void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old; -int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old; - -#endif - -/* Return number of available real-time signal with highest priority. */ -int __libc_current_sigrtmin (void) -{ - return current_rtmin; -} - -/* Return number of available real-time signal with lowest priority. */ -int __libc_current_sigrtmax (void) -{ - return current_rtmax; -} - -#if 0 -/* Allocate real-time signal with highest/lowest available - priority. Please note that we don't use a lock since we assume - this function to be called at program start. */ -int __libc_allocate_rtsig (int high); -int __libc_allocate_rtsig (int high) -{ - if (current_rtmin == -1 || current_rtmin > current_rtmax) - /* We don't have anymore signal available. */ - return -1; - return high ? current_rtmin++ : current_rtmax--; -} -#endif -#endif - -/* Initialize the pthread library. - Initialization is split in two functions: - - a constructor function that blocks the __pthread_sig_restart signal - (must do this very early, since the program could capture the signal - mask with e.g. sigsetjmp before creating the first thread); - - a regular function called from pthread_create when needed. */ - -static void pthread_initialize(void) __attribute__((constructor)); - -libpthread_hidden_proto(pthread_attr_destroy) -libpthread_hidden_proto(pthread_attr_init) -libpthread_hidden_proto(pthread_attr_getdetachstate) -libpthread_hidden_proto(pthread_attr_setdetachstate) -libpthread_hidden_proto(pthread_attr_getinheritsched) -libpthread_hidden_proto(pthread_attr_setinheritsched) -libpthread_hidden_proto(pthread_attr_setschedparam) -libpthread_hidden_proto(pthread_attr_getschedparam) -libpthread_hidden_proto(pthread_attr_getschedpolicy) -libpthread_hidden_proto(pthread_attr_setschedpolicy) -libpthread_hidden_proto(pthread_attr_getscope) -libpthread_hidden_proto(pthread_attr_setscope) - -libpthread_hidden_proto(pthread_exit) - -libpthread_hidden_proto(pthread_equal) -libpthread_hidden_proto(pthread_self) -libpthread_hidden_proto(pthread_getschedparam) -libpthread_hidden_proto(pthread_setschedparam) - -libpthread_hidden_proto(pthread_setcancelstate) -libpthread_hidden_proto(pthread_setcanceltype) -libpthread_hidden_proto(_pthread_cleanup_push_defer) -libpthread_hidden_proto(_pthread_cleanup_pop_restore) - -libpthread_hidden_proto(pthread_cond_broadcast) -libpthread_hidden_proto(pthread_cond_destroy) -libpthread_hidden_proto(pthread_cond_init) -libpthread_hidden_proto(pthread_cond_signal) -libpthread_hidden_proto(pthread_cond_wait) -libpthread_hidden_proto(pthread_cond_timedwait) - -libpthread_hidden_proto(pthread_condattr_destroy) -libpthread_hidden_proto(pthread_condattr_init) - -struct pthread_functions __pthread_functions = - { -#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_RPC__ - .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set, - .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get, - .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address, -#endif -/* - .ptr_pthread_fork = __pthread_fork, -*/ - .ptr_pthread_attr_destroy = pthread_attr_destroy, - .ptr_pthread_attr_init = pthread_attr_init, - .ptr_pthread_attr_getdetachstate = pthread_attr_getdetachstate, - .ptr_pthread_attr_setdetachstate = pthread_attr_setdetachstate, - .ptr_pthread_attr_getinheritsched = pthread_attr_getinheritsched, - .ptr_pthread_attr_setinheritsched = pthread_attr_setinheritsched, - .ptr_pthread_attr_getschedparam = pthread_attr_getschedparam, - .ptr_pthread_attr_setschedparam = pthread_attr_setschedparam, - .ptr_pthread_attr_getschedpolicy = pthread_attr_getschedpolicy, - .ptr_pthread_attr_setschedpolicy = pthread_attr_setschedpolicy, - .ptr_pthread_attr_getscope = pthread_attr_getscope, - .ptr_pthread_attr_setscope = pthread_attr_setscope, - .ptr_pthread_condattr_destroy = pthread_condattr_destroy, - .ptr_pthread_condattr_init = pthread_condattr_init, - .ptr_pthread_cond_broadcast = pthread_cond_broadcast, - .ptr_pthread_cond_destroy = pthread_cond_destroy, - .ptr_pthread_cond_init = pthread_cond_init, - .ptr_pthread_cond_signal = pthread_cond_signal, - .ptr_pthread_cond_wait = pthread_cond_wait, - .ptr_pthread_cond_timedwait = pthread_cond_timedwait, - .ptr_pthread_equal = pthread_equal, - .ptr___pthread_exit = pthread_exit, - .ptr_pthread_getschedparam = pthread_getschedparam, - .ptr_pthread_setschedparam = pthread_setschedparam, - .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, - .ptr_pthread_mutex_init = __pthread_mutex_init, - .ptr_pthread_mutex_lock = __pthread_mutex_lock, - .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, - .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, - .ptr_pthread_self = pthread_self, - .ptr_pthread_setcancelstate = pthread_setcancelstate, - .ptr_pthread_setcanceltype = pthread_setcanceltype, -/* - .ptr_pthread_do_exit = pthread_do_exit, - .ptr_pthread_thread_self = pthread_thread_self, - .ptr_pthread_cleanup_upto = pthread_cleanup_upto, - .ptr_pthread_sigaction = pthread_sigaction, - .ptr_pthread_sigwait = pthread_sigwait, - .ptr_pthread_raise = pthread_raise, - .ptr__pthread_cleanup_push = _pthread_cleanup_push, - .ptr__pthread_cleanup_pop = _pthread_cleanup_pop, -*/ - .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer, - .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore - }; -#ifdef SHARED -# define ptr_pthread_functions &__pthread_functions -#else -# define ptr_pthread_functions NULL -#endif - -static int *__libc_multiple_threads_ptr; - - /* Do some minimal initialization which has to be done during the - startup of the C library. */ -void __pthread_initialize_minimal(void) -{ - /* If we have special thread_self processing, initialize - * that for the main thread now. */ -#ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(&__pthread_initial_thread, 0); -#endif - - __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); -} - - -static void pthread_initialize(void) -{ - struct sigaction sa; - sigset_t mask; -#ifdef __ARCH_USE_MMU__ - struct rlimit limit; - rlim_t max_stack; -#endif - - /* If already done (e.g. by a constructor called earlier!), bail out */ - if (__pthread_initial_thread_bos != NULL) return; -#ifdef TEST_FOR_COMPARE_AND_SWAP - /* Test if compare-and-swap is available */ - __pthread_has_cas = compare_and_swap_is_available(); -#endif - /* For the initial stack, reserve at least STACK_SIZE bytes of stack - below the current stack address, and align that on a - STACK_SIZE boundary. */ - __pthread_initial_thread_bos = - (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); - /* Update the descriptor for the initial thread. */ - __pthread_initial_thread.p_pid = getpid(); - /* If we have special thread_self processing, initialize that for the - main thread now. */ -#ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(&__pthread_initial_thread, 0); -#endif - /* The errno/h_errno variable of the main thread are the global ones. */ - __pthread_initial_thread.p_errnop = &_errno; - __pthread_initial_thread.p_h_errnop = &_h_errno; - -#ifdef __UCLIBC_HAS_XLOCALE__ - /* The locale of the main thread is the current locale in use. */ - __pthread_initial_thread.locale = __curlocale_var; -#endif /* __UCLIBC_HAS_XLOCALE__ */ - - { /* uClibc-specific stdio initialization for threads. */ - FILE *fp; - - _stdio_user_locking = 0; /* 2 if threading not initialized */ - for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { - if (fp->__user_locking != 1) { - fp->__user_locking = 0; - } - } - } - - /* Play with the stack size limit to make sure that no stack ever grows - beyond STACK_SIZE minus two pages (one page for the thread descriptor - immediately beyond, and one page to act as a guard page). */ - -#ifdef __ARCH_USE_MMU__ - /* We cannot allocate a huge chunk of memory to mmap all thread stacks later - * on a non-MMU system. Thus, we don't need the rlimit either. -StS */ - getrlimit(RLIMIT_STACK, &limit); - max_stack = STACK_SIZE - 2 * getpagesize(); - if (limit.rlim_cur > max_stack) { - limit.rlim_cur = max_stack; - setrlimit(RLIMIT_STACK, &limit); - } -#else - /* For non-MMU, the initial thread stack can reside anywhere in memory. - * We don't have a way of knowing where the kernel started things -- top - * or bottom (well, that isn't exactly true, but the solution is fairly - * complex and error prone). All we can determine here is an address - * that lies within that stack. Save that address as a reference so that - * as other thread stacks are created, we can adjust the estimated bounds - * of the initial thread's stack appropriately. - * - * This checking is handled in NOMMU_INITIAL_THREAD_BOUNDS(), so see that - * for a few more details. - */ - __pthread_initial_thread_mid = CURRENT_STACK_FRAME; - __pthread_initial_thread_tos = (char *) -1; - __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */ - PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n", - __pthread_initial_thread_bos, __pthread_initial_thread_tos); -#endif /* __ARCH_USE_MMU__ */ - - /* Setup signal handlers for the initial thread. - Since signal handlers are shared between threads, these settings - will be inherited by all other threads. */ - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = pthread_handle_sigrestart; - __libc_sigaction(__pthread_sig_restart, &sa, NULL); - sa.sa_handler = pthread_handle_sigcancel; - sigaddset(&sa.sa_mask, __pthread_sig_restart); - __libc_sigaction(__pthread_sig_cancel, &sa, NULL); - if (__pthread_sig_debug > 0) { - sa.sa_handler = pthread_handle_sigdebug; - __sigemptyset(&sa.sa_mask); - __libc_sigaction(__pthread_sig_debug, &sa, NULL); - } - /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */ - __sigemptyset(&mask); - sigaddset(&mask, __pthread_sig_restart); - sigprocmask(SIG_BLOCK, &mask, NULL); - /* And unblock __pthread_sig_cancel if it has been blocked. */ - sigdelset(&mask, __pthread_sig_restart); - sigaddset(&mask, __pthread_sig_cancel); - sigprocmask(SIG_UNBLOCK, &mask, NULL); - /* Register an exit function to kill all other threads. */ - /* Do it early so that user-registered atexit functions are called - before pthread_onexit_process. */ - on_exit(pthread_onexit_process, NULL); -} - -void __pthread_initialize(void); -void __pthread_initialize(void) -{ - pthread_initialize(); -} - -int __pthread_initialize_manager(void) -{ - int manager_pipe[2]; - int pid; - int report_events; - struct pthread_request request; - - *__libc_multiple_threads_ptr = 1; - - /* If basic initialization not done yet (e.g. we're called from a - constructor run before our constructor), do it now */ - if (__pthread_initial_thread_bos == NULL) pthread_initialize(); - /* Setup stack for thread manager */ - __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); - if (__pthread_manager_thread_bos == NULL) return -1; - __pthread_manager_thread_tos = - __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; - - /* On non-MMU systems we make sure that the initial thread bounds don't overlap - * with the manager stack frame */ - NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos); - PDEBUG("manager stack: size=%ld, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE, - __pthread_manager_thread_bos, __pthread_manager_thread_tos); -#if 0 - PDEBUG("initial stack: estimate bos=%p, tos=%p\n", - __pthread_initial_thread_bos, __pthread_initial_thread_tos); -#endif - - /* Setup pipe to communicate with thread manager */ - if (pipe(manager_pipe) == -1) { - free(__pthread_manager_thread_bos); - return -1; - } - /* Start the thread manager */ - pid = 0; -#if defined(USE_TLS) && USE_TLS - if (__linuxthreads_initial_report_events != 0) - THREAD_SETMEM (((pthread_descr) NULL), p_report_events, - __linuxthreads_initial_report_events); - report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events); -#else - if (__linuxthreads_initial_report_events != 0) - __pthread_initial_thread.p_report_events - = __linuxthreads_initial_report_events; - report_events = __pthread_initial_thread.p_report_events; -#endif - if (__builtin_expect (report_events, 0)) - { - /* It's a bit more complicated. We have to report the creation of - the manager thread. */ - int idx = __td_eventword (TD_CREATE); - uint32_t mask = __td_eventmask (TD_CREATE); - - if ((mask & (__pthread_threads_events.event_bits[idx] - | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx])) - != 0) - { - - __pthread_lock(__pthread_manager_thread.p_lock, NULL); - -#ifdef __ia64__ - pid = __clone2(__pthread_manager_event, - (void **) __pthread_manager_thread_tos, - THREAD_MANAGER_STACK_SIZE, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - (void *)(long)manager_pipe[0]); -#else - pid = clone(__pthread_manager_event, - (void **) __pthread_manager_thread_tos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - (void *)(long)manager_pipe[0]); -#endif - - if (pid != -1) - { - /* Now fill in the information about the new thread in - the newly created thread's data structure. We cannot let - the new thread do this since we don't know whether it was - already scheduled when we send the event. */ - __pthread_manager_thread.p_eventbuf.eventdata = - &__pthread_manager_thread; - __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE; - __pthread_last_event = &__pthread_manager_thread; - __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; - __pthread_manager_thread.p_pid = pid; - - /* Now call the function which signals the event. */ - __linuxthreads_create_event (); - } - /* Now restart the thread. */ - __pthread_unlock(__pthread_manager_thread.p_lock); - } - } - - if (pid == 0) { -#ifdef __ia64__ - pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_tos, - THREAD_MANAGER_STACK_SIZE, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - (void *)(long)manager_pipe[0]); -#else - pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos, - CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, - (void *)(long)manager_pipe[0]); -#endif - } - if (pid == -1) { - free(__pthread_manager_thread_bos); - close(manager_pipe[0]); - close(manager_pipe[1]); - return -1; - } - __pthread_manager_request = manager_pipe[1]; /* writing end */ - __pthread_manager_reader = manager_pipe[0]; /* reading end */ - __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; - __pthread_manager_thread.p_pid = pid; - - /* Make gdb aware of new thread manager */ - if (__pthread_threads_debug && __pthread_sig_debug > 0) - { - raise(__pthread_sig_debug); - /* We suspend ourself and gdb will wake us up when it is - ready to handle us. */ - __pthread_wait_for_restart_signal(thread_self()); - } - /* Synchronize debugging of the thread manager */ - PDEBUG("send REQ_DEBUG to manager thread\n"); - request.req_kind = REQ_DEBUG; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - return 0; -} - -/* Thread creation */ - -int pthread_create(pthread_t *thread, const pthread_attr_t *attr, - void * (*start_routine)(void *), void *arg) -{ - pthread_descr self = thread_self(); - struct pthread_request request; - if (__pthread_manager_request < 0) { - if (__pthread_initialize_manager() < 0) return EAGAIN; - } - request.req_thread = self; - request.req_kind = REQ_CREATE; - request.req_args.create.attr = attr; - request.req_args.create.fn = start_routine; - request.req_args.create.arg = arg; - sigprocmask(SIG_SETMASK, NULL, &request.req_args.create.mask); - PDEBUG("write REQ_CREATE to manager thread\n"); - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - PDEBUG("before suspend(self)\n"); - suspend(self); - PDEBUG("after suspend(self)\n"); - if (THREAD_GETMEM(self, p_retcode) == 0) - *thread = (pthread_t) THREAD_GETMEM(self, p_retval); - return THREAD_GETMEM(self, p_retcode); -} - -/* Simple operations on thread identifiers */ - -pthread_t pthread_self(void) -{ - pthread_descr self = thread_self(); - return THREAD_GETMEM(self, p_tid); -} -libpthread_hidden_def (pthread_self) - -int pthread_equal(pthread_t thread1, pthread_t thread2) -{ - return thread1 == thread2; -} -libpthread_hidden_def (pthread_equal) - -/* Helper function for thread_self in the case of user-provided stacks */ - -#ifndef THREAD_SELF - -pthread_descr __pthread_find_self(void) -{ - char * sp = CURRENT_STACK_FRAME; - pthread_handle h; - - /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is - the manager threads handled specially in thread_self(), so start at 2 */ - h = __pthread_handles + 2; - while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++; - -#ifdef DEBUG_PT - if (h->h_descr == NULL) { - printf("*** %s ERROR descriptor is NULL!!!!! ***\n\n", __FUNCTION__); - _exit(1); - } -#endif - - return h->h_descr; -} -#else - -static pthread_descr thread_self_stack(void) -{ - char *sp = CURRENT_STACK_FRAME; - pthread_handle h; - - if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) - return manager_thread; - h = __pthread_handles + 2; -# if defined(USE_TLS) && USE_TLS - while (h->h_descr == NULL - || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom)) - h++; -# else - while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) - h++; -# endif - return h->h_descr; -} - -#endif - -/* Thread scheduling */ - -int pthread_setschedparam(pthread_t thread, int policy, - const struct sched_param *param) -{ - pthread_handle handle = thread_handle(thread); - pthread_descr th; - - __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, thread)) { - __pthread_unlock(&handle->h_lock); - return ESRCH; - } - th = handle->h_descr; - if (sched_setscheduler(th->p_pid, policy, param) == -1) { - __pthread_unlock(&handle->h_lock); - return errno; - } - th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority; - __pthread_unlock(&handle->h_lock); - if (__pthread_manager_request >= 0) - __pthread_manager_adjust_prio(th->p_priority); - return 0; -} -libpthread_hidden_def(pthread_setschedparam) - -int pthread_getschedparam(pthread_t thread, int *policy, - struct sched_param *param) -{ - pthread_handle handle = thread_handle(thread); - int pid, pol; - - __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, thread)) { - __pthread_unlock(&handle->h_lock); - return ESRCH; - } - pid = handle->h_descr->p_pid; - __pthread_unlock(&handle->h_lock); - pol = sched_getscheduler(pid); - if (pol == -1) return errno; - if (sched_getparam(pid, param) == -1) return errno; - *policy = pol; - return 0; -} -libpthread_hidden_def(pthread_getschedparam) - -/* Process-wide exit() request */ - -static void pthread_onexit_process(int retcode, void *arg attribute_unused) -{ - struct pthread_request request; - pthread_descr self = thread_self(); - - if (__pthread_manager_request >= 0) { - request.req_thread = self; - request.req_kind = REQ_PROCESS_EXIT; - request.req_args.exit.code = retcode; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - suspend(self); - /* Main thread should accumulate times for thread manager and its - children, so that timings for main thread account for all threads. */ - if (self == __pthread_main_thread) { - waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); - /* Since all threads have been asynchronously terminated - * (possibly holding locks), free cannot be used any more. */ - __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; - } - } -} - -/* The handler for the RESTART signal just records the signal received - in the thread descriptor, and optionally performs a siglongjmp - (for pthread_cond_timedwait). */ - -static void pthread_handle_sigrestart(int sig) -{ - pthread_descr self = thread_self(); - THREAD_SETMEM(self, p_signal, sig); - if (THREAD_GETMEM(self, p_signal_jmp) != NULL) - siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); -} - -/* The handler for the CANCEL signal checks for cancellation - (in asynchronous mode), for process-wide exit and exec requests. - For the thread manager thread, redirect the signal to - __pthread_manager_sighandler. */ - -static void pthread_handle_sigcancel(int sig) -{ - pthread_descr self = thread_self(); - sigjmp_buf * jmpbuf; - - - if (self == &__pthread_manager_thread) - { -#ifdef THREAD_SELF - /* A new thread might get a cancel signal before it is fully - initialized, so that the thread register might still point to the - manager thread. Double check that this is really the manager - thread. */ - pthread_descr real_self = thread_self_stack(); - if (real_self == &__pthread_manager_thread) - { - __pthread_manager_sighandler(sig); - return; - } - /* Oops, thread_self() isn't working yet.. */ - self = real_self; -# ifdef INIT_THREAD_SELF - INIT_THREAD_SELF(self, self->p_nr); -# endif -#else - __pthread_manager_sighandler(sig); - return; -#endif - } - if (__builtin_expect (__pthread_exit_requested, 0)) { - /* Main thread should accumulate times for thread manager and its - children, so that timings for main thread account for all threads. */ - if (self == __pthread_main_thread) { -#if defined(USE_TLS) && USE_TLS - waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE); -#else - waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); -#endif - } - _exit(__pthread_exit_code); - } - if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { - if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); - if (jmpbuf != NULL) { - THREAD_SETMEM(self, p_cancel_jmp, NULL); - siglongjmp(*jmpbuf, 1); - } - } -} - -/* Handler for the DEBUG signal. - The debugging strategy is as follows: - On reception of a REQ_DEBUG request (sent by new threads created to - the thread manager under debugging mode), the thread manager throws - __pthread_sig_debug to itself. The debugger (if active) intercepts - this signal, takes into account new threads and continue execution - of the thread manager by propagating the signal because it doesn't - know what it is specifically done for. In the current implementation, - the thread manager simply discards it. */ - -static void pthread_handle_sigdebug(int sig attribute_unused) -{ - /* Nothing */ -} - -/* Reset the state of the thread machinery after a fork(). - Close the pipe used for requests and set the main thread to the forked - thread. - Notice that we can't free the stack segments, as the forked thread - may hold pointers into them. */ - -void __pthread_reset_main_thread(void) -{ - pthread_descr self = thread_self(); - - if (__pthread_manager_request != -1) { - /* Free the thread manager stack */ - free(__pthread_manager_thread_bos); - __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; - /* Close the two ends of the pipe */ - close(__pthread_manager_request); - close(__pthread_manager_reader); - __pthread_manager_request = __pthread_manager_reader = -1; - } - - /* Update the pid of the main thread */ - THREAD_SETMEM(self, p_pid, getpid()); - /* Make the forked thread the main thread */ - __pthread_main_thread = self; - THREAD_SETMEM(self, p_nextlive, self); - THREAD_SETMEM(self, p_prevlive, self); - /* Now this thread modifies the global variables. */ - THREAD_SETMEM(self, p_errnop, &_errno); - THREAD_SETMEM(self, p_h_errnop, &_h_errno); -} - -/* Process-wide exec() request */ - -void __pthread_kill_other_threads_np(void) -{ - struct sigaction sa; - /* Terminate all other threads and thread manager */ - pthread_onexit_process(0, NULL); - /* Make current thread the main thread in case the calling thread - changes its mind, does not exec(), and creates new threads instead. */ - __pthread_reset_main_thread(); - /* Reset the signal handlers behaviour for the signals the - implementation uses since this would be passed to the new - process. */ - memset(&sa, 0, sizeof(sa)); - if (SIG_DFL) /* if it's constant zero, it's already done */ - sa.sa_handler = SIG_DFL; - __libc_sigaction(__pthread_sig_restart, &sa, NULL); - __libc_sigaction(__pthread_sig_cancel, &sa, NULL); - if (__pthread_sig_debug > 0) - __libc_sigaction(__pthread_sig_debug, &sa, NULL); -} -weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np) - -/* Concurrency symbol level. */ -static int current_level; - -int __pthread_setconcurrency(int level) -{ - /* We don't do anything unless we have found a useful interpretation. */ - current_level = level; - return 0; -} -weak_alias (__pthread_setconcurrency, pthread_setconcurrency) - -int __pthread_getconcurrency(void) -{ - return current_level; -} -weak_alias (__pthread_getconcurrency, pthread_getconcurrency) - - -/* Primitives for controlling thread execution */ - -void __pthread_wait_for_restart_signal(pthread_descr self) -{ - sigset_t mask; - - sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */ - sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */ - THREAD_SETMEM(self, p_signal, 0); - do { - sigsuspend(&mask); /* Wait for signal */ - } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart); - - READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ -} - -#ifndef __NR_rt_sigaction -/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT - signals. - On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation. - Since the restart signal does not queue, we use an atomic counter to create - queuing semantics. This is needed to resolve a rare race condition in - pthread_cond_timedwait_relative. */ - -void __pthread_restart_old(pthread_descr th) -{ - if (atomic_increment(&th->p_resume_count) == -1) - kill(th->p_pid, __pthread_sig_restart); -} - -void __pthread_suspend_old(pthread_descr self) -{ - if (atomic_decrement(&self->p_resume_count) <= 0) - __pthread_wait_for_restart_signal(self); -} - -int -__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) -{ - sigset_t unblock, initial_mask; - int was_signalled = 0; - sigjmp_buf jmpbuf; - - 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 now. */ - gettimeofday (&now, NULL); - reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; - reltime.tv_sec = abstime->tv_sec - now.tv_sec; - if (reltime.tv_nsec < 0) { - reltime.tv_nsec += 1000000000; - reltime.tv_sec -= 1; - } - - /* Sleep for the required duration. If woken by a signal, - resume waiting as required by Single Unix Specification. */ - if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) - break; - } - - /* Block the restart signal again */ - sigprocmask(SIG_SETMASK, &initial_mask, NULL); - was_signalled = 0; - } else { - was_signalled = 1; - } - THREAD_SETMEM(self, p_signal_jmp, NULL); - } - - /* Now was_signalled is true if we exited the above code - due to the delivery of a restart signal. In that case, - we know we have been dequeued and resumed and that the - resume count is balanced. Otherwise, there are some - cases to consider. First, try to bump up the resume count - back to zero. If it goes to 1, it means restart() was - invoked on this thread. The signal must be consumed - and the count bumped down and everything is cool. We - can return a 1 to the caller. - Otherwise, no restart was delivered yet, so a potential - race exists; we return a 0 to the caller which must deal - with this race in an appropriate way; for example by - atomically removing the thread from consideration for a - wakeup---if such a thing fails, it means a restart is - being delivered. */ - - if (!was_signalled) { - if (atomic_increment(&self->p_resume_count) != -1) { - __pthread_wait_for_restart_signal(self); - atomic_decrement(&self->p_resume_count); /* should be zero now! */ - /* woke spontaneously and consumed restart signal */ - return 1; - } - /* woke spontaneously but did not consume restart---caller must resolve */ - return 0; - } - /* woken due to restart signal */ - return 1; -} -#endif /* __NR_rt_sigaction */ - - -#ifdef __NR_rt_sigaction -void __pthread_restart_new(pthread_descr th) -{ - /* The barrier is proabably not needed, in which case it still documents - our assumptions. The intent is to commit previous writes to shared - memory so the woken thread will have a consistent view. Complementary - read barriers are present to the suspend functions. */ - WRITE_MEMORY_BARRIER(); - kill(th->p_pid, __pthread_sig_restart); -} - -int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) -{ - sigset_t unblock, initial_mask; - int was_signalled = 0; - sigjmp_buf jmpbuf; - - 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 now. */ - gettimeofday (&now, NULL); - reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; - reltime.tv_sec = abstime->tv_sec - now.tv_sec; - if (reltime.tv_nsec < 0) { - reltime.tv_nsec += 1000000000; - reltime.tv_sec -= 1; - } - - /* Sleep for the required duration. If woken by a signal, - resume waiting as required by Single Unix Specification. */ - if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) - break; - } - - /* Block the restart signal again */ - sigprocmask(SIG_SETMASK, &initial_mask, NULL); - was_signalled = 0; - } else { - was_signalled = 1; - } - THREAD_SETMEM(self, p_signal_jmp, NULL); - - /* Now was_signalled is true if we exited the above code - due to the delivery of a restart signal. In that case, - everything is cool. We have been removed from whatever - we were waiting on by the other thread, and consumed its signal. - - Otherwise we this thread woke up spontaneously, or due to a signal other - than restart. This is an ambiguous case that must be resolved by - the caller; the thread is still eligible for a restart wakeup - so there is a race. */ - - READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ - return was_signalled; -} -#endif - -/* Debugging aid */ - -#ifdef DEBUG_PT -#include <stdarg.h> - -void __pthread_message(char * fmt, ...) -{ - char buffer[1024]; - va_list args; - sprintf(buffer, "%05d : ", getpid()); - va_start(args, fmt); - vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args); - va_end(args); - TEMP_FAILURE_RETRY(write(2, buffer, strlen(buffer))); -} - -#endif - - -#ifndef __PIC__ -/* We need a hook to force the cancellation wrappers to be linked in when - static libpthread is used. */ -extern const char __pthread_provide_wrappers; -static const char *const __pthread_require_wrappers = - &__pthread_provide_wrappers; -#endif diff --git a/libpthread/linuxthreads.old/ptlongjmp.c b/libpthread/linuxthreads.old/ptlongjmp.c deleted file mode 100644 index 5cb708944..000000000 --- a/libpthread/linuxthreads.old/ptlongjmp.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Redefine siglongjmp and longjmp so that they interact correctly - with cleanup handlers */ - -#include <setjmp.h> -#include "pthread.h" -#include "internals.h" -#include <bits/stackinfo.h> -#include <jmpbuf-unwind.h> - -static void pthread_cleanup_upto(__jmp_buf target) -{ - pthread_descr self = thread_self(); - struct _pthread_cleanup_buffer * c; - char *currentframe = CURRENT_STACK_FRAME; - - for (c = THREAD_GETMEM(self, p_cleanup); - c != NULL && _JMPBUF_UNWINDS(target, c); - c = c->__prev) - { -#ifdef _STACK_GROWS_DOWN - if ((char *) c <= currentframe) - { - c = NULL; - break; - } -#elif defined _STACK_GROWS_UP - if ((char *) c >= currentframe) - { - c = NULL; - break; - } -#else -# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" -#endif - c->__routine(c->__arg); - } - THREAD_SETMEM(self, p_cleanup, c); - if (THREAD_GETMEM(self, p_in_sighandler) - && _JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler))) - THREAD_SETMEM(self, p_in_sighandler, NULL); -} - -void siglongjmp(sigjmp_buf env, int val) -{ - pthread_cleanup_upto(env->__jmpbuf); - __libc_siglongjmp(env, val); -} - -void longjmp(jmp_buf env, int val) -{ - pthread_cleanup_upto(env->__jmpbuf); - __libc_longjmp(env, val); -} diff --git a/libpthread/linuxthreads.old/queue.h b/libpthread/linuxthreads.old/queue.h deleted file mode 100644 index 01d18d16e..000000000 --- a/libpthread/linuxthreads.old/queue.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Waiting queues */ - -/* Waiting queues are represented by lists of thread descriptors - linked through their p_nextwaiting field. The lists are kept - sorted by decreasing priority, and then decreasing waiting time. */ - -static __inline__ void enqueue(pthread_descr * q, pthread_descr th) -{ - int prio = th->p_priority; - for (; *q != NULL; q = &((*q)->p_nextwaiting)) { - if (prio > (*q)->p_priority) { - th->p_nextwaiting = *q; - *q = th; - return; - } - } - *q = th; -} - -static __inline__ pthread_descr dequeue(pthread_descr * q) -{ - pthread_descr th; - th = *q; - if (th != NULL) { - *q = th->p_nextwaiting; - th->p_nextwaiting = NULL; - } - return th; -} - -static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th) -{ - for (; *q != NULL; q = &((*q)->p_nextwaiting)) { - if (*q == th) { - *q = th->p_nextwaiting; - th->p_nextwaiting = NULL; - return 1; - } - } - return 0; -} - -static __inline__ int queue_is_empty(pthread_descr * q) -{ - return *q == NULL; -} diff --git a/libpthread/linuxthreads.old/restart.h b/libpthread/linuxthreads.old/restart.h deleted file mode 100644 index 7d63a7022..000000000 --- a/libpthread/linuxthreads.old/restart.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -#include <signal.h> -#include <sys/syscall.h> -#define __ASSUME_REALTIME_SIGNALS defined(__NR_rt_sigaction) - -/* Primitives for controlling thread execution */ - -static __inline__ void restart(pthread_descr th) -{ - /* See pthread.c */ -#if __ASSUME_REALTIME_SIGNALS - __pthread_restart_new(th); -#else - __pthread_restart(th); -#endif -} - -static __inline__ void suspend(pthread_descr self) -{ - /* See pthread.c */ -#if __ASSUME_REALTIME_SIGNALS - __pthread_wait_for_restart_signal(self); -#else - __pthread_suspend(self); -#endif -} - -static __inline__ int timedsuspend(pthread_descr self, - const struct timespec *abstime) -{ - /* See pthread.c */ -#if __ASSUME_REALTIME_SIGNALS - return __pthread_timedsuspend_new(self, abstime); -#else - return __pthread_timedsuspend(self, abstime); -#endif -} diff --git a/libpthread/linuxthreads.old/rwlock.c b/libpthread/linuxthreads.old/rwlock.c deleted file mode 100644 index 3ab940261..000000000 --- a/libpthread/linuxthreads.old/rwlock.c +++ /dev/null @@ -1,485 +0,0 @@ -/* Read-write lock implementation. - Copyright (C) 1998 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Xavier Leroy <Xavier.Leroy@inria.fr> - and Ulrich Drepper <drepper@cygnus.com>, 1998. - - 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, - see <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <pthread.h> -#include <stdlib.h> -#include "internals.h" -#include "queue.h" -#include "spinlock.h" -#include "restart.h" - -/* - * Check whether the calling thread already owns one or more read locks on the - * specified lock. If so, return a pointer to the read lock info structure - * corresponding to that lock. - */ - -static pthread_readlock_info * -rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock) -{ - pthread_readlock_info *info; - - for (info = self->p_readlock_list; info != NULL; info = info->pr_next) - { - if (info->pr_lock == rwlock) - return info; - } - - return NULL; -} - -/* - * Add a new lock to the thread's list of locks for which it has a read lock. - * A new info node must be allocated for this, which is taken from the thread's - * free list, or by calling malloc. If malloc fails, a null pointer is - * returned. Otherwise the lock info structure is initialized and pushed - * onto the thread's list. - */ - -static pthread_readlock_info * -rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock) -{ - pthread_readlock_info *info = self->p_readlock_free; - - if (info != NULL) - self->p_readlock_free = info->pr_next; - else - info = malloc(sizeof *info); - - if (info == NULL) - return NULL; - - info->pr_lock_count = 1; - info->pr_lock = rwlock; - info->pr_next = self->p_readlock_list; - self->p_readlock_list = info; - - return info; -} - -/* - * If the thread owns a read lock over the given pthread_rwlock_t, - * and this read lock is tracked in the thread's lock list, - * this function returns a pointer to the info node in that list. - * It also decrements the lock count within that node, and if - * it reaches zero, it removes the node from the list. - * If nothing is found, it returns a null pointer. - */ - -static pthread_readlock_info * -rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock) -{ - pthread_readlock_info **pinfo; - - for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next) - { - if ((*pinfo)->pr_lock == rwlock) - { - pthread_readlock_info *info = *pinfo; - if (--info->pr_lock_count == 0) - *pinfo = info->pr_next; - return info; - } - } - - return NULL; -} - -/* - * This function checks whether the conditions are right to place a read lock. - * It returns 1 if so, otherwise zero. The rwlock's internal lock must be - * locked upon entry. - */ - -static int -rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already) -{ - /* Can't readlock; it is write locked. */ - if (rwlock->__rw_writer != NULL) - return 0; - - /* Lock prefers readers; get it. */ - if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP) - return 1; - - /* Lock prefers writers, but none are waiting. */ - if (queue_is_empty(&rwlock->__rw_write_waiting)) - return 1; - - /* Writers are waiting, but this thread already has a read lock */ - if (have_lock_already) - return 1; - - /* Writers are waiting, and this is a new lock */ - return 0; -} - -/* - * This function helps support brain-damaged recursive read locking - * semantics required by Unix 98, while maintaining write priority. - * This basically determines whether this thread already holds a read lock - * already. It returns 1 if so, otherwise it returns 0. - * - * If the thread has any ``untracked read locks'' then it just assumes - * that this lock is among them, just to be safe, and returns 1. - * - * Also, if it finds the thread's lock in the list, it sets the pointer - * referenced by pexisting to refer to the list entry. - * - * If the thread has no untracked locks, and the lock is not found - * in its list, then it is added to the list. If this fails, - * then *pout_of_mem is set to 1. - */ - -static int -rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, - pthread_readlock_info **pexisting, int *pout_of_mem) -{ - pthread_readlock_info *existing = NULL; - int out_of_mem = 0, have_lock_already = 0; - pthread_descr self = *pself; - - if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) - { - if (!self) - self = thread_self(); - - existing = rwlock_is_in_list(self, rwlock); - - if (existing != NULL || self->p_untracked_readlock_count > 0) - have_lock_already = 1; - else - { - existing = rwlock_add_to_list(self, rwlock); - if (existing == NULL) - out_of_mem = 1; - } - } - - *pout_of_mem = out_of_mem; - *pexisting = existing; - *pself = self; - - return have_lock_already; -} - -int -pthread_rwlock_init (pthread_rwlock_t *rwlock, - const pthread_rwlockattr_t *attr) -{ - __pthread_init_lock(&rwlock->__rw_lock); - rwlock->__rw_readers = 0; - rwlock->__rw_writer = NULL; - rwlock->__rw_read_waiting = NULL; - rwlock->__rw_write_waiting = NULL; - - if (attr == NULL) - { - rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP; - rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE; - } - else - { - rwlock->__rw_kind = attr->__lockkind; - rwlock->__rw_pshared = attr->__pshared; - } - - return 0; -} - - -int -pthread_rwlock_destroy (pthread_rwlock_t *rwlock) -{ - int readers; - _pthread_descr writer; - - __pthread_lock (&rwlock->__rw_lock, NULL); - readers = rwlock->__rw_readers; - writer = rwlock->__rw_writer; - __pthread_unlock (&rwlock->__rw_lock); - - if (readers > 0 || writer != NULL) - return EBUSY; - - return 0; -} - -int -pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) -{ - pthread_descr self = NULL; - pthread_readlock_info *existing; - int out_of_mem, have_lock_already; - - have_lock_already = rwlock_have_already(&self, rwlock, - &existing, &out_of_mem); - - for (;;) - { - if (self == NULL) - self = thread_self (); - - __pthread_lock (&rwlock->__rw_lock, self); - - if (rwlock_can_rdlock(rwlock, have_lock_already)) - break; - - enqueue (&rwlock->__rw_read_waiting, self); - __pthread_unlock (&rwlock->__rw_lock); - suspend (self); /* This is not a cancellation point */ - } - - ++rwlock->__rw_readers; - __pthread_unlock (&rwlock->__rw_lock); - - if (have_lock_already || out_of_mem) - { - if (existing != NULL) - existing->pr_lock_count++; - else - self->p_untracked_readlock_count++; - } - - return 0; -} - -int -pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) -{ - pthread_descr self = thread_self(); - pthread_readlock_info *existing; - int out_of_mem, have_lock_already; - int retval = EBUSY; - - have_lock_already = rwlock_have_already(&self, rwlock, - &existing, &out_of_mem); - - __pthread_lock (&rwlock->__rw_lock, self); - - /* 0 is passed to here instead of have_lock_already. - This is to meet Single Unix Spec requirements: - if writers are waiting, pthread_rwlock_tryrdlock - does not acquire a read lock, even if the caller has - one or more read locks already. */ - - if (rwlock_can_rdlock(rwlock, 0)) - { - ++rwlock->__rw_readers; - retval = 0; - } - - __pthread_unlock (&rwlock->__rw_lock); - - if (retval == 0) - { - if (have_lock_already || out_of_mem) - { - if (existing != NULL) - existing->pr_lock_count++; - else - self->p_untracked_readlock_count++; - } - } - - return retval; -} - - -int -pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) -{ - pthread_descr self = thread_self (); - - while(1) - { - __pthread_lock (&rwlock->__rw_lock, self); - if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) - { - rwlock->__rw_writer = self; - __pthread_unlock (&rwlock->__rw_lock); - return 0; - } - - /* Suspend ourselves, then try again */ - enqueue (&rwlock->__rw_write_waiting, self); - __pthread_unlock (&rwlock->__rw_lock); - suspend (self); /* This is not a cancellation point */ - } -} - - -int -pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) -{ - int result = EBUSY; - - __pthread_lock (&rwlock->__rw_lock, NULL); - if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) - { - rwlock->__rw_writer = thread_self (); - result = 0; - } - __pthread_unlock (&rwlock->__rw_lock); - - return result; -} - - -int -pthread_rwlock_unlock (pthread_rwlock_t *rwlock) -{ - pthread_descr torestart; - pthread_descr th; - - __pthread_lock (&rwlock->__rw_lock, NULL); - if (rwlock->__rw_writer != NULL) - { - /* Unlocking a write lock. */ - if (rwlock->__rw_writer != thread_self ()) - { - __pthread_unlock (&rwlock->__rw_lock); - return EPERM; - } - rwlock->__rw_writer = NULL; - - if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP - || (th = dequeue (&rwlock->__rw_write_waiting)) == NULL) - { - /* Restart all waiting readers. */ - torestart = rwlock->__rw_read_waiting; - rwlock->__rw_read_waiting = NULL; - __pthread_unlock (&rwlock->__rw_lock); - while ((th = dequeue (&torestart)) != NULL) - restart (th); - } - else - { - /* Restart one waiting writer. */ - __pthread_unlock (&rwlock->__rw_lock); - restart (th); - } - } - else - { - /* Unlocking a read lock. */ - if (rwlock->__rw_readers == 0) - { - __pthread_unlock (&rwlock->__rw_lock); - return EPERM; - } - - --rwlock->__rw_readers; - if (rwlock->__rw_readers == 0) - /* Restart one waiting writer, if any. */ - th = dequeue (&rwlock->__rw_write_waiting); - else - th = NULL; - - __pthread_unlock (&rwlock->__rw_lock); - if (th != NULL) - restart (th); - - /* Recursive lock fixup */ - - if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) - { - pthread_descr self = thread_self(); - pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock); - - if (victim != NULL) - { - if (victim->pr_lock_count == 0) - { - victim->pr_next = self->p_readlock_free; - self->p_readlock_free = victim; - } - } - else - { - if (self->p_untracked_readlock_count > 0) - self->p_untracked_readlock_count--; - } - } - } - - return 0; -} - - - -int -pthread_rwlockattr_init (pthread_rwlockattr_t *attr) -{ - attr->__lockkind = 0; - attr->__pshared = 0; - - return 0; -} - - -int -pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr attribute_unused) -{ - return 0; -} - - -int -pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared) -{ - *pshared = attr->__pshared; - return 0; -} - - -int -pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared) -{ - if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) - return EINVAL; - - attr->__pshared = pshared; - - return 0; -} - - -int -pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref) -{ - *pref = attr->__lockkind; - return 0; -} - - -int -pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref) -{ - if (pref != PTHREAD_RWLOCK_PREFER_READER_NP - && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP - && pref != PTHREAD_RWLOCK_DEFAULT_NP) - return EINVAL; - - attr->__lockkind = pref; - - return 0; -} diff --git a/libpthread/linuxthreads.old/semaphore.c b/libpthread/linuxthreads.old/semaphore.c deleted file mode 100644 index 9025dfee6..000000000 --- a/libpthread/linuxthreads.old/semaphore.c +++ /dev/null @@ -1,299 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Semaphores a la POSIX 1003.1b */ - -#include <features.h> -#include <limits.h> -#include <errno.h> -#include "pthread.h" -#include "semaphore.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" -#include "queue.h" - -int sem_init(sem_t *sem, int pshared, unsigned int value) -{ - if (value > SEM_VALUE_MAX) { - errno = EINVAL; - return -1; - } - if (pshared) { - errno = ENOSYS; - return -1; - } - __pthread_init_lock(&sem->__sem_lock); - sem->__sem_value = value; - sem->__sem_waiting = NULL; - return 0; -} - -/* Function called by pthread_cancel to remove the thread from - waiting inside sem_wait. */ - -static int new_sem_extricate_func(void *obj, pthread_descr th) -{ - volatile pthread_descr self = thread_self(); - sem_t *sem = obj; - int did_remove = 0; - - __pthread_lock(&sem->__sem_lock, self); - did_remove = remove_from_queue(&sem->__sem_waiting, th); - __pthread_unlock(&sem->__sem_lock); - - return did_remove; -} - -int sem_wait(sem_t * sem) -{ - volatile pthread_descr self = thread_self(); - pthread_extricate_if extr; - int already_canceled = 0; - int spurious_wakeup_count; - - /* Set up extrication interface */ - extr.pu_object = sem; - extr.pu_extricate_func = new_sem_extricate_func; - - __pthread_lock(&sem->__sem_lock, self); - if (sem->__sem_value > 0) { - sem->__sem_value--; - __pthread_unlock(&sem->__sem_lock); - return 0; - } - /* Register extrication interface */ - THREAD_SETMEM(self, p_sem_avail, 0); - __pthread_set_own_extricate_if(self, &extr); - /* Enqueue only if not already cancelled. */ - if (!(THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) - enqueue(&sem->__sem_waiting, self); - else - already_canceled = 1; - __pthread_unlock(&sem->__sem_lock); - - if (already_canceled) { - __pthread_set_own_extricate_if(self, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - /* Wait for sem_post or cancellation, or fall through if already canceled */ - spurious_wakeup_count = 0; - while (1) - { - suspend(self); - if (THREAD_GETMEM(self, p_sem_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); - - /* Terminate only if the wakeup came from cancellation. */ - /* Otherwise ignore cancellation because we got the semaphore. */ - - if (THREAD_GETMEM(self, p_woken_by_cancel) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { - THREAD_SETMEM(self, p_woken_by_cancel, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - /* We got the semaphore */ - return 0; -} - -int sem_trywait(sem_t * sem) -{ - int retval; - - __pthread_lock(&sem->__sem_lock, NULL); - if (sem->__sem_value == 0) { - errno = EAGAIN; - retval = -1; - } else { - sem->__sem_value--; - retval = 0; - } - __pthread_unlock(&sem->__sem_lock); - return retval; -} - -int sem_post(sem_t * sem) -{ - pthread_descr self = thread_self(); - pthread_descr th; - struct pthread_request request; - - if (THREAD_GETMEM(self, p_in_sighandler) == NULL) { - __pthread_lock(&sem->__sem_lock, self); - if (sem->__sem_waiting == NULL) { - if (sem->__sem_value >= SEM_VALUE_MAX) { - /* Overflow */ - errno = ERANGE; - __pthread_unlock(&sem->__sem_lock); - return -1; - } - sem->__sem_value++; - __pthread_unlock(&sem->__sem_lock); - } else { - th = dequeue(&sem->__sem_waiting); - __pthread_unlock(&sem->__sem_lock); - th->p_sem_avail = 1; - WRITE_MEMORY_BARRIER(); - restart(th); - } - } else { - /* If we're in signal handler, delegate post operation to - the thread manager. */ - if (__pthread_manager_request < 0) { - if (__pthread_initialize_manager() < 0) { - errno = EAGAIN; - return -1; - } - } - request.req_kind = REQ_POST; - request.req_args.post = sem; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); - } - return 0; -} - -int sem_getvalue(sem_t * sem, int * sval) -{ - *sval = sem->__sem_value; - return 0; -} - -int sem_destroy(sem_t * sem) -{ - if (sem->__sem_waiting != NULL) { - __set_errno (EBUSY); - return -1; - } - return 0; -} - -sem_t *sem_open(const char *name attribute_unused, int oflag attribute_unused, ...) -{ - __set_errno (ENOSYS); - return SEM_FAILED; -} - -int sem_close(sem_t *sem attribute_unused) -{ - __set_errno (ENOSYS); - return -1; -} - -int sem_unlink(const char *name attribute_unused) -{ - __set_errno (ENOSYS); - return -1; -} - -int sem_timedwait(sem_t *sem, const struct timespec *abstime) -{ - pthread_descr self = thread_self(); - pthread_extricate_if extr; - int already_canceled = 0; - int spurious_wakeup_count; - - __pthread_lock(&sem->__sem_lock, self); - if (sem->__sem_value > 0) { - --sem->__sem_value; - __pthread_unlock(&sem->__sem_lock); - return 0; - } - - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { - /* The standard requires that if the function would block and the - time value is illegal, the function returns with an error. */ - __pthread_unlock(&sem->__sem_lock); - __set_errno (EINVAL); - return -1; - } - - /* Set up extrication interface */ - extr.pu_object = sem; - extr.pu_extricate_func = new_sem_extricate_func; - - /* Register extrication interface */ - THREAD_SETMEM(self, p_sem_avail, 0); - __pthread_set_own_extricate_if(self, &extr); - /* Enqueue only if not already cancelled. */ - if (!(THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) - enqueue(&sem->__sem_waiting, self); - else - already_canceled = 1; - __pthread_unlock(&sem->__sem_lock); - - if (already_canceled) { - __pthread_set_own_extricate_if(self, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - - spurious_wakeup_count = 0; - while (1) - { - if (timedsuspend(self, abstime) == 0) { - int was_on_queue; - - /* __pthread_lock will queue back any spurious restarts that - may happen to it. */ - - __pthread_lock(&sem->__sem_lock, self); - was_on_queue = remove_from_queue(&sem->__sem_waiting, self); - __pthread_unlock(&sem->__sem_lock); - - if (was_on_queue) { - __pthread_set_own_extricate_if(self, 0); - __set_errno (ETIMEDOUT); - return -1; - } - - /* Eat the outstanding restart() from the signaller */ - suspend(self); - } - - if (THREAD_GETMEM(self, p_sem_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); - - /* Terminate only if the wakeup came from cancellation. */ - /* Otherwise ignore cancellation because we got the semaphore. */ - - if (THREAD_GETMEM(self, p_woken_by_cancel) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { - THREAD_SETMEM(self, p_woken_by_cancel, 0); - __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); - } - /* We got the semaphore */ - return 0; -} diff --git a/libpthread/linuxthreads.old/semaphore.h b/libpthread/linuxthreads.old/semaphore.h deleted file mode 100644 index 9a9b72c9e..000000000 --- a/libpthread/linuxthreads.old/semaphore.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -#ifndef _SEMAPHORE_H -#define _SEMAPHORE_H 1 - -#include <features.h> -#include <sys/types.h> -#include <limits.h> -#ifdef __USE_XOPEN2K -# define __need_timespec -# include <time.h> -#endif - -#ifndef _PTHREAD_DESCR_DEFINED -/* Thread descriptors. Needed for `sem_t' definition. */ -typedef struct _pthread_descr_struct *_pthread_descr; -# define _PTHREAD_DESCR_DEFINED -#endif - -/* System specific semaphore definition. */ -typedef struct -{ - struct _pthread_fastlock __sem_lock; - int __sem_value; - _pthread_descr __sem_waiting; -} sem_t; - - - -/* Value returned if `sem_open' failed. */ -#define SEM_FAILED ((sem_t *) 0) - -/* Maximum value the semaphore can have. */ -#ifndef SEM_VALUE_MAX -#define SEM_VALUE_MAX ((int) ((~0u) >> 1)) -#endif - - -__BEGIN_DECLS - -/* Initialize semaphore object SEM to VALUE. If PSHARED then share it - with other processes. */ -extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; - -/* Free resources associated with semaphore object SEM. */ -extern int sem_destroy (sem_t *__sem) __THROW; - -/* Open a named semaphore NAME with open flags OFLAG. */ -extern sem_t *sem_open (const char *__name, int __oflag, ...) __THROW; - -/* Close descriptor for named semaphore SEM. */ -extern int sem_close (sem_t *__sem) __THROW; - -/* Remove named semaphore NAME. */ -extern int sem_unlink (const char *__name) __THROW; - -/* Wait for SEM being posted. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int sem_wait (sem_t *__sem); - -#ifdef __USE_XOPEN2K -/* Similar to `sem_wait' but wait only until ABSTIME. - - This function is a cancellation point and therefore not marked with - __THROW. */ -extern int sem_timedwait (sem_t *__restrict __sem, - const struct timespec *__restrict __abstime); -#endif - -/* Test whether SEM is posted. */ -extern int sem_trywait (sem_t *__sem) __THROW; - -/* Post SEM. */ -extern int sem_post (sem_t *__sem) __THROW; - -/* Get current value of SEM and store it in *SVAL. */ -extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) - __THROW; - - -__END_DECLS - -#endif /* semaphore.h */ diff --git a/libpthread/linuxthreads.old/signals.c b/libpthread/linuxthreads.old/signals.c deleted file mode 100644 index d8dbc78bd..000000000 --- a/libpthread/linuxthreads.old/signals.c +++ /dev/null @@ -1,246 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Handling of signals */ - -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include <bits/sigcontextinfo.h> - -int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask) -{ - sigset_t mask; - - if (newmask != NULL) { - mask = *newmask; - /* Don't allow __pthread_sig_restart to be unmasked. - Don't allow __pthread_sig_cancel to be masked. */ - switch(how) { - case SIG_SETMASK: - sigaddset(&mask, __pthread_sig_restart); - sigdelset(&mask, __pthread_sig_cancel); - if (__pthread_sig_debug > 0) - sigdelset(&mask, __pthread_sig_debug); - break; - case SIG_BLOCK: - sigdelset(&mask, __pthread_sig_cancel); - if (__pthread_sig_debug > 0) - sigdelset(&mask, __pthread_sig_debug); - break; - case SIG_UNBLOCK: - sigdelset(&mask, __pthread_sig_restart); - break; - } - newmask = &mask; - } - if (sigprocmask(how, newmask, oldmask) == -1) - return errno; - else - return 0; -} - -int pthread_kill(pthread_t thread, int signo) -{ - pthread_handle handle = thread_handle(thread); - int pid; - - __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, thread)) { - __pthread_unlock(&handle->h_lock); - return ESRCH; - } - pid = handle->h_descr->p_pid; - __pthread_unlock(&handle->h_lock); - if (kill(pid, signo) == -1) - return errno; - else - return 0; -} - -/* User-provided signal handlers */ -typedef void (*arch_sighandler_t) __PMT ((int, SIGCONTEXT)); -static union -{ - arch_sighandler_t old; - void (*rt) (int, struct siginfo *, struct ucontext *); -} sighandler[NSIG]; - -/* The wrapper around user-provided signal handlers */ -static void pthread_sighandler(int signo, SIGCONTEXT ctx) -{ - pthread_descr self = thread_self(); - char * in_sighandler; - /* If we're in a sigwait operation, just record the signal received - and return without calling the user's handler */ - if (THREAD_GETMEM(self, p_sigwaiting)) { - THREAD_SETMEM(self, p_sigwaiting, 0); - THREAD_SETMEM(self, p_signal, signo); - return; - } - /* Record that we're in a signal handler and call the user's - handler function */ - in_sighandler = THREAD_GETMEM(self, p_in_sighandler); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); - sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, NULL); -} - -/* The same, this time for real-time signals. */ -static void pthread_sighandler_rt(int signo, struct siginfo *si, - struct ucontext *uc) -{ - pthread_descr self = thread_self(); - char * in_sighandler; - /* If we're in a sigwait operation, just record the signal received - and return without calling the user's handler */ - if (THREAD_GETMEM(self, p_sigwaiting)) { - THREAD_SETMEM(self, p_sigwaiting, 0); - THREAD_SETMEM(self, p_signal, signo); - return; - } - /* Record that we're in a signal handler and call the user's - handler function */ - in_sighandler = THREAD_GETMEM(self, p_in_sighandler); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); - sighandler[signo].rt(signo, si, uc); - if (in_sighandler == NULL) - THREAD_SETMEM(self, p_in_sighandler, NULL); -} - -/* The wrapper around sigaction. Install our own signal handler - around the signal. */ -libpthread_hidden_proto(sigaction) -int sigaction(int sig, const struct sigaction * act, - struct sigaction * oact) -{ - struct sigaction newact; - struct sigaction *newactp; - -#ifdef DEBUG_PT -printf(__FUNCTION__": pthreads wrapper!\n"); -#endif - if (sig == __pthread_sig_restart || - sig == __pthread_sig_cancel || - (sig == __pthread_sig_debug && __pthread_sig_debug > 0)) - return EINVAL; - if (act) - { - newact = *act; - if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL - && sig > 0 && sig < NSIG) - { - if (act->sa_flags & SA_SIGINFO) - newact.sa_handler = (__sighandler_t) pthread_sighandler_rt; - else - newact.sa_handler = (__sighandler_t) pthread_sighandler; - } - newactp = &newact; - } - else - newactp = NULL; - if (__libc_sigaction(sig, newactp, oact) == -1) - return -1; -#ifdef DEBUG_PT -printf(__FUNCTION__": sighandler installed, sigaction successful\n"); -#endif - if (sig > 0 && sig < NSIG) - { - if (oact != NULL) - oact->sa_handler = (__sighandler_t) sighandler[sig].old; - if (act) - /* For the assignment is does not matter whether it's a normal - or real-time signal. */ - sighandler[sig].old = (arch_sighandler_t) act->sa_handler; - } - return 0; -} -libpthread_hidden_def(sigaction) - -/* A signal handler that does nothing */ -static void pthread_null_sighandler(int sig attribute_unused) { } - -/* sigwait -- synchronously wait for a signal */ -int sigwait(const sigset_t * set, int * sig) -{ - volatile pthread_descr self = thread_self(); - sigset_t mask; - int s; - sigjmp_buf jmpbuf; - struct sigaction sa; - - /* Get ready to block all signals except those in set - and the cancellation signal. - Also check that handlers are installed on all signals in set, - and if not, install our dummy handler. This is conformant to - POSIX: "The effect of sigwait() on the signal actions for the - signals in set is unspecified." */ - __sigfillset(&mask); - sigdelset(&mask, __pthread_sig_cancel); - for (s = 1; s <= NSIG; s++) { - if (sigismember(set, s) && - s != __pthread_sig_restart && - s != __pthread_sig_cancel && - s != __pthread_sig_debug) { - sigdelset(&mask, s); - if (sighandler[s].old == NULL || - sighandler[s].old == (arch_sighandler_t) SIG_DFL || - sighandler[s].old == (arch_sighandler_t) SIG_IGN) { - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = pthread_null_sighandler; - sigaction(s, &sa, NULL); - } - } - } - /* Test for cancellation */ - if (sigsetjmp(jmpbuf, 1) == 0) { - THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf); - if (! (THREAD_GETMEM(self, p_canceled) - && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) { - /* Reset the signal count */ - THREAD_SETMEM(self, p_signal, 0); - /* Say we're in sigwait */ - THREAD_SETMEM(self, p_sigwaiting, 1); - /* Unblock the signals and wait for them */ - sigsuspend(&mask); - } - } - THREAD_SETMEM(self, p_cancel_jmp, NULL); - /* The signals are now reblocked. Check for cancellation */ - pthread_testcancel(); - /* We should have self->p_signal != 0 and equal to the signal received */ - *sig = THREAD_GETMEM(self, p_signal); - return 0; -} - -/* Redefine raise() to send signal to calling thread only, - as per POSIX 1003.1c */ -libpthread_hidden_proto(raise) -int raise (int sig) -{ - int retcode = pthread_kill(pthread_self(), sig); - if (retcode == 0) - return 0; - else { - errno = retcode; - return -1; - } -} -libpthread_hidden_def(raise) diff --git a/libpthread/linuxthreads.old/specific.c b/libpthread/linuxthreads.old/specific.c deleted file mode 100644 index c4bcfbf8c..000000000 --- a/libpthread/linuxthreads.old/specific.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Thread-specific data */ - -#include <features.h> -#include <errno.h> -#include <stddef.h> -#include <stdlib.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" - -/* Table of keys. */ - -static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = - { { 0, NULL } }; - -/* For debugging purposes put the maximum number of keys in a variable. */ -const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX; -const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE; - -/* Mutex to protect access to pthread_keys */ - -static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* Create a new key */ - -int pthread_key_create(pthread_key_t * key, destr_function destr) -{ - int i; - - __pthread_mutex_lock(&pthread_keys_mutex); - for (i = 0; i < PTHREAD_KEYS_MAX; i++) { - if (! pthread_keys[i].in_use) { - /* Mark key in use */ - pthread_keys[i].in_use = 1; - pthread_keys[i].destr = destr; - __pthread_mutex_unlock(&pthread_keys_mutex); - *key = i; - return 0; - } - } - __pthread_mutex_unlock(&pthread_keys_mutex); - return EAGAIN; -} - -/* Delete a key */ -int pthread_key_delete(pthread_key_t key) -{ - pthread_descr self = thread_self(); - - __pthread_mutex_lock(&pthread_keys_mutex); - if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { - __pthread_mutex_unlock(&pthread_keys_mutex); - return EINVAL; - } - pthread_keys[key].in_use = 0; - pthread_keys[key].destr = NULL; - - /* Set the value of the key to NULL in all running threads, so - that if the key is reallocated later by pthread_key_create, its - associated values will be NULL in all threads. - Do nothing if no threads have been created yet. */ - if (__pthread_manager_request != -1) - { - pthread_descr th; - unsigned int idx1st, idx2nd; - - idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; - idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; - th = self; - do { - /* If the thread already is terminated don't modify the memory. */ - if (!th->p_terminated && th->p_specific[idx1st] != NULL) - th->p_specific[idx1st][idx2nd] = NULL; - th = th->p_nextlive; - } while (th != self); - } - - __pthread_mutex_unlock(&pthread_keys_mutex); - return 0; -} - -/* Set the value of a key */ - -int pthread_setspecific(pthread_key_t key, const void * pointer) -{ - pthread_descr self = thread_self(); - unsigned int idx1st, idx2nd; - - if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) - return EINVAL; - idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; - idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; - if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) { - void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *)); - if (newp == NULL) - return ENOMEM; - THREAD_SETMEM_NC(self, p_specific[idx1st], newp); - } - THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer; - return 0; -} - -/* Get the value of a key */ - -void * pthread_getspecific(pthread_key_t key) -{ - pthread_descr self = thread_self(); - unsigned int idx1st, idx2nd; - - if (key >= PTHREAD_KEYS_MAX) - return NULL; - idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; - idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; - if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL - || !pthread_keys[key].in_use) - return NULL; - return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd]; -} - -/* Call the destruction routines on all keys */ - -void __pthread_destroy_specifics(void) -{ - pthread_descr self = thread_self(); - int i, j, round, found_nonzero; - destr_function destr; - void * data; - - for (round = 0, found_nonzero = 1; - found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS; - round++) { - found_nonzero = 0; - for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) - if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) - for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) { - destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr; - data = THREAD_GETMEM_NC(self, p_specific[i])[j]; - if (destr != NULL && data != NULL) { - THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL; - destr(data); - found_nonzero = 1; - } - } - } - __pthread_lock(THREAD_GETMEM(self, p_lock), self); - for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { - if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) { - free(THREAD_GETMEM_NC(self, p_specific[i])); - THREAD_SETMEM_NC(self, p_specific[i], NULL); - } - } - __pthread_unlock(THREAD_GETMEM(self, p_lock)); -} - -#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_RPC__ - -/* Thread-specific data for libc. */ - -int -__pthread_internal_tsd_set (int key, const void * pointer) -{ - pthread_descr self = thread_self(); - - THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer); - return 0; -} - -void * -__pthread_internal_tsd_get (int key) -{ - pthread_descr self = thread_self(); - - return THREAD_GETMEM_NC(self, p_libc_specific[key]); -} - -void ** __attribute__ ((__const__)) -__pthread_internal_tsd_address (int key) -{ - pthread_descr self = thread_self(); - return &self->p_libc_specific[key]; -} - -#endif diff --git a/libpthread/linuxthreads.old/spinlock.c b/libpthread/linuxthreads.old/spinlock.c deleted file mode 100644 index 80aeda529..000000000 --- a/libpthread/linuxthreads.old/spinlock.c +++ /dev/null @@ -1,720 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -/* Internal locks */ - -#include <errno.h> -#include <sched.h> -#include <time.h> -#include <stdlib.h> -#include <limits.h> -#include "pthread.h" -#include "internals.h" -#include "spinlock.h" -#include "restart.h" - -libpthread_hidden_proto(nanosleep) - -static void __pthread_acquire(int * spinlock); - -static __inline__ void __pthread_release(int * spinlock) -{ - WRITE_MEMORY_BARRIER(); - *spinlock = __LT_SPINLOCK_INIT; - __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock)); -} - - -/* The status field of a spinlock is a pointer whose least significant - bit is a locked flag. - - Thus the field values have the following meanings: - - status == 0: spinlock is free - status == 1: spinlock is taken; no thread is waiting on it - - (status & 1) == 1: spinlock is taken and (status & ~1L) is a - pointer to the first waiting thread; other - waiting threads are linked via the p_nextlock - field. - (status & 1) == 0: same as above, but spinlock is not taken. - - The waiting list is not sorted by priority order. - Actually, we always insert at top of list (sole insertion mode - that can be performed without locking). - For __pthread_unlock, we perform a linear search in the list - to find the highest-priority, oldest waiting thread. - This is safe because there are no concurrent __pthread_unlock - operations -- only the thread that locked the mutex can unlock it. */ - - -void internal_function __pthread_lock(struct _pthread_fastlock * lock, - pthread_descr self) -{ -#if defined HAS_COMPARE_AND_SWAP - long oldstatus, newstatus; - int successful_seizure, spurious_wakeup_count; -#endif - -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - __pthread_acquire(&lock->__spinlock); - return; - } -#endif - -#if defined HAS_COMPARE_AND_SWAP - /* First try it without preparation. Maybe it's a completely - uncontested lock. */ - if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1)) - return; - - spurious_wakeup_count = 0; - - /* On SMP, try spinning to get the lock. */ -#if 0 - if (__pthread_smp_kernel) { - int spin_count; - int max_count = lock->__spinlock * 2 + 10; - - if (max_count > MAX_ADAPTIVE_SPIN_COUNT) - max_count = MAX_ADAPTIVE_SPIN_COUNT; - - for (spin_count = 0; spin_count < max_count; spin_count++) { - if (((oldstatus = lock->__status) & 1) == 0) { - if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1)) - { - if (spin_count) - lock->__spinlock += (spin_count - lock->__spinlock) / 8; - READ_MEMORY_BARRIER(); - return; - } - } -#ifdef BUSY_WAIT_NOP - BUSY_WAIT_NOP; -#endif - __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status)); - } - - lock->__spinlock += (spin_count - lock->__spinlock) / 8; - } -#endif - -again: - - /* No luck, try once more or suspend. */ - - do { - oldstatus = lock->__status; - successful_seizure = 0; - - if ((oldstatus & 1) == 0) { - newstatus = oldstatus | 1; - successful_seizure = 1; - } else { - if (self == NULL) - self = thread_self(); - newstatus = (long) self | 1; - } - - if (self != NULL) { - THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus)); - /* Make sure the store in p_nextlock completes before performing - the compare-and-swap */ - MEMORY_BARRIER(); - } - } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); - - /* Suspend with guard against spurious wakeup. - This can happen in pthread_cond_timedwait_relative, when the thread - wakes up due to timeout and is still on the condvar queue, and then - locks the queue to remove itself. At that point it may still be on the - queue, and may be resumed by a condition signal. */ - - if (!successful_seizure) { - for (;;) { - suspend(self); - if (self->p_nextlock != NULL) { - /* Count resumes that don't belong to us. */ - spurious_wakeup_count++; - continue; - } - break; - } - goto again; - } - - /* Put back any resumes we caught that don't belong to us. */ - while (spurious_wakeup_count--) - restart(self); - - READ_MEMORY_BARRIER(); -#endif -} - -int __pthread_unlock(struct _pthread_fastlock * lock) -{ -#if defined HAS_COMPARE_AND_SWAP - long oldstatus; - pthread_descr thr, * ptr, * maxptr; - int maxprio; -#endif - -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - __pthread_release(&lock->__spinlock); - return 0; - } -#endif - -#if defined HAS_COMPARE_AND_SWAP - WRITE_MEMORY_BARRIER(); - -again: - while ((oldstatus = lock->__status) == 1) { - if (__compare_and_swap_with_release_semantics(&lock->__status, - oldstatus, 0)) - return 0; - } - - /* Find thread in waiting queue with maximal priority */ - ptr = (pthread_descr *) &lock->__status; - thr = (pthread_descr) (oldstatus & ~1L); - maxprio = 0; - maxptr = ptr; - - /* Before we iterate over the wait queue, we need to execute - a read barrier, otherwise we may read stale contents of nodes that may - just have been inserted by other processors. One read barrier is enough to - ensure we have a stable list; we don't need one for each pointer chase - through the list, because we are the owner of the lock; other threads - can only add nodes at the front; if a front node is consistent, - the ones behind it must also be. */ - - READ_MEMORY_BARRIER(); - - while (thr != 0) { - if (thr->p_priority >= maxprio) { - maxptr = ptr; - maxprio = thr->p_priority; - } - ptr = &(thr->p_nextlock); - thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L); - } - - /* Remove max prio thread from waiting list. */ - if (maxptr == (pthread_descr *) &lock->__status) { - /* If max prio thread is at head, remove it with compare-and-swap - to guard against concurrent lock operation. This removal - also has the side effect of marking the lock as released - because the new status comes from thr->p_nextlock whose - least significant bit is clear. */ - thr = (pthread_descr) (oldstatus & ~1L); - if (! __compare_and_swap_with_release_semantics - (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) - goto again; - } else { - /* No risk of concurrent access, remove max prio thread normally. - But in this case we must also flip the least significant bit - of the status to mark the lock as released. */ - thr = (pthread_descr)((long)*maxptr & ~1L); - *maxptr = thr->p_nextlock; - - /* Ensure deletion from linked list completes before we - release the lock. */ - WRITE_MEMORY_BARRIER(); - - do { - oldstatus = lock->__status; - } while (!__compare_and_swap_with_release_semantics(&lock->__status, - oldstatus, oldstatus & ~1L)); - } - - /* Wake up the selected waiting thread. Woken thread can check - its own p_nextlock field for NULL to detect that it has been removed. No - barrier is needed here, since restart() and suspend() take - care of memory synchronization. */ - - thr->p_nextlock = NULL; - restart(thr); - - return 0; -#endif -} - -/* - * Alternate fastlocks do not queue threads directly. Instead, they queue - * these wait queue node structures. When a timed wait wakes up due to - * a timeout, it can leave its wait node in the queue (because there - * is no safe way to remove from the quue). Some other thread will - * deallocate the abandoned node. - */ - - -struct wait_node { - struct wait_node *next; /* Next node in null terminated linked list */ - pthread_descr thr; /* The thread waiting with this node */ - int abandoned; /* Atomic flag */ -}; - -static long wait_node_free_list; -static int wait_node_free_list_spinlock; - -/* Allocate a new node from the head of the free list using an atomic - operation, or else using malloc if that list is empty. A fundamental - assumption here is that we can safely access wait_node_free_list->next. - That's because we never free nodes once we allocate them, so a pointer to a - node remains valid indefinitely. */ - -static struct wait_node *wait_node_alloc(void) -{ - struct wait_node *new_node = 0; - - __pthread_acquire(&wait_node_free_list_spinlock); - if (wait_node_free_list != 0) { - new_node = (struct wait_node *) wait_node_free_list; - wait_node_free_list = (long) new_node->next; - } - WRITE_MEMORY_BARRIER(); - __pthread_release(&wait_node_free_list_spinlock); - - if (new_node == 0) - return malloc(sizeof *wait_node_alloc()); - - return new_node; -} - -/* Return a node to the head of the free list using an atomic - operation. */ - -static void wait_node_free(struct wait_node *wn) -{ - __pthread_acquire(&wait_node_free_list_spinlock); - wn->next = (struct wait_node *) wait_node_free_list; - wait_node_free_list = (long) wn; - WRITE_MEMORY_BARRIER(); - __pthread_release(&wait_node_free_list_spinlock); - return; -} - -#if defined HAS_COMPARE_AND_SWAP - -/* Remove a wait node from the specified queue. It is assumed - that the removal takes place concurrently with only atomic insertions at the - head of the queue. */ - -static void wait_node_dequeue(struct wait_node **pp_head, - struct wait_node **pp_node, - struct wait_node *p_node) -{ - /* If the node is being deleted from the head of the - list, it must be deleted using atomic compare-and-swap. - Otherwise it can be deleted in the straightforward way. */ - - if (pp_node == pp_head) { - /* We don't need a read barrier between these next two loads, - because it is assumed that the caller has already ensured - the stability of *p_node with respect to p_node. */ - - long oldvalue = (long) p_node; - long newvalue = (long) p_node->next; - - if (__compare_and_swap((long *) pp_node, oldvalue, newvalue)) - return; - - /* Oops! Compare and swap failed, which means the node is - no longer first. We delete it using the ordinary method. But we don't - know the identity of the node which now holds the pointer to the node - being deleted, so we must search from the beginning. */ - - for (pp_node = pp_head; p_node != *pp_node; ) { - pp_node = &(*pp_node)->next; - READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */ - } - } - - *pp_node = p_node->next; - return; -} - -#endif - -void __pthread_alt_lock(struct _pthread_fastlock * lock, - pthread_descr self) -{ -#if defined HAS_COMPARE_AND_SWAP - long oldstatus, newstatus; -#endif - struct wait_node wait_node; - -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - int suspend_needed = 0; - __pthread_acquire(&lock->__spinlock); - - if (lock->__status == 0) - lock->__status = 1; - else { - if (self == NULL) - self = thread_self(); - - wait_node.abandoned = 0; - wait_node.next = (struct wait_node *) lock->__status; - wait_node.thr = self; - lock->__status = (long) &wait_node; - suspend_needed = 1; - } - - __pthread_release(&lock->__spinlock); - - if (suspend_needed) - suspend (self); - return; - } -#endif - -#if defined HAS_COMPARE_AND_SWAP - do { - oldstatus = lock->__status; - if (oldstatus == 0) { - newstatus = 1; - } else { - if (self == NULL) - self = thread_self(); - wait_node.thr = self; - newstatus = (long) &wait_node; - } - wait_node.abandoned = 0; - wait_node.next = (struct wait_node *) oldstatus; - /* Make sure the store in wait_node.next completes before performing - the compare-and-swap */ - MEMORY_BARRIER(); - } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); - - /* Suspend. Note that unlike in __pthread_lock, we don't worry - here about spurious wakeup. That's because this lock is not - used in situations where that can happen; the restart can - only come from the previous lock owner. */ - - if (oldstatus != 0) - suspend(self); - - READ_MEMORY_BARRIER(); -#endif -} - -/* Timed-out lock operation; returns 0 to indicate timeout. */ - -int __pthread_alt_timedlock(struct _pthread_fastlock * lock, - pthread_descr self, const struct timespec *abstime) -{ - long oldstatus = 0; -#if defined HAS_COMPARE_AND_SWAP - long newstatus; -#endif - struct wait_node *p_wait_node = wait_node_alloc(); - - /* Out of memory, just give up and do ordinary lock. */ - if (p_wait_node == 0) { - __pthread_alt_lock(lock, self); - return 1; - } - -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - __pthread_acquire(&lock->__spinlock); - - if (lock->__status == 0) - lock->__status = 1; - else { - if (self == NULL) - self = thread_self(); - - p_wait_node->abandoned = 0; - p_wait_node->next = (struct wait_node *) lock->__status; - p_wait_node->thr = self; - lock->__status = (long) p_wait_node; - oldstatus = 1; /* force suspend */ - } - - __pthread_release(&lock->__spinlock); - goto suspend; - } -#endif - -#if defined HAS_COMPARE_AND_SWAP - do { - oldstatus = lock->__status; - if (oldstatus == 0) { - newstatus = 1; - } else { - if (self == NULL) - self = thread_self(); - p_wait_node->thr = self; - newstatus = (long) p_wait_node; - } - p_wait_node->abandoned = 0; - p_wait_node->next = (struct wait_node *) oldstatus; - /* Make sure the store in wait_node.next completes before performing - the compare-and-swap */ - MEMORY_BARRIER(); - } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); -#endif - -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - suspend: -#endif - - /* If we did not get the lock, do a timed suspend. If we wake up due - to a timeout, then there is a race; the old lock owner may try - to remove us from the queue. This race is resolved by us and the owner - doing an atomic testandset() to change the state of the wait node from 0 - to 1. If we succeed, then it's a timeout and we abandon the node in the - queue. If we fail, it means the owner gave us the lock. */ - - if (oldstatus != 0) { - if (timedsuspend(self, abstime) == 0) { - if (!testandset(&p_wait_node->abandoned)) - return 0; /* Timeout! */ - - /* Eat oustanding resume from owner, otherwise wait_node_free() below - will race with owner's wait_node_dequeue(). */ - suspend(self); - } - } - - wait_node_free(p_wait_node); - - READ_MEMORY_BARRIER(); - - return 1; /* Got the lock! */ -} - -void __pthread_alt_unlock(struct _pthread_fastlock *lock) -{ - struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio; - struct wait_node ** const pp_head = (struct wait_node **) &lock->__status; - int maxprio; - - WRITE_MEMORY_BARRIER(); - -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - __pthread_acquire(&lock->__spinlock); - } -#endif - - while (1) { - - /* If no threads are waiting for this lock, try to just - atomically release it. */ -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - if (lock->__status == 0 || lock->__status == 1) { - lock->__status = 0; - break; - } - } -#endif - -#if defined TEST_FOR_COMPARE_AND_SWAP - else -#endif - -#if defined HAS_COMPARE_AND_SWAP - { - long oldstatus = lock->__status; - if (oldstatus == 0 || oldstatus == 1) { - if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0)) - break; - else - continue; - } - } -#endif - - /* Process the entire queue of wait nodes. Remove all abandoned - wait nodes and put them into the global free queue, and - remember the one unabandoned node which refers to the thread - having the highest priority. */ - - pp_max_prio = pp_node = pp_head; - p_max_prio = p_node = *pp_head; - maxprio = INT_MIN; - - READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */ - - while (p_node != (struct wait_node *) 1) { - int prio; - - if (p_node->abandoned) { - /* Remove abandoned node. */ -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - *pp_node = p_node->next; -#endif -#if defined TEST_FOR_COMPARE_AND_SWAP - else -#endif -#if defined HAS_COMPARE_AND_SWAP - wait_node_dequeue(pp_head, pp_node, p_node); -#endif - wait_node_free(p_node); - /* Note that the next assignment may take us to the beginning - of the queue, to newly inserted nodes, if pp_node == pp_head. - In that case we need a memory barrier to stabilize the first of - these new nodes. */ - p_node = *pp_node; - if (pp_node == pp_head) - READ_MEMORY_BARRIER(); /* No stale reads through p_node */ - continue; - } else if ((prio = p_node->thr->p_priority) >= maxprio) { - /* Otherwise remember it if its thread has a higher or equal priority - compared to that of any node seen thus far. */ - maxprio = prio; - pp_max_prio = pp_node; - p_max_prio = p_node; - } - - /* This canno6 jump backward in the list, so no further read - barrier is needed. */ - pp_node = &p_node->next; - p_node = *pp_node; - } - - /* If all threads abandoned, go back to top */ - if (maxprio == INT_MIN) - continue; - - /* Now we want to to remove the max priority thread's wait node from - the list. Before we can do this, we must atomically try to change the - node's abandon state from zero to nonzero. If we succeed, that means we - have the node that we will wake up. If we failed, then it means the - thread timed out and abandoned the node in which case we repeat the - whole unlock operation. */ - - if (!testandset(&p_max_prio->abandoned)) { -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - *pp_max_prio = p_max_prio->next; -#endif -#if defined TEST_FOR_COMPARE_AND_SWAP - else -#endif -#if defined HAS_COMPARE_AND_SWAP - wait_node_dequeue(pp_head, pp_max_prio, p_max_prio); -#endif - restart(p_max_prio->thr); - break; - } - } - -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - __pthread_release(&lock->__spinlock); - } -#endif -} - - -/* Compare-and-swap emulation with a spinlock */ - -#ifdef TEST_FOR_COMPARE_AND_SWAP -int __pthread_has_cas = 0; -#endif - -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - -int __pthread_compare_and_swap(long * ptr, long oldval, long newval, - int * spinlock) -{ - int res; - - __pthread_acquire(spinlock); - - if (*ptr == oldval) { - *ptr = newval; res = 1; - } else { - res = 0; - } - - __pthread_release(spinlock); - - return res; -} - -#endif - -/* The retry strategy is as follows: - - We test and set the spinlock MAX_SPIN_COUNT times, calling - sched_yield() each time. This gives ample opportunity for other - threads with priority >= our priority to make progress and - release the spinlock. - - If a thread with priority < our priority owns the spinlock, - calling sched_yield() repeatedly is useless, since we're preventing - the owning thread from making progress and releasing the spinlock. - So, after MAX_SPIN_LOCK attemps, we suspend the calling thread - using nanosleep(). This again should give time to the owning thread - for releasing the spinlock. - Notice that the nanosleep() interval must not be too small, - since the kernel does busy-waiting for short intervals in a realtime - process (!). The smallest duration that guarantees thread - suspension is currently 2ms. - - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT - sched_yield(), then sleeping again if needed. */ - -static void __pthread_acquire(int * spinlock) -{ - int cnt = 0; - struct timespec tm; - - READ_MEMORY_BARRIER(); - - while (testandset(spinlock)) { - if (cnt < MAX_SPIN_COUNT) { - sched_yield(); - cnt++; - } else { - tm.tv_sec = 0; - tm.tv_nsec = SPIN_SLEEP_DURATION; - nanosleep(&tm, NULL); - cnt = 0; - } - } -} diff --git a/libpthread/linuxthreads.old/spinlock.h b/libpthread/linuxthreads.old/spinlock.h deleted file mode 100644 index 7117898f7..000000000 --- a/libpthread/linuxthreads.old/spinlock.h +++ /dev/null @@ -1,218 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -#include <bits/initspin.h> - - -/* There are 2 compare and swap synchronization primitives with - different semantics: - - 1. compare_and_swap, which has acquire semantics (i.e. it - completes befor subsequent writes.) - 2. compare_and_swap_with_release_semantics, which has release - semantics (it completes after previous writes.) - - For those platforms on which they are the same. HAS_COMPARE_AND_SWAP - should be defined. For those platforms on which they are different, - HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */ - -#ifndef HAS_COMPARE_AND_SWAP -#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS -#define HAS_COMPARE_AND_SWAP -#endif -#endif - -#if defined(TEST_FOR_COMPARE_AND_SWAP) - -extern int __pthread_has_cas; -extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, - int * spinlock); - -static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, - int * spinlock) -{ - if (__builtin_expect (__pthread_has_cas, 1)) - return __compare_and_swap(ptr, oldval, newval); - else - return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); -} - -#elif defined(HAS_COMPARE_AND_SWAP) - -#ifdef IMPLEMENT_TAS_WITH_CAS -#define testandset(p) !__compare_and_swap((long int *) p, 0, 1) -#endif - -#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS - -static __inline__ int -compare_and_swap_with_release_semantics (long * ptr, long oldval, - long newval, int * spinlock) -{ - return __compare_and_swap_with_release_semantics (ptr, oldval, - newval); -} - -#endif - -static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, - int * spinlock) -{ - return __compare_and_swap(ptr, oldval, newval); -} - -#else - -extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, - int * spinlock); - -static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, - int * spinlock) -{ - return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); -} - -#endif - -#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS -#define compare_and_swap_with_release_semantics compare_and_swap -#define __compare_and_swap_with_release_semantics __compare_and_swap -#endif - -/* Internal locks */ - -extern void internal_function __pthread_lock(struct _pthread_fastlock * lock, - pthread_descr self); -extern int __pthread_unlock(struct _pthread_fastlock *lock); - -static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock) -{ - lock->__status = 0; - lock->__spinlock = __LT_SPINLOCK_INIT; -} - -static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock) -{ -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - return (testandset(&lock->__spinlock) ? EBUSY : 0); - } -#endif - -#if defined HAS_COMPARE_AND_SWAP - do { - if (lock->__status != 0) return EBUSY; - } while(! __compare_and_swap(&lock->__status, 0, 1)); - return 0; -#endif -} - -/* Variation of internal lock used for pthread_mutex_t, supporting - timed-out waits. Warning: do not mix these operations with the above ones - over the same lock object! */ - -extern void __pthread_alt_lock(struct _pthread_fastlock * lock, - pthread_descr self); - -extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock, - pthread_descr self, const struct timespec *abstime); - -extern void __pthread_alt_unlock(struct _pthread_fastlock *lock); - -static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock) -{ - lock->__status = 0; - lock->__spinlock = __LT_SPINLOCK_INIT; -} - -static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock) -{ -#if defined TEST_FOR_COMPARE_AND_SWAP - if (!__pthread_has_cas) -#endif -#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP - { - int res = EBUSY; - - if (testandset(&lock->__spinlock) == 0) - { - if (lock->__status == 0) - { - lock->__status = 1; - WRITE_MEMORY_BARRIER(); - res = 0; - } - lock->__spinlock = __LT_SPINLOCK_INIT; - } - return res; - } -#endif - -#if defined HAS_COMPARE_AND_SWAP - do { - if (lock->__status != 0) return EBUSY; - } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock)); - return 0; -#endif -} - -/* Operations on pthread_atomic, which is defined in internals.h */ - -static __inline__ long atomic_increment(struct pthread_atomic *pa) -{ - long oldval; - - do { - oldval = pa->p_count; - } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock)); - - return oldval; -} - - -static __inline__ long atomic_decrement(struct pthread_atomic *pa) -{ - long oldval; - - do { - oldval = pa->p_count; - } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock)); - - return oldval; -} - - -static __inline__ void -__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) -{ - /* Only store a non-null peif if the thread has cancellation enabled. - Otherwise pthread_cancel will unconditionally call the extricate handler, - and restart the thread giving rise to forbidden spurious wakeups. */ - if (peif == NULL - || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) - { - /* If we are removing the extricate interface, we need to synchronize - against pthread_cancel so that it does not continue with a pointer - to a deallocated pthread_extricate_if struct! The thread lock - is (ab)used for this synchronization purpose. */ - if (peif == NULL) - __pthread_lock (THREAD_GETMEM(self, p_lock), self); - THREAD_SETMEM(self, p_extricate, peif); - if (peif == NULL) - __pthread_unlock (THREAD_GETMEM(self, p_lock)); - } -} diff --git a/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h deleted file mode 100644 index b47343ba7..000000000 --- a/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - Alpha version. - Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If not, - see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -#ifdef __linux__ -# include <asm/pal.h> -#else -# include <machine/pal.h> -#endif - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char *stack_pointer __asm__("$30"); - - -/* Memory barrier; default is to do nothing */ -#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory") -/* Write barrier. */ -#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory") - - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - long int ret, temp; - - __asm__ __volatile__( - "/* Inline spinlock test & set */\n" - "1:\t" - "ldl_l %0,%3\n\t" - "bne %0,2f\n\t" - "or $31,1,%1\n\t" - "stl_c %1,%2\n\t" - "beq %1,1b\n" - "2:\tmb\n" - "/* End spinlock test & set */" - : "=&r"(ret), "=&r"(temp), "=m"(*spinlock) - : "m"(*spinlock) - : "memory"); - - return ret; -} - - -/* Begin allocating thread stacks at this address. Default is to allocate - them just below the initial program stack. */ -#define THREAD_STACK_START_ADDRESS 0x40000000000 - - -/* Return the thread descriptor for the current thread. */ -#define THREAD_SELF \ -({ \ - register pthread_descr __self __asm__("$0"); \ - __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ - __self; \ -}) - -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) \ -{ \ - register pthread_descr __self __asm__("$16") = (descr); \ - __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \ -} - - -/* Compare-and-swap for semaphores. */ - -#define HAS_COMPARE_AND_SWAP -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - long int ret; - - __asm__ __volatile__ ( - "/* Inline compare & swap */\n" - "1:\t" - "ldq_l %0,%4\n\t" - "cmpeq %0,%2,%0\n\t" - "beq %0,2f\n\t" - "mov %3,%0\n\t" - "stq_c %0,%1\n\t" - "beq %0,1b\n\t" - "2:\tmb\n" - "/* End compare & swap */" - : "=&r"(ret), "=m"(*p) - : "r"(oldval), "r"(newval), "m"(*p) - : "memory"); - - return ret; -} - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* Maximum size of the stack if the rlimit is unlimited. */ -#define ARCH_STACK_MAX_SIZE 32*1024*1024 - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/arc/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/arc/pt-machine.h deleted file mode 100644 index 8df1e77e3..000000000 --- a/libpthread/linuxthreads.old/sysdeps/arc/pt-machine.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) - * - * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. - */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - -PT_EI long int -testandset (int *spinlock) -{ - unsigned int old = 1; - - /* Atomically exchange @spinlock with 1 */ - __asm__ __volatile__( - "ex %0, [%1]" - : "+r" (old) - : "r" (spinlock) - : "memory"); - - return old; - -} - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. - I don't trust register variables, so let's do this the safe way. */ -#define CURRENT_STACK_FRAME \ -__extension__ ({ char *__sp; __asm__ ("mov %0,sp" : "=r" (__sp)); __sp; }) - -#else -#error PT_MACHINE already defined -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h deleted file mode 100644 index 2b877f980..000000000 --- a/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - ARM version. - Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Philip Blundell <philb@gnu.org>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <sys/syscall.h> -#include <unistd.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -#if defined(__thumb__) -#if defined(__USE_LDREXSTREX__) -PT_EI long int ldrex(int *spinlock) -{ - long int ret; - __asm__ __volatile__( - "ldrex %0, [%1]\n" - : "=r"(ret) - : "r"(spinlock) : "memory"); - return ret; -} - -PT_EI long int strex(int val, int *spinlock) -{ - long int ret; - __asm__ __volatile__( - "strex %0, %1, [%2]\n" - : "=r"(ret) - : "r" (val), "r"(spinlock) : "memory"); - return ret; -} - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - register unsigned int ret; - - do { - ret = ldrex(spinlock); - } while (strex(1, spinlock)); - - return ret; -} - -#else /* __USE_LDREXSTREX__ */ - -/* This will not work on ARM1 or ARM2 because SWP is lacking on those - machines. Unfortunately we have no way to detect this at compile - time; let's hope nobody tries to use one. */ - -/* Spinlock implementation; required. */ -PT_EI long int testandset (int *spinlock); -PT_EI long int testandset (int *spinlock) -{ - register unsigned int ret; - void *pc; - __asm__ __volatile__( - ".align 0\n" - "\tbx pc\n" - "\tnop\n" - "\t.arm\n" - "\tswp %0, %2, [%3]\n" - "\torr %1, pc, #1\n" - "\tbx %1\n" - "\t.force_thumb" - : "=r"(ret), "=r"(pc) - : "0"(1), "r"(spinlock)); - return ret; -} -#endif -#else /* __thumb__ */ - -PT_EI long int testandset (int *spinlock); -PT_EI long int testandset (int *spinlock) -{ - register unsigned int ret; - __asm__ __volatile__("swp %0, %1, [%2]" - : "=r"(ret) - : "0"(1), "r"(spinlock)); - return ret; -} -#endif - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("sp"); - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h deleted file mode 100644 index 5735d0ea2..000000000 --- a/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - * - * Copyright (C) 2005-2007 Atmel Corporation - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License. See the file "COPYING.LIB" in the main directory of this - * archive for more details. - */ -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -static __inline__ int -_test_and_set (int *p, int v) -{ - int result; - - __asm__ __volatile__( - "/* Inline test and set */\n" - " xchg %[old], %[mem], %[new]" - : [old] "=&r"(result) - : [mem] "r"(p), [new] "r"(v) - : "memory"); - - return result; -} - -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - return _test_and_set(spinlock, 1); -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("sp"); - -/* Compare-and-swap for semaphores. */ - -#define HAS_COMPARE_AND_SWAP -PT_EI int -__compare_and_swap(long int *p, long int oldval, long int newval) -{ - long int result; - - __asm__ __volatile__( - "/* Inline compare and swap */\n" - "1: ssrf 5\n" - " ld.w %[result], %[mem]\n" - " eor %[result], %[old]\n" - " brne 2f\n" - " stcond %[mem], %[new]\n" - " brne 1b\n" - "2:" - : [result] "=&r"(result), [mem] "=m"(*p) - : "m"(*p), [new] "r"(newval), [old] "r"(oldval) - : "cc", "memory"); - - return result == 0; -} - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h deleted file mode 100644 index 912d64b2c..000000000 --- a/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -#include <asm/fixed_code.h> - -/* Spinlock implementation; required. */ -/* The semantics of the TESTSET instruction cannot be guaranteed. We cannot - easily move all locks used by linux kernel to non-cacheable memory. - EXCPT 0x4 is used to trap into kernel to do the atomic testandset. - It's ugly. But it's the only thing we can do now. - The handler of EXCPT 0x4 expects the address of the lock is passed through - R0. And the result is returned by R0. */ -PT_EI long int -testandset (int *spinlock) -{ - long int res; - - __asm__ __volatile__ ( - "CALL (%4);" - : "=q0" (res), "=m" (*spinlock) - : "qA" (spinlock), "m" (*spinlock), "a" (ATOMIC_XCHG32), "q1" (1) - : "RETS", "cc", "memory"); - - return res; -} - -#define HAS_COMPARE_AND_SWAP -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - long int readval; - __asm__ __volatile__ ( - "CALL (%5);" - : "=q0" (readval), "=m" (*p) - : "qA" (p), - "q1" (oldval), - "q2" (newval), - "a" (ATOMIC_CAS32), - "m" (*p) - : "RETS", "memory", "cc"); - return readval == oldval; -} - -#ifdef SHARED -# define PTHREAD_STATIC_FN_REQUIRE(name) -#else -# define PTHREAD_STATIC_FN_REQUIRE(name) __asm__ (".globl " "_"#name); -#endif - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/c6x/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/c6x/pt-machine.h deleted file mode 100644 index 5e8bfca56..000000000 --- a/libpthread/linuxthreads.old/sysdeps/c6x/pt-machine.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - C6x version. - Copyright (C) 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Aurelien Jacquiot <aurelien.jacquiot@jaluna.com>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#ifndef PT_EI -# define PT_EI extern inline -#endif - -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - -/* Spinlock implementation; required. */ -static inline long int -testandset (int *spinlock) -{ - register unsigned int ret = 1; - int dummy; - __asm__ __volatile__ ("mvc .s2 CSR, %0\n\tand .s2 -2, %0, %0\n\tmvc .s2 %0, CSR\n" - : "=b" (dummy)); - - if (*spinlock == 0) { - *spinlock = 1; - ret = 0; - } - __asm__ __volatile__ ("mvc .s2 CSR, %0\n\tor .s2 1, %0, %0\n\tmvc .s2 %0, CSR\n" - : "=b" (dummy)); - return ret; -} - -#define WRITE_MEMORY_BARRIER() -#define READ_MEMORY_BARRIER() - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME get_stack_pointer() -static inline char * get_stack_pointer(void) -{ - char *sp; - __asm__ __volatile__ ("mv .d2 B15, %0" : "=b" (sp)); - return sp; -} - -#define THREAD_STACK_OFFSET 8 - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h deleted file mode 100644 index a89579ee0..000000000 --- a/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - CRIS version. - Copyright (C) 2001, 2002, 2003 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 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; see the file COPYING.LIB. If not, - see <http://www.gnu.org/licenses/>. */ -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -PT_EI long int -testandset (int *spinlock) -{ - register unsigned long int ret; - - /* Note the use of a dummy output of *spinlock to expose the write. The - memory barrier is to stop *other* writes being moved past this code. */ - -#ifdef __arch_v32 - __asm__ __volatile__("clearf p\n" - "0:\n\t" - "movu.b [%2],%0\n\t" - "ax\n\t" - "move.b %3,[%2]\n\t" - "bcs 0b\n\t" - "clearf p" - : "=&r" (ret), "=m" (*spinlock) - : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) - : "memory"); -#else /* not __arch_v32 */ - __asm__ __volatile__("clearf\n" - "0:\n\t" - "movu.b [%2],%0\n\t" - "ax\n\t" - "move.b %3,[%2]\n\t" - "bwf 0b\n\t" - "clearf" - : "=&r" (ret), "=m" (*spinlock) - : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) - : "memory"); -#endif /* __arch_v32 */ - return ret; -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. - I don't trust register variables, so let's do this the safe way. */ -#define CURRENT_STACK_FRAME \ - ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h deleted file mode 100644 index 6f867ade7..000000000 --- a/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - FR-V version. - Copyright (C) 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Alexandre Oliva <aoliva@redhat.com> - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef __ASSEMBLER__ - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - int i = 1; - __asm__ ("swap%I0 %M0, %1" : "+m"(*(volatile int *)spinlock), "+r"(i)); - return i; -} - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* This symbol is defined by the ABI as the stack size requested by - the main program. */ -extern char __stacksize; -#define ARCH_STACK_MAX_SIZE ((unsigned long)&__stacksize) - -/* Memory barrier; default is to do nothing */ -#define MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory") -/* Write barrier. */ -#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory") - -/* Return the thread descriptor for the current thread. */ -register struct _pthread_descr_struct *THREAD_SELF __asm__ ("gr29"); -#define THREAD_SELF THREAD_SELF - -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) \ - (THREAD_SELF = descr) - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("sp"); - -#endif - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h deleted file mode 100644 index a37384de9..000000000 --- a/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - H8/300 version. - Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - char ret; - - __asm__ __volatile__( - "sub.w %0,%0\n\t" - "stc ccr,@-sp\n\t" - "orc #0x80,ccr\n\t" - "bld #0,@%2\n\t" - "bset #0,@%2\n\t" - "rotxl.w %0\n\t" - "ldc @sp+,ccr\n\t" - :"=r"(ret),"=m"(*spinlock) - :"g"(spinlock) - :"cc"); - - return ret; -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("%sp"); - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h deleted file mode 100644 index 24c5e6c7c..000000000 --- a/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h +++ /dev/null @@ -1,146 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - i386 version. - Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef __ASSEMBLER__ -#ifndef PT_EI -# define PT_EI __extern_always_inline __attribute__((visibility("hidden"))) -#endif - -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME __builtin_frame_address (0) - - -/* See if we can optimize for newer cpus... */ -#if defined __GNUC__ && __GNUC__ >= 2 && \ - (defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __pentium4__ || \ - defined __athlon__ || defined __k8__) - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - long int ret; - - __asm__ __volatile__ ( - "xchgl %0, %1" - : "=r" (ret), "=m" (*spinlock) - : "0" (1), "m" (*spinlock) - : "memory"); - - return ret; -} - -/* Compare-and-swap for semaphores. It's always available on i686. */ -#define HAS_COMPARE_AND_SWAP - -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - char ret; - long int readval; - - __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" - : "=q" (ret), "=m" (*p), "=a" (readval) - : "r" (newval), "m" (*p), "a" (oldval) - : "memory"); - return ret; -} - -#if defined(__ASSUME_LDT_WORKS) && __ASSUME_LDT_WORKS > 0 -#include "useldt.h" -#endif - -/* The P4 and above really want some help to prevent overheating. */ -#define BUSY_WAIT_NOP __asm__ ("rep; nop") - - -#else /* Generic i386 implementation */ - -extern int compare_and_swap_is_available (void); - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - long int ret; - - __asm__ __volatile__( - "xchgl %0, %1" - : "=r"(ret), "=m"(*spinlock) - : "0"(1), "m"(*spinlock) - : "memory"); - - return ret; -} - - -/* Compare-and-swap for semaphores. - Available on the 486 and above, but not on the 386. - We test dynamically whether it's available or not. */ - -#define HAS_COMPARE_AND_SWAP -#define TEST_FOR_COMPARE_AND_SWAP - -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - char ret; - long int readval; - - __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" - : "=q" (ret), "=m" (*p), "=a" (readval) - : "r" (newval), "m" (*p), "a" (oldval) - : "memory"); - return ret; -} - -PT_EI int -compare_and_swap_is_available (void) -{ - int changed; - int oldflags; - /* get EFLAGS */ - __asm__ __volatile__ ("pushfl; popl %0" : "=r" (oldflags) : ); - /* Flip AC bit in EFLAGS. */ - __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags ^ 0x40000) : "cc"); - /* reread EFLAGS */ - __asm__ __volatile__ ("pushfl; popl %0" : "=r" (changed) : ); - /* See if bit changed. */ - changed = (changed ^ oldflags) & 0x40000; - /* Restore EFLAGS. */ - __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags) : "cc"); - /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. - Otherwise, it's a 486 or above and it has cmpxchg. */ - return changed != 0; -} -#endif /* Generic i386 implementation */ - -#endif /* __ASSEMBLER__ */ - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/i386/tls.h b/libpthread/linuxthreads.old/sysdeps/i386/tls.h deleted file mode 100644 index 4469f0776..000000000 --- a/libpthread/linuxthreads.old/sysdeps/i386/tls.h +++ /dev/null @@ -1,184 +0,0 @@ -/* Definition for thread-local data handling. linuxthreads/i386 version. - Copyright (C) 2002, 2003, 2004, 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 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _TLS_H -#define _TLS_H - -# include <pt-machine.h> - -#ifndef __ASSEMBLER__ -# include <stdbool.h> -# include <stddef.h> -# include <stdint.h> - -/* Type for the dtv. */ -typedef union dtv -{ - size_t counter; - void *pointer; -} dtv_t; - - -typedef struct -{ - void *tcb; /* Pointer to the TCB. Not necessary the - thread descriptor used by libpthread. */ - dtv_t *dtv; - void *self; /* Pointer to the thread descriptor. */ -} tcbhead_t; -#endif - - -/* We can support TLS only if the floating-stack support is available. */ -#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT - -/* Signal that TLS support is available. */ -//# define USE_TLS 1 - -# ifndef __ASSEMBLER__ -/* Get system call information. */ -# include <sysdep.h> - - -/* Get the thread descriptor definition. */ -# include <linuxthreads/descr.h> - -/* This is the size of the initial TCB. */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) - -/* Alignment requirements for the initial TCB. */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) - -/* This is the size of the TCB. */ -# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) - -/* Alignment requirements for the TCB. */ -# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) - -/* The TCB can have any size and the memory following the address the - thread pointer points to is unspecified. Allocate the TCB there. */ -# define TLS_TCB_AT_TP 1 - - -/* Install the dtv pointer. The pointer passed is to the element with - index -1 which contain the length. */ -# define INSTALL_DTV(descr, dtvp) \ - ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 - -/* Install new dtv for current thread. */ -# define INSTALL_NEW_DTV(dtv) \ - ({ struct _pthread_descr_struct *__descr; \ - THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) - -/* Return dtv of given thread descriptor. */ -# define GET_DTV(descr) \ - (((tcbhead_t *) (descr))->dtv) - -# ifdef __PIC__ -# define TLS_EBX_ARG "r" -# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" -# else -# define TLS_EBX_ARG "b" -# define TLS_LOAD_EBX -# endif - -# define TLS_DO_MODIFY_LDT(descr, nr) \ -({ \ - struct modify_ldt_ldt_s ldt_entry = \ - { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ - 1, 0, 0, 1, 0, 1, 0 }; \ - int result; \ - __asm__ __volatile__ (TLS_LOAD_EBX \ - "int $0x80\n\t" \ - TLS_LOAD_EBX \ - : "=a" (result) \ - : "0" (__NR_modify_ldt), \ - /* The extra argument with the "m" constraint is necessary \ - to let the compiler know that we are accessing LDT_ENTRY \ - here. */ \ - "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ - "d" (sizeof (ldt_entry))); \ - __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \ -}) - -# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ -({ \ - struct modify_ldt_ldt_s ldt_entry = \ - { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ - 1, 0, 0, 1, 0, 1, 0 }; \ - int result; \ - if (secondcall) \ - ldt_entry.entry_number = ({ int _gs; \ - __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \ - (_gs & 0xffff) >> 3; }); \ - __asm__ __volatile__ (TLS_LOAD_EBX \ - "int $0x80\n\t" \ - TLS_LOAD_EBX \ - : "=a" (result), "=m" (ldt_entry.entry_number) \ - : "0" (__NR_set_thread_area), \ - /* The extra argument with the "m" constraint is necessary \ - to let the compiler know that we are accessing LDT_ENTRY \ - here. */ \ - TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ - __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \ -}) - -# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL -# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ - TLS_DO_SET_THREAD_AREA (descr, firstcall) -# elif defined __NR_set_thread_area -# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ - ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \ - __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; }) -# else -# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ - TLS_DO_MODIFY_LDT ((descr), 0) -# endif - -/* Code to initially initialize the thread pointer. This might need - special attention since 'errno' is not yet available and if the - operation can cause a failure 'errno' must not be touched. */ -# define TLS_INIT_TP(descr, secondcall) \ - ({ \ - void *_descr = (descr); \ - tcbhead_t *head = _descr; \ - int __gs; \ - \ - head->tcb = _descr; \ - /* For now the thread descriptor is at the same address. */ \ - head->self = _descr; \ - \ - __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ - if (__builtin_expect (__gs, 7) != -1) \ - { \ - __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ - __gs = 0; \ - } \ - __gs; \ - }) - - -/* Return the address of the dtv for the current thread. */ -# define THREAD_DTV() \ - ({ struct _pthread_descr_struct *__descr; \ - THREAD_GETMEM (__descr, p_header.data.dtvp); }) - -# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ -#endif /* __ASSEMBLER__ */ - -#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/i386/useldt.h b/libpthread/linuxthreads.old/sysdeps/i386/useldt.h deleted file mode 100644 index 02326729a..000000000 --- a/libpthread/linuxthreads.old/sysdeps/i386/useldt.h +++ /dev/null @@ -1,306 +0,0 @@ -/* Special definitions for ix86 machine using segment register based - thread descriptor. - Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>. - - 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; see the file COPYING.LIB. If not, - see <http://www.gnu.org/licenses/>. */ - -#ifndef __ASSEMBLER__ -#include <stddef.h> /* For offsetof. */ -#include <stdlib.h> /* For abort(). */ - - -/* We don't want to include the kernel header. So duplicate the - information. */ - -/* Structure passed on `modify_ldt' call. */ -struct modify_ldt_ldt_s -{ - unsigned int entry_number; - unsigned long int base_addr; - unsigned int limit; - unsigned int seg_32bit:1; - unsigned int contents:2; - unsigned int read_exec_only:1; - unsigned int limit_in_pages:1; - unsigned int seg_not_present:1; - unsigned int useable:1; - unsigned int empty:25; -}; - -/* System call to set LDT entry. */ -extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); - - -/* Return the thread descriptor for the current thread. - - The contained asm must *not* be marked volatile since otherwise - assignments like - pthread_descr self = thread_self(); - do not get optimized away. */ -#define THREAD_SELF \ -({ \ - register pthread_descr __self; \ - __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ - : "i" (offsetof (struct _pthread_descr_struct, \ - p_header.data.self))); \ - __self; \ -}) - - -/* Initialize the thread-unique value. Two possible ways to do it. */ - -#define DO_MODIFY_LDT(descr, nr) \ -({ \ - struct modify_ldt_ldt_s ldt_entry = \ - { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ - 1, 0, 0, 1, 0, 1, 0 }; \ - if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ - abort (); \ - __asm__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ -}) - -#ifdef __PIC__ -# define USETLS_EBX_ARG "r" -# define USETLS_LOAD_EBX "xchgl %3, %%ebx\n\t" -#else -# define USETLS_EBX_ARG "b" -# define USETLS_LOAD_EBX -#endif - -/* When using the new set_thread_area call, we don't need to change %gs - because we inherited the value set up in the main thread by TLS setup. - We need to extract that value and set up the same segment in this - thread. */ -#if USE_TLS -# define DO_SET_THREAD_AREA_REUSE(nr) 1 -#else -/* Without TLS, we do the initialization of the main thread, where NR == 0. */ -# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr)) -#endif -#define DO_SET_THREAD_AREA(descr, nr) \ -({ \ - int __gs; \ - if (DO_SET_THREAD_AREA_REUSE (nr)) \ - { \ - __asm__ ("movw %%gs, %w0" : "=q" (__gs)); \ - struct modify_ldt_ldt_s ldt_entry = \ - { (__gs & 0xffff) >> 3, \ - (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ - 1, 0, 0, 1, 0, 1, 0 }; \ - \ - int __result; \ - __asm__ (USETLS_LOAD_EBX \ - "movl %2, %%eax\n\t" \ - "int $0x80\n\t" \ - USETLS_LOAD_EBX \ - : "&a" (__result) \ - : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \ - if (__result == 0) \ - __asm__ ("movw %w0, %%gs" :: "q" (__gs)); \ - else \ - __gs = -1; \ - } \ - else \ - { \ - struct modify_ldt_ldt_s ldt_entry = \ - { -1, \ - (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ - 1, 0, 0, 1, 0, 1, 0 }; \ - int __result; \ - __asm__ (USETLS_LOAD_EBX \ - "movl %2, %%eax\n\t" \ - "int $0x80\n\t" \ - USETLS_LOAD_EBX \ - : "&a" (__result) \ - : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \ - if (__result == 0) \ - { \ - __gs = (ldt_entry.entry_number << 3) + 3; \ - __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ - } \ - else \ - __gs = -1; \ - } \ - __gs; \ -}) - -#if defined __ASSUME_SET_THREAD_AREA_SYSCALL -# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr) -#elif defined __NR_set_thread_area -# define INIT_THREAD_SELF(descr, nr) \ -({ \ - if (__builtin_expect (__have_no_set_thread_area, 0) \ - || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \ - && (__have_no_set_thread_area = 1))) \ - DO_MODIFY_LDT (descr, nr); \ -}) -/* Defined in pspinlock.c. */ -extern int __have_no_set_thread_area; -#else -# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr) -#endif - -/* Free resources associated with thread descriptor. */ -#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL -#define FREE_THREAD(descr, nr) do { } while (0) -#elif defined __NR_set_thread_area -#define FREE_THREAD(descr, nr) \ -{ \ - int __gs; \ - __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \ - if (__builtin_expect (__gs & 4, 0)) \ - { \ - struct modify_ldt_ldt_s ldt_entry = \ - { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ - __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ - } \ -} -#else -#define FREE_THREAD(descr, nr) \ -{ \ - struct modify_ldt_ldt_s ldt_entry = \ - { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ - __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ -} -#endif - -/* Read member of the thread descriptor directly. */ -#define THREAD_GETMEM(descr, member) \ -({ \ - __typeof__ (descr->member) __value; \ - if (sizeof (__value) == 1) \ - __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ - : "=q" (__value) \ - : "0" (0), \ - "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else if (sizeof (__value) == 4) \ - __asm__ __volatile__ ("movl %%gs:%P1,%0" \ - : "=r" (__value) \ - : "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else \ - { \ - if (sizeof (__value) != 8) \ - /* There should not be any value with a size other than 1, 4 or 8. */\ - abort (); \ - \ - __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ - "movl %%gs:%P2,%%edx" \ - : "=A" (__value) \ - : "i" (offsetof (struct _pthread_descr_struct, \ - member)), \ - "i" (offsetof (struct _pthread_descr_struct, \ - member) + 4)); \ - } \ - __value; \ -}) - -/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ -#define THREAD_GETMEM_NC(descr, member) \ -({ \ - __typeof__ (descr->member) __value; \ - if (sizeof (__value) == 1) \ - __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ - : "=q" (__value) \ - : "0" (0), \ - "r" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else if (sizeof (__value) == 4) \ - __asm__ __volatile__ ("movl %%gs:(%1),%0" \ - : "=r" (__value) \ - : "r" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else \ - { \ - if (sizeof (__value) != 8) \ - /* There should not be any value with a size other than 1, 4 or 8. */\ - abort (); \ - \ - __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ - "movl %%gs:4(%1),%%edx" \ - : "=&A" (__value) \ - : "r" (offsetof (struct _pthread_descr_struct, \ - member))); \ - } \ - __value; \ -}) - -/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ -#define THREAD_SETMEM(descr, member, value) \ -({ \ - __typeof__ (descr->member) __value = (value); \ - if (sizeof (__value) == 1) \ - __asm__ __volatile__ ("movb %0,%%gs:%P1" : \ - : "q" (__value), \ - "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else if (sizeof (__value) == 4) \ - __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ - : "r" (__value), \ - "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else \ - { \ - if (sizeof (__value) != 8) \ - /* There should not be any value with a size other than 1, 4 or 8. */\ - abort (); \ - \ - __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ - "movl %%edx,%%gs:%P2" : \ - : "A" (__value), \ - "i" (offsetof (struct _pthread_descr_struct, \ - member)), \ - "i" (offsetof (struct _pthread_descr_struct, \ - member) + 4)); \ - } \ -}) - -/* Set member of the thread descriptor directly. */ -#define THREAD_SETMEM_NC(descr, member, value) \ -({ \ - __typeof__ (descr->member) __value = (value); \ - if (sizeof (__value) == 1) \ - __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \ - : "q" (__value), \ - "r" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else if (sizeof (__value) == 4) \ - __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ - : "r" (__value), \ - "r" (offsetof (struct _pthread_descr_struct, \ - member))); \ - else \ - { \ - if (sizeof (__value) != 8) \ - /* There should not be any value with a size other than 1, 4 or 8. */\ - abort (); \ - \ - __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ - "movl %%edx,%%gs:4(%1)" : \ - : "A" (__value), \ - "r" (offsetof (struct _pthread_descr_struct, \ - member))); \ - } \ -}) -#endif - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* Maximum size of the stack if the rlimit is unlimited. */ -#define ARCH_STACK_MAX_SIZE 8*1024*1024 diff --git a/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h deleted file mode 100644 index f4c6be989..000000000 --- a/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - IA-64 version. - Copyright (C) 1999, 2000, 2002, 2003, 2004 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 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> -#include <ia64intrin.h> - -#include <sys/types.h> -extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, - size_t __child_stack_size, int __flags, void *__arg, ...); - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Make sure gcc doesn't try to be clever and move things around on - us. We need to use _exactly_ the address the user gave us, not some - alias that contains the same information. */ -#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) - -#ifndef ELF_MACHINE_NAME - -#define NEED_SEPARATE_REGISTER_STACK - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* Maximum size of the stack if the rlimit is unlimited. */ -#define ARCH_STACK_MAX_SIZE 32*1024*1024 - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. - r12 (sp) is the stack pointer. */ -#define CURRENT_STACK_FRAME stack_pointer -register char *stack_pointer __asm__ ("sp"); - - -/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ -struct _pthread_descr_struct; -register struct _pthread_descr_struct *__thread_self __asm__("r13"); - -/* Return the thread descriptor for the current thread. */ -#define THREAD_SELF __thread_self - -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) - - -/* Access to data in the thread descriptor is easy. */ -#define THREAD_GETMEM(descr, member) \ - ((void) sizeof (descr), THREAD_SELF->member) -#define THREAD_GETMEM_NC(descr, member) \ - ((void) sizeof (descr), THREAD_SELF->member) -#define THREAD_SETMEM(descr, member, value) \ - ((void) sizeof (descr), THREAD_SELF->member = (value)) -#define THREAD_SETMEM_NC(descr, member, value) \ - ((void) sizeof (descr), THREAD_SELF->member = (value)) - - -/* Memory barrier */ -#define MEMORY_BARRIER() __sync_synchronize () - - -#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS - -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - long int readval; - - __asm__ __volatile__ - ("mov ar.ccv=%4;;\n\t" - "cmpxchg8.acq %0=%1,%2,ar.ccv" - : "=r" (readval), "=m" (__atomic_fool_gcc (p)) - : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) - : "memory"); - return readval == oldval; -} - -PT_EI int -__compare_and_swap_with_release_semantics (long int *p, - long int oldval, - long int newval) -{ - long int readval; - - __asm__ __volatile__ - ("mov ar.ccv=%4;;\n\t" - "cmpxchg8.rel %0=%1,%2,ar.ccv" - : "=r" (readval), "=m" (__atomic_fool_gcc (p)) - : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) - : "memory"); - return readval == oldval; -} - -#endif /* ELF_MACHINE_NAME */ - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - long int ret; - - __asm__ __volatile__( - "xchg4 %0=%1,%2" - : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock)) - : "r"(1), "m"(__atomic_fool_gcc (spinlock)) - : "memory"); - - return ret; -} - -/* Indicate that we are looping. */ -#define BUSY_WAIT_NOP __asm__ ("hint @pause") - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/ia64/tls.h b/libpthread/linuxthreads.old/sysdeps/ia64/tls.h deleted file mode 100644 index a78f0ec7a..000000000 --- a/libpthread/linuxthreads.old/sysdeps/ia64/tls.h +++ /dev/null @@ -1,138 +0,0 @@ -/* Definitions for thread-local data handling. linuxthreads/IA-64 version. - Copyright (C) 2002, 2003, 2004, 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 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _TLS_H -#define _TLS_H - -#ifndef __ASSEMBLER__ - -# include <pt-machine.h> -# include <stdbool.h> -# include <stddef.h> - -/* Type for the dtv. */ -typedef union dtv -{ - size_t counter; - struct - { - void *val; - bool is_static; - } pointer; -} dtv_t; - -#else /* __ASSEMBLER__ */ -# include <tcb-offsets.h> -#endif /* __ASSEMBLER__ */ - -#ifdef HAVE_TLS_SUPPORT - -/* Signal that TLS support is available. */ -# define USE_TLS 1 - -# ifndef __ASSEMBLER__ - -typedef struct -{ - dtv_t *dtv; - void *private; -} tcbhead_t; - -/* This is the size of the initial TCB. */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) - -/* Alignment requirements for the initial TCB. */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) - -/* This is the size of the TCB. */ -# define TLS_TCB_SIZE sizeof (tcbhead_t) - -/* This is the size we need before TCB. */ -# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) - -/* Alignment requirements for the TCB. */ -# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) - -/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ -# define TLS_DTV_AT_TP 1 - -/* Install the dtv pointer. The pointer passed is to the element with - index -1 which contain the length. */ -# define INSTALL_DTV(tcbp, dtvp) \ - ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 - -/* Install new dtv for current thread. */ -# define INSTALL_NEW_DTV(DTV) \ - (((tcbhead_t *)__thread_self)->dtv = (DTV)) - -/* Return dtv of given thread descriptor. */ -# define GET_DTV(tcbp) \ - (((tcbhead_t *) (tcbp))->dtv) - -#if defined NEED_DL_SYSINFO -# define INIT_SYSINFO \ - (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo)) -#else -# define INIT_SYSINFO 0 -#endif - -/* Code to initially initialize the thread pointer. This might need - special attention since 'errno' is not yet available and if the - operation can cause a failure 'errno' must not be touched. */ -# define TLS_INIT_TP(tcbp, secondcall) \ - (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL) - -/* Return the address of the dtv for the current thread. */ -# define THREAD_DTV() \ - (((tcbhead_t *)__thread_self)->dtv) - -/* Return the thread descriptor for the current thread. */ -# undef THREAD_SELF -# define THREAD_SELF (__thread_self - 1) - -# undef INIT_THREAD_SELF -# define INIT_THREAD_SELF(descr, nr) \ - (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) - -# define TLS_MULTIPLE_THREADS_IN_TCB 1 - -# endif - -#else - -# ifndef __ASSEMBLER__ - -typedef struct -{ - void *tcb; - dtv_t *dtv; - void *self; - int multiple_threads; -} tcbhead_t; - -# define NONTLS_INIT_TP \ - do { \ - static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ - __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ - } while (0) - -#endif - -#endif /* USE_TLS */ - -#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h deleted file mode 100644 index 3be216524..000000000 --- a/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - m68k version. - Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - char ret; - - __asm__ __volatile__( -#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__m68000) - "tas %1; sne %0" -#else - "bset #7,%1; sne %0" -#endif - : "=&dm"(ret), "=m"(*spinlock) - : "m"(*spinlock) - : "cc"); - - return ret; -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("%sp"); - - -/* Compare-and-swap for semaphores. */ - -#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__mc68000) -#define HAS_COMPARE_AND_SWAP -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - char ret; - long int readval; - - __asm__ __volatile__ ("casl %2, %3, %1; seq %0" - : "=dm" (ret), "=m" (*p), "=d" (readval) - : "d" (newval), "m" (*p), "2" (oldval)); - - return ret; -} -#endif - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h deleted file mode 100644 index e8c03f9e5..000000000 --- a/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * sysdeps/microblaze/pt-machine.h -- microblaze-specific pthread definitions - * - * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au> - * Copyright (C) 2002 NEC Electronics Corporation - * Copyright (C) 2002 Miles Bader <miles@gnu.org> - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License. See the file COPYING.LIB in the main - * directory of this archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI extern inline -#endif - -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long *ptr, long old, long new); - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME __stack_pointer -register char *__stack_pointer __asm__ ("r1"); - -#define HAS_COMPARE_AND_SWAP -#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS -#define IMPLEMENT_TAS_WITH_CAS - -/* Atomically: If *PTR == OLD, set *PTR to NEW and return true, - otherwise do nothing and return false. */ -PT_EI int __compare_and_swap (long *ptr, long old, long new) -{ - unsigned long psw; - - /* disable interrupts */ - /* This is ugly ugly ugly! */ - __asm__ __volatile__ ("mfs %0, rmsr;" - "andi r3, %0, ~2;" - "mts rmsr, r3;" - : "=&r" (psw) - : - : "r3"); - - if (likely (*ptr == old)) - { - *ptr = new; - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); /* re-enable */ - return 1; - } - else - { - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); /* re-enable */ - return 0; - } -} - -/* like above's __compare_and_swap() but it first syncs the memory - (This is also the difference between both functions in e.g. - ../powerpc/pt-machine.h) - Doing this additional sync fixes a hang of __pthread_alt_unlock() - (Falk Brettschneider <fbrettschneider@baumeroptronic.de>) */ -PT_EI int -__compare_and_swap_with_release_semantics (long *p, - long oldval, long newval) -{ - __asm__ __volatile__ ("" : : : "memory"); /*MEMORY_BARRIER ();*/ - return __compare_and_swap (p, oldval, newval); -} - - -#ifndef IMPLEMENT_TAS_WITH_CAS -/* Spinlock implementation; required. */ -PT_EI long int testandset (int *spinlock) -{ - unsigned psw; - - /* disable interrupts */ - __asm__ __volatile__ ("mfs %0, rmsr;" - "andi r3, %0, ~2;" - "mts rmsr, r3;" - : "=&r" (psw) - : - : "r3"); - - if (*spinlock) - { - /* Enable ints */ - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); - return 1; - } else { - *spinlock=1; - /* Enable ints */ - __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); - return 0; - } -} - -#endif -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h b/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h deleted file mode 100644 index de450ff8a..000000000 --- a/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * sysdeps/v850/sigcontextinfo.h -- v850-specific pthread signal definitions - * - * Copyright (C) 2002 NEC Electronics Corporation - * Copyright (C) 2002 Miles Bader <miles@gnu.org> - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License. See the file COPYING.LIB in the main - * directory of this archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - */ - -#include <signal.h> - -#define SIGCONTEXT struct sigcontext * -#define SIGCONTEXT_EXTRA_ARGS diff --git a/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h deleted file mode 100644 index caaf9a7c0..000000000 --- a/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h +++ /dev/null @@ -1,105 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - - Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ralf Baechle <ralf@gnu.org>. - Based on the Alpha version by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 2000. */ -static __inline__ int -__NTH (_test_and_set (int *p, int v)) -{ - int r, t; - - __asm__ __volatile__ - ("/* Inline test and set */\n" - "1:\n\t" - ".set push\n\t" - ".set mips2\n\t" - "ll %0,%3\n\t" - "move %1,%4\n\t" - "beq %0,%4,2f\n\t" - "sc %1,%2\n\t" - ".set pop\n\t" - "beqz %1,1b\n" - "2:\n\t" - "/* End test and set */" - : "=&r" (r), "=&r" (t), "=m" (*p) - : "m" (*p), "r" (v) - : "memory"); - - return r; -} - - -/* Spinlock implementation; required. */ - -PT_EI long int -testandset (int *spinlock) -{ - return _test_and_set (spinlock, 1); -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("$29"); - - -/* Compare-and-swap for semaphores. */ - -#define HAS_COMPARE_AND_SWAP -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - long int ret, temp; - - __asm__ __volatile__ - ("/* Inline compare & swap */\n" - "1:\n\t" - ".set push\n\t" - ".set mips2\n\t" - "ll %1,%5\n\t" - "move %0,$0\n\t" - "bne %1,%3,2f\n\t" - "move %0,%4\n\t" - "sc %0,%2\n\t" - ".set pop\n\t" - "beqz %0,1b\n" - "2:\n\t" - "/* End compare & swap */" - : "=&r" (ret), "=&r" (temp), "=m" (*p) - : "r" (oldval), "r" (newval), "m" (*p) - : "memory"); - - return ret; -} - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h deleted file mode 100644 index 91bbf8fea..000000000 --- a/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - ARM version. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Philip Blundell <philb@gnu.org>. - - 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, - see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Spinlock implementation; required. */ -/* it is weird and dangerous to disable interrupt in userspace, but for nios - what else we can do before we have a swap like instruction? This is better - than nothing - */ -PT_EI long int -testandset (int *spinlock) -{ - unsigned int ret; - - __asm__ __volatile__("pfx 8\n\t" - "wrctl %1 ; disable interrupt\n\t" - "nop\n\t" - "nop\n\t" - "ld %0, [%2]\n\t" - "st [%2], %1\n\t" - "pfx 9\n\t" - "wrctl %1 ; enable interrupt\n\t" - "nop\n\t" - "nop\n\t" - : "=&r"(ret) - : "r"(1), "r"(spinlock) - : "memory"); - - return ret; -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("%sp"); - -/* nios needs more because of reg windows */ -#define THREAD_MANAGER_STACK_SIZE (32*1024) -#define STACK_SIZE (32*1024) - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h deleted file mode 100644 index e3260811b..000000000 --- a/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - nios2 version. - Copyright (C) 1996, 1998, 2000, 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 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - unsigned int scratch; - long int ret=-2; - - __asm__ __volatile__( - "rdctl %0, status\n\t" - "and %0, %0, %1\n\t" - "wrctl status, %0 #disable interrupts\n\t" - "ldw %1, 0(%4)\n\t" - "stw %3, 0(%4)\n\t" - "ori %0, %0, 1\n\t" - "wrctl status, %0 #enable interrupts\n\t" - : "=&r"(scratch), "=r"(ret) - : "1"(ret), "r"(1), "r"(spinlock) - : "memory"); - - return ret; -} - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("%sp"); - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h deleted file mode 100644 index aa2d206b0..000000000 --- a/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - powerpc version. - Copyright (C) 1996, 1997, 1998, 2000, 2001, 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 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor - User's Manual', by IBM and Motorola. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* For multiprocessor systems, we want to ensure all memory accesses - are completed before we reset a lock. On other systems, we still - need to make sure that the compiler has flushed everything to memory. */ -#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("r1"); - -/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ -struct _pthread_descr_struct; -register struct _pthread_descr_struct *__thread_self __asm__("r2"); - -/* Return the thread descriptor for the current thread. */ -#define THREAD_SELF __thread_self - -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) - -/* Compare-and-swap for semaphores. */ -/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ - -#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS -#define IMPLEMENT_TAS_WITH_CAS - -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - int ret; - - __asm__ __volatile__ ( - "0: lwarx %0,0,%1 ;" - " xor. %0,%3,%0;" - " bne 1f;" - " stwcx. %2,0,%1;" - " bne- 0b;" - "1: " - : "=&r"(ret) - : "r"(p), "r"(newval), "r"(oldval) - : "cr0", "memory"); - /* This version of __compare_and_swap is to be used when acquiring - a lock, so we don't need to worry about whether other memory - operations have completed, but we do need to be sure that any loads - after this point really occur after we have acquired the lock. */ - __asm__ __volatile__ ("isync" : : : "memory"); - return ret == 0; -} - -PT_EI int -__compare_and_swap_with_release_semantics (long int *p, - long int oldval, long int newval) -{ - int ret; - - MEMORY_BARRIER (); - __asm__ __volatile__ ( - "0: lwarx %0,0,%1 ;" - " xor. %0,%3,%0;" - " bne 1f;" - " stwcx. %2,0,%1;" - " bne- 0b;" - "1: " - : "=&r"(ret) - : "r"(p), "r"(newval), "r"(oldval) - : "cr0", "memory"); - return ret == 0; -} - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h b/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h deleted file mode 100644 index 8833e343d..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h +++ /dev/null @@ -1,415 +0,0 @@ -/* libc-internal interface for mutex locks. LinuxThreads version. - Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003 - 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 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _BITS_LIBC_LOCK_H -#define _BITS_LIBC_LOCK_H 1 - -#include <pthread.h> - -#if defined _LIBC && !defined NOT_IN_libc -#include <linuxthreads.old/internals.h> -#endif - -/* Mutex type. */ -#if defined(_LIBC) || defined(_IO_MTSAFE_IO) -typedef pthread_mutex_t __libc_lock_t; -typedef pthread_mutex_t __libc_lock_recursive_t; -# ifdef __USE_UNIX98 -typedef pthread_rwlock_t __libc_rwlock_t; -# else -typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; -# endif -typedef __libc_lock_recursive_t __rtld_lock_recursive_t; -#else -typedef struct __libc_lock_opaque__ __libc_lock_t; -typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; -typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; -#endif - -/* Type for key to thread-specific data. */ -typedef pthread_key_t __libc_key_t; - -/* Define a lock variable NAME with storage class CLASS. The lock must be - initialized with __libc_lock_init before it can be used (or define it - with __libc_lock_define_initialized, below). Use `extern' for CLASS to - declare a lock defined in another module. In public structure - definitions you must use a pointer to the lock structure (i.e., NAME - begins with a `*'), because its storage size will not be known outside - of libc. */ -#define __libc_lock_define(CLASS,NAME) \ - CLASS __libc_lock_t NAME; -#define __libc_rwlock_define(CLASS,NAME) \ - CLASS __libc_rwlock_t NAME; -#define __libc_lock_define_recursive(CLASS,NAME) \ - CLASS __libc_lock_recursive_t NAME; -#define __rtld_lock_define_recursive(CLASS,NAME) \ - CLASS __rtld_lock_recursive_t NAME; - -/* Define an initialized lock variable NAME with storage class CLASS. - - For the C library we take a deeper look at the initializer. For - this implementation all fields are initialized to zero. Therefore - we don't initialize the variable which allows putting it into the - BSS section. (Except on PA-RISC and other odd architectures, where - initialized locks must be set to one due to the lack of normal - atomic operations.) */ - -#if __LT_SPINLOCK_INIT == 0 -# define __libc_lock_define_initialized(CLASS,NAME) \ - CLASS __libc_lock_t NAME; -#else -# define __libc_lock_define_initialized(CLASS,NAME) \ - CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; -#endif - -#define __libc_rwlock_define_initialized(CLASS,NAME) \ - CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; - -/* Define an initialized recursive lock variable NAME with storage - class CLASS. */ -#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ - CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; -#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ - {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} - -#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ - CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; -#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ - {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} - -#if defined _LIBC && defined IS_IN_libpthread -# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS -#else -# if defined __PIC__ || (defined _LIBC && defined SHARED) -# define __libc_maybe_call(FUNC, ARGS, ELSE) \ - (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ - _fn != NULL ? (*_fn) ARGS : ELSE; })) -# else -# define __libc_maybe_call(FUNC, ARGS, ELSE) \ - (FUNC != NULL ? FUNC ARGS : ELSE) -# endif -#endif -#if defined _LIBC && !defined NOT_IN_libc && defined SHARED -# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ - ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ - ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) -#else -# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) -#endif - -/* Initialize the named lock variable, leaving it in a consistent, unlocked - state. */ -#if defined _LIBC && !defined NOT_IN_libc && defined SHARED -#define __libc_lock_init(NAME) \ - ({ \ - (NAME).__m_count = 0; \ - (NAME).__m_owner = NULL; \ - (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ - (NAME).__m_lock.__status = 0; \ - (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ - 0; }) -#else -#define __libc_lock_init(NAME) \ - (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) -#endif -#define __libc_rwlock_init(NAME) \ - (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); - -/* Same as last but this time we initialize an adaptive mutex. */ -#if defined _LIBC && !defined NOT_IN_libc && defined SHARED -#define __libc_lock_init_adaptive(NAME) \ - ({ \ - (NAME).__m_count = 0; \ - (NAME).__m_owner = NULL; \ - (NAME).__m_kind = PTHREAD_MUTEX_ADAPTIVE_NP; \ - (NAME).__m_lock.__status = 0; \ - (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ - 0; }) -#else -#define __libc_lock_init_adaptive(NAME) \ - do { \ - if (__pthread_mutex_init != NULL) \ - { \ - pthread_mutexattr_t __attr; \ - __pthread_mutexattr_init (&__attr); \ - __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_ADAPTIVE_NP); \ - __pthread_mutex_init (&(NAME), &__attr); \ - __pthread_mutexattr_destroy (&__attr); \ - } \ - } while (0); -#endif - -/* Same as last but this time we initialize a recursive mutex. */ -#if defined _LIBC && !defined NOT_IN_libc && defined SHARED -#define __libc_lock_init_recursive(NAME) \ - ({ \ - (NAME).__m_count = 0; \ - (NAME).__m_owner = NULL; \ - (NAME).__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ - (NAME).__m_lock.__status = 0; \ - (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ - 0; }) -#else -#define __libc_lock_init_recursive(NAME) \ - do { \ - if (__pthread_mutex_init != NULL) \ - { \ - pthread_mutexattr_t __attr; \ - __pthread_mutexattr_init (&__attr); \ - __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ - __pthread_mutex_init (&(NAME), &__attr); \ - __pthread_mutexattr_destroy (&__attr); \ - } \ - } while (0); -#endif -#define __rtld_lock_init_recursive(NAME) \ - __libc_lock_init_recursive (NAME) - -/* Finalize the named lock variable, which must be locked. It cannot be - used again until __libc_lock_init is called again on it. This must be - called on a lock variable before the containing storage is reused. */ -#define __libc_lock_fini(NAME) \ - (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); -#define __libc_rwlock_fini(NAME) \ - (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); - -/* Finalize recursive named lock. */ -#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) -#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) - -/* Lock the named lock variable. */ -#define __libc_lock_lock(NAME) \ - (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); -#define __libc_rwlock_rdlock(NAME) \ - (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); -#define __libc_rwlock_wrlock(NAME) \ - (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); - -/* Lock the recursive named lock variable. */ -#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) - -/* Try to lock the named lock variable. */ -#define __libc_lock_trylock(NAME) \ - (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) -#define __libc_rwlock_tryrdlock(NAME) \ - (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) -#define __libc_rwlock_trywrlock(NAME) \ - (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) - -/* Try to lock the recursive named lock variable. */ -#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) -#define __rtld_lock_trylock_recursive(NAME) \ - __libc_lock_trylock_recursive (NAME) - -/* Unlock the named lock variable. */ -#define __libc_lock_unlock(NAME) \ - (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); -#define __libc_rwlock_unlock(NAME) \ - (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); - -/* Unlock the recursive named lock variable. */ -#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) - -/* Define once control variable. */ -#if PTHREAD_ONCE_INIT == 0 -/* Special case for static variables where we can avoid the initialization - if it is zero. */ -# define __libc_once_define(CLASS, NAME) \ - CLASS pthread_once_t NAME -#else -# define __libc_once_define(CLASS, NAME) \ - CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT -#endif - -/* Call handler iff the first call. */ -#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ - do { \ - if (__pthread_once != NULL) \ - __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ - else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ - INIT_FUNCTION (); \ - (ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \ - } \ - } while (0) - - -/* Start critical region with cleanup. */ -#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ - { struct _pthread_cleanup_buffer _buffer; \ - int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ - if (_avail) { \ - _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ - } - -/* End critical region with cleanup. */ -#define __libc_cleanup_region_end(DOIT) \ - if (_avail) { \ - _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ - } \ - } - -/* Sometimes we have to exit the block in the middle. */ -#define __libc_cleanup_end(DOIT) \ - if (_avail) { \ - _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ - } - -#if 0 -#define __libc_cleanup_push(fct, arg) \ - { struct _pthread_cleanup_buffer _buffer; \ - __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) - -#define __libc_cleanup_pop(execute) \ - __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ - } -#endif - -/* Create thread-specific key. */ -#define __libc_key_create(KEY, DESTRUCTOR) \ - (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) - -/* Get thread-specific data. */ -#define __libc_getspecific(KEY) \ - (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) - -/* Set thread-specific data. */ -#define __libc_setspecific(KEY, VALUE) \ - (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) - - -/* Register handlers to execute before and after `fork'. */ -#define __libc_atfork(PREPARE, PARENT, CHILD) \ - (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) - -/* Functions that are used by this file and are internal to the GNU C - library. */ - -extern int __pthread_mutex_init (pthread_mutex_t *__mutex, - const pthread_mutexattr_t *__mutex_attr); - -extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); - -extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); - -extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); - -extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); - -extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); - -extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); - -extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, - int __kind); - -#ifdef __USE_UNIX98 -extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, - const pthread_rwlockattr_t *__attr); - -extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); - -extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); - -extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); - -extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); - -extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); - -extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); -#endif - -extern int __pthread_key_create (pthread_key_t *__key, - void (*__destr_function) (void *)); - -extern int __pthread_setspecific (pthread_key_t __key, - const void *__pointer); - -extern void *__pthread_getspecific (pthread_key_t __key); - -extern int __pthread_once (pthread_once_t *__once_control, - void (*__init_routine) (void)); - -extern int __pthread_atfork (void (*__prepare) (void), - void (*__parent) (void), - void (*__child) (void)); - - - -/* Make the pthread functions weak so that we can elide them from - single-threaded processes. */ -#ifndef __NO_WEAK_PTHREAD_ALIASES -# ifdef weak_extern -# define BP_SYM(sym) sym -weak_extern (BP_SYM (__pthread_mutex_init)) -weak_extern (BP_SYM (__pthread_mutex_destroy)) -weak_extern (BP_SYM (__pthread_mutex_lock)) -weak_extern (BP_SYM (__pthread_mutex_trylock)) -weak_extern (BP_SYM (__pthread_mutex_unlock)) -weak_extern (BP_SYM (__pthread_mutexattr_init)) -weak_extern (BP_SYM (__pthread_mutexattr_destroy)) -weak_extern (BP_SYM (__pthread_mutexattr_settype)) -weak_extern (BP_SYM (__pthread_rwlock_init)) -weak_extern (BP_SYM (__pthread_rwlock_destroy)) -weak_extern (BP_SYM (__pthread_rwlock_rdlock)) -weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) -weak_extern (BP_SYM (__pthread_rwlock_wrlock)) -weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) -weak_extern (BP_SYM (__pthread_rwlock_unlock)) -weak_extern (BP_SYM (__pthread_key_create)) -weak_extern (BP_SYM (__pthread_setspecific)) -weak_extern (BP_SYM (__pthread_getspecific)) -weak_extern (BP_SYM (__pthread_once)) -weak_extern (__pthread_atfork) -weak_extern (BP_SYM (_pthread_cleanup_push)) -weak_extern (BP_SYM (_pthread_cleanup_pop)) -weak_extern (BP_SYM (_pthread_cleanup_push_defer)) -weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) -# else -# pragma weak __pthread_mutex_init -# pragma weak __pthread_mutex_destroy -# pragma weak __pthread_mutex_lock -# pragma weak __pthread_mutex_trylock -# pragma weak __pthread_mutex_unlock -# pragma weak __pthread_mutexattr_init -# pragma weak __pthread_mutexattr_destroy -# pragma weak __pthread_mutexattr_settype -# pragma weak __pthread_rwlock_destroy -# pragma weak __pthread_rwlock_rdlock -# pragma weak __pthread_rwlock_tryrdlock -# pragma weak __pthread_rwlock_wrlock -# pragma weak __pthread_rwlock_trywrlock -# pragma weak __pthread_rwlock_unlock -# pragma weak __pthread_key_create -# pragma weak __pthread_setspecific -# pragma weak __pthread_getspecific -# pragma weak __pthread_once -# pragma weak __pthread_atfork -# pragma weak _pthread_cleanup_push_defer -# pragma weak _pthread_cleanup_pop_restore -# pragma weak _pthread_cleanup_push -# pragma weak _pthread_cleanup_pop -# endif -#endif - -/* We need portable names for some functions. E.g., when they are - used as argument to __libc_cleanup_region_start. */ -#define __libc_mutex_unlock __pthread_mutex_unlock - -#endif /* bits/libc-lock.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h b/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h deleted file mode 100644 index 97af75ebf..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h +++ /dev/null @@ -1,69 +0,0 @@ -/* libc-internal interface for thread-specific data. LinuxThreads version. - Copyright (C) 1997-2002, 2003 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 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _BITS_LIBC_TSD_H -#define _BITS_LIBC_TSD_H 1 - -/* Fast thread-specific data internal to libc. */ -enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, - _LIBC_TSD_KEY_DL_ERROR, - _LIBC_TSD_KEY_RPC_VARS, - _LIBC_TSD_KEY_LOCALE, - _LIBC_TSD_KEY_CTYPE_B, - _LIBC_TSD_KEY_CTYPE_TOLOWER, - _LIBC_TSD_KEY_CTYPE_TOUPPER, - _LIBC_TSD_KEY_N }; - -#include <features.h> -#include <linuxthreads.old/internals.h> - -#ifdef __UCLIBC_HAS_TLS__ -#include <tls.h> - -/* When __thread works, the generic definition is what we want. */ -# include <sysdeps/generic/bits/libc-tsd.h> - -#else - -# include <bits/libc-lock.h> - -# ifndef SHARED -extern void ** __pthread_internal_tsd_address (int); -extern void *__pthread_internal_tsd_get (int); -extern int __pthread_internal_tsd_set (int, const void *); - -weak_extern (__pthread_internal_tsd_address) -weak_extern (__pthread_internal_tsd_get) -weak_extern (__pthread_internal_tsd_set) -# endif - -#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; -#define __libc_tsd_address(KEY) \ - __libc_maybe_call2 (pthread_internal_tsd_address, \ - (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data) -#define __libc_tsd_get(KEY) \ - __libc_maybe_call2 (pthread_internal_tsd_get, \ - (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data) -#define __libc_tsd_set(KEY, VALUE) \ - __libc_maybe_call2 (pthread_internal_tsd_set, \ - (_LIBC_TSD_KEY_##KEY, (VALUE)), \ - (__libc_tsd_##KEY##_data = (VALUE), 0)) - -#endif - -#endif /* bits/libc-tsd.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h b/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h deleted file mode 100644 index 3eb592919..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -#if !defined _BITS_TYPES_H && !defined _PTHREAD_H -# error "Never include <bits/pthreadtypes.h> directly; use <sys/types.h> instead." -#endif - -#ifndef _BITS_PTHREADTYPES_H -#define _BITS_PTHREADTYPES_H 1 - -#define __need_size_t -#include <stddef.h> - -#define __need_schedparam -#include <bits/sched.h> - -/* 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 */ - int __spinlock; /* Used by compare_and_swap emulation. Also, - adaptive SMP lock stores spin count here. */ -}; - -#ifndef _PTHREAD_DESCR_DEFINED -/* Thread descriptors */ -typedef struct _pthread_descr_struct *_pthread_descr; -# define _PTHREAD_DESCR_DEFINED -#endif - - -/* Attributes for threads. */ -typedef struct __pthread_attr_s -{ - int __detachstate; - int __schedpolicy; - struct __sched_param __schedparam; - int __inheritsched; - int __scope; - size_t __guardsize; - int __stackaddr_set; - void *__stackaddr; - size_t __stacksize; -} pthread_attr_t; - - -/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ -typedef struct -{ - struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ - _pthread_descr __c_waiting; /* Threads waiting on this condition */ -} pthread_cond_t; - - -/* Attribute for conditionally variables. */ -typedef struct -{ - int __dummy; -} pthread_condattr_t; - -/* Keys for thread-specific data */ -typedef unsigned int pthread_key_t; - - -/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ -/* (The layout is unnatural to maintain binary compatibility - with earlier releases of LinuxThreads.) */ -typedef struct -{ - int __m_reserved; /* Reserved for future use */ - int __m_count; /* Depth of recursive locking */ - _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ - int __m_kind; /* Mutex kind: fast, recursive or errcheck */ - struct _pthread_fastlock __m_lock; /* Underlying fast lock */ -} pthread_mutex_t; - - -/* Attribute for mutex. */ -typedef struct -{ - int __mutexkind; -} pthread_mutexattr_t; - - -/* Once-only execution */ -typedef int pthread_once_t; - - -#if defined __USE_UNIX98 || defined __USE_XOPEN2K -/* Read-write locks. */ -typedef struct _pthread_rwlock_t -{ - struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ - int __rw_readers; /* Number of readers */ - _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ - _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ - _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ - int __rw_kind; /* Reader/Writer preference selection */ - int __rw_pshared; /* Shared between processes or not */ -} pthread_rwlock_t; - - -/* Attribute for read-write locks. */ -typedef struct -{ - int __lockkind; - int __pshared; -} pthread_rwlockattr_t; -#endif - -#ifdef __USE_XOPEN2K -/* POSIX spinlock data type. */ -typedef volatile int pthread_spinlock_t; - -/* POSIX barrier. */ -typedef struct { - struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ - int __ba_required; /* Threads needed for completion */ - int __ba_present; /* Threads waiting */ - _pthread_descr __ba_waiting; /* Queue of waiting threads */ -} pthread_barrier_t; - -/* barrier attribute */ -typedef struct { - int __pshared; -} pthread_barrierattr_t; - -#endif - - -/* Thread identifiers */ -typedef unsigned long int pthread_t; - -#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h b/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h deleted file mode 100644 index bbdb0739c..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Uncancelable versions of cancelable interfaces. Linux version. - Copyright (C) 2003, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. - - 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, see - <http://www.gnu.org/licenses/>. */ - -#include <sys/types.h> -#include <sysdep.h> - -/* Uncancelable open. */ -#if defined __NR_openat && !defined __NR_open -#define open_not_cancel(name, flags, mode) \ - INLINE_SYSCALL (openat, 4, AT_FDCWD, (const char *) (name), \ - (flags), (mode)) -#define open_not_cancel_2(name, flags) \ - INLINE_SYSCALL (openat, 3, AT_FDCWD, (const char *) (name), \ - (flags)) -#else -#define open_not_cancel(name, flags, mode) \ - INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) -#define open_not_cancel_2(name, flags) \ - INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) -#endif - -/* Uncancelable openat. */ -#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt -extern int __openat_nocancel (int fd, const char *fname, int oflag, - mode_t mode) attribute_hidden; -extern int __openat64_nocancel (int fd, const char *fname, int oflag, - mode_t mode) attribute_hidden; -#else -# define __openat_nocancel(fd, fname, oflag, mode) \ - openat (fd, fname, oflag, mode) -# define __openat64_nocancel(fd, fname, oflag, mode) \ - openat64 (fd, fname, oflag, mode) -#endif - -#define openat_not_cancel(fd, fname, oflag, mode) \ - __openat_nocancel (fd, fname, oflag, mode) -#define openat_not_cancel_3(fd, fname, oflag) \ - __openat_nocancel (fd, fname, oflag, 0) -#define openat64_not_cancel(fd, fname, oflag, mode) \ - __openat64_nocancel (fd, fname, oflag, mode) -#define openat64_not_cancel_3(fd, fname, oflag) \ - __openat64_nocancel (fd, fname, oflag, 0) - -/* Uncancelable close. */ -#define close_not_cancel(fd) \ - INLINE_SYSCALL (close, 1, fd) -#define close_not_cancel_no_status(fd) \ - (void) ({ INTERNAL_SYSCALL_DECL (err); \ - INTERNAL_SYSCALL (close, err, 1, (fd)); }) - -/* Uncancelable read. */ -#define read_not_cancel(fd, buf, n) \ - INLINE_SYSCALL (read, 3, (fd), (buf), (n)) - -/* Uncancelable write. */ -#define write_not_cancel(fd, buf, n) \ - INLINE_SYSCALL (write, 3, (fd), (buf), (n)) - -/* Uncancelable writev. */ -#define writev_not_cancel_no_status(fd, iov, n) \ - (void) ({ INTERNAL_SYSCALL_DECL (err); \ - INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) - -/* Uncancelable fcntl. */ -#define fcntl_not_cancel(fd, cmd, val) \ - __fcntl_nocancel (fd, cmd, val) - -/* Uncancelable waitpid. */ -#ifdef __NR_waitpid -# define waitpid_not_cancel(pid, stat_loc, options) \ - INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) -#else -# define waitpid_not_cancel(pid, stat_loc, options) \ - INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) -#endif - -/* Uncancelable pause. */ -#ifdef __NR_pause -# define pause_not_cancel() \ - INLINE_SYSCALL (pause, 0) -#else -# define pause_not_cancel() \ - __pause_nocancel () -#endif - -/* Uncancelable nanosleep. */ -#ifdef __NR_nanosleep -# define nanosleep_not_cancel(requested_time, remaining) \ - INLINE_SYSCALL (nanosleep, 2, requested_time, remaining) -#else -# define nanosleep_not_cancel(requested_time, remaining) \ - __nanosleep_nocancel (requested_time, remaining) -#endif - -/* Uncancelable sigsuspend. */ -#define sigsuspend_not_cancel(set) \ - __sigsuspend_nocancel (set) diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h b/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h deleted file mode 100644 index 2afaa52e8..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. - - 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _PTHREAD_FUNCTIONS_H -#define _PTHREAD_FUNCTIONS_H 1 - -#include <pthread.h> -#if 0 -#include <setjmp.h> -#include <linuxthreads.old/internals.h> - -struct fork_block; -#endif - -/* Data type shared with libc. The libc uses it to pass on calls to - the thread functions. Wine pokes directly into this structure, - so if possible avoid breaking it and append new hooks to the end. */ -struct pthread_functions -{ -#if 0 - pid_t (*ptr_pthread_fork) (struct fork_block *); -#endif - int (*ptr_pthread_attr_destroy) (pthread_attr_t *); - int (*ptr_pthread_attr_init) (pthread_attr_t *); - int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); - int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); - int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); - int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); - int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, - struct sched_param *); - int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, - const struct sched_param *); - int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); - int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); - int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); - int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); - int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); - int (*ptr_pthread_condattr_init) (pthread_condattr_t *); - int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); - int (*ptr_pthread_cond_destroy) (pthread_cond_t *); - int (*ptr_pthread_cond_init) (pthread_cond_t *, - const pthread_condattr_t *); - int (*ptr_pthread_cond_signal) (pthread_cond_t *); - int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); - int (*ptr_pthread_equal) (pthread_t, pthread_t); - void (*ptr___pthread_exit) (void *); - int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); - int (*ptr_pthread_setschedparam) (pthread_t, int, - const struct sched_param *); - int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); - int (*ptr_pthread_mutex_init) (pthread_mutex_t *, - const pthread_mutexattr_t *); - int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); - int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); - int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); - pthread_t (*ptr_pthread_self) (void); - int (*ptr_pthread_setcancelstate) (int, int *); - int (*ptr_pthread_setcanceltype) (int, int *); -#if 0 - void (*ptr_pthread_do_exit) (void *retval, char *currentframe); - void (*ptr_pthread_cleanup_upto) (__jmp_buf target, - char *targetframe); - pthread_descr (*ptr_pthread_thread_self) (void); -#endif -#if !defined __UCLIBC_HAS_TLS__ && defined __UCLIBC_HAS_RPC__ - int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); - void * (*ptr_pthread_internal_tsd_get) (int key); - void ** __attribute__ ((__const__)) - (*ptr_pthread_internal_tsd_address) (int key); -#endif -#if 0 - int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, - struct sigaction *oact); - int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); - int (*ptr_pthread_raise) (int sig); -#endif - int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, - const struct timespec *); -#if 0 - void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, - void (*routine)(void *), void * arg); -#endif - void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer, - void (*routine)(void *), void * arg); -#if 0 - void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, - int execute); -#endif - void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer, - int execute); -}; - -/* Variable in libc.so. */ -extern struct pthread_functions __libc_pthread_functions attribute_hidden; - -extern int * __libc_pthread_init (const struct pthread_functions *functions); - -#endif /* pthread-functions.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h b/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h deleted file mode 100644 index 46c1010c6..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h +++ /dev/null @@ -1,710 +0,0 @@ -/* Linuxthreads - a simple clone()-based implementation of Posix */ -/* threads for Linux. */ -/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ -/* */ -/* This program 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. */ -/* */ -/* This program 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. */ - -#ifndef _PTHREAD_H -#define _PTHREAD_H 1 - -#include <features.h> - -#include <sched.h> -#include <time.h> - -#define __need_sigset_t -#include <signal.h> -#include <bits/pthreadtypes.h> -#include <bits/initspin.h> - - -__BEGIN_DECLS - -/* Initializers. */ - -#define PTHREAD_MUTEX_INITIALIZER \ - {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} -#ifdef __USE_GNU -# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ - {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} -# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ - {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} -# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ - {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} -#endif - -#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0} - -#if defined __USE_UNIX98 || defined __USE_XOPEN2K -# define PTHREAD_RWLOCK_INITIALIZER \ - { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ - PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } -#endif -#ifdef __USE_GNU -# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ - { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } -#endif - -/* Values for attributes. */ - -enum -{ - PTHREAD_CREATE_JOINABLE, -#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE - PTHREAD_CREATE_DETACHED -#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED -}; - -enum -{ - PTHREAD_INHERIT_SCHED, -#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED - PTHREAD_EXPLICIT_SCHED -#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED -}; - -enum -{ - PTHREAD_SCOPE_SYSTEM, -#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM - PTHREAD_SCOPE_PROCESS -#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS -}; - -enum -{ - PTHREAD_MUTEX_ADAPTIVE_NP, - PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_TIMED_NP -#ifdef __USE_UNIX98 - , - PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_ADAPTIVE_NP, - PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, - PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, - PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL -#endif -#ifdef __USE_GNU - /* For compatibility. */ - , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP -#endif -}; - -enum -{ - PTHREAD_PROCESS_PRIVATE, -#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE - PTHREAD_PROCESS_SHARED -#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED -}; - -#if defined __USE_UNIX98 || defined __USE_XOPEN2K -enum -{ - PTHREAD_RWLOCK_PREFER_READER_NP, - PTHREAD_RWLOCK_PREFER_WRITER_NP, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, - PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP -}; -#endif /* Unix98 */ - -#define PTHREAD_ONCE_INIT 0 - -/* Special constants */ - -#ifdef __USE_XOPEN2K -/* -1 is distinct from 0 and all errno constants */ -# define PTHREAD_BARRIER_SERIAL_THREAD -1 -#endif - -/* Cleanup buffers */ - -struct _pthread_cleanup_buffer -{ - void (*__routine) (void *); /* Function to call. */ - void *__arg; /* Its argument. */ - int __canceltype; /* Saved cancellation type. */ - struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ -}; - -/* Cancellation */ - -enum -{ - PTHREAD_CANCEL_ENABLE, -#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE - PTHREAD_CANCEL_DISABLE -#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE -}; -enum -{ - PTHREAD_CANCEL_DEFERRED, -#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED - PTHREAD_CANCEL_ASYNCHRONOUS -#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS -}; -#define PTHREAD_CANCELED ((void *) -1) - - -/* Function for handling threads. */ - -/* Create a thread with given attributes ATTR (or default attributes - if ATTR is NULL), and call function START_ROUTINE with given - arguments ARG. */ -extern int pthread_create (pthread_t *__restrict __threadp, - const pthread_attr_t *__restrict __attr, - void *(*__start_routine) (void *), - void *__restrict __arg) __THROW; - -/* Obtain the identifier of the current thread. */ -extern pthread_t pthread_self (void) __THROW; - -/* Compare two thread identifiers. */ -extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; - -/* Terminate calling thread. */ -extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); - -/* Make calling thread wait for termination of the thread TH. The - exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN - is not NULL. */ -extern int pthread_join (pthread_t __th, void **__thread_return); - -/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. - The resources of TH will therefore be freed immediately when it - terminates, instead of waiting for another thread to perform PTHREAD_JOIN - on it. */ -extern int pthread_detach (pthread_t __th) __THROW; - - -/* Functions for handling attributes. */ - -/* Initialize thread attribute *ATTR with default attributes - (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, - no user-provided stack). */ -extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; - -/* Destroy thread attribute *ATTR. */ -extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; - -/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ -extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, - int __detachstate) __THROW; - -/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ -extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr, - int *__detachstate) __THROW; - -/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ -extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, - const struct sched_param *__restrict - __param) __THROW; - -/* Return in *PARAM the scheduling parameters of *ATTR. */ -extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict - __attr, - struct sched_param *__restrict __param) - __THROW; - -/* Set scheduling policy in *ATTR according to POLICY. */ -extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) - __THROW; - -/* Return in *POLICY the scheduling policy of *ATTR. */ -extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict - __attr, int *__restrict __policy) - __THROW; - -/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ -extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, - int __inherit) __THROW; - -/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ -extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict - __attr, int *__restrict __inherit) - __THROW; - -/* Set scheduling contention scope in *ATTR according to SCOPE. */ -extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) - __THROW; - -/* Return in *SCOPE the scheduling contention scope of *ATTR. */ -extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr, - int *__restrict __scope) __THROW; - -#ifdef __USE_UNIX98 -/* Set the size of the guard area at the bottom of the thread. */ -extern int pthread_attr_setguardsize (pthread_attr_t *__attr, - size_t __guardsize) __THROW; - -/* Get the size of the guard area at the bottom of the thread. */ -extern int pthread_attr_getguardsize (const pthread_attr_t *__restrict - __attr, size_t *__restrict __guardsize) - __THROW; -#endif - -#if 0 /* uClibc: deprecated stuff disabled. def __UCLIBC_SUSV3_LEGACY__ */ -/* Set the starting address of the stack of the thread to be created. - Depending on whether the stack grows up or down the value must either - be higher or lower than all the address in the memory block. The - minimal size of the block must be PTHREAD_STACK_SIZE. */ -extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, - void *__stackaddr) __THROW; - -/* Return the previously set address for the stack. */ -extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict - __attr, void **__restrict __stackaddr) - __THROW; -#endif - -#ifdef __USE_XOPEN2K -/* The following two interfaces are intended to replace the last two. They - require setting the address as well as the size since only setting the - address will make the implementation on some architectures impossible. */ -extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, - size_t __stacksize) __THROW; - -/* Return the previously set address for the stack. */ -extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr, - void **__restrict __stackaddr, - size_t *__restrict __stacksize) __THROW; -#endif - -/* Add information about the minimum stack size needed for the thread - to be started. This size must never be less than PTHREAD_STACK_SIZE - and must also not exceed the system limits. */ -extern int pthread_attr_setstacksize (pthread_attr_t *__attr, - size_t __stacksize) __THROW; - -/* Return the currently used minimal stack size. */ -extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict - __attr, size_t *__restrict __stacksize) - __THROW; - -#if 0 -/* Not yet implemented in uClibc! */ - -#ifdef __USE_GNU -/* Initialize thread attribute *ATTR with attributes corresponding to the - already running thread TH. It shall be called on uninitialized ATTR - and destroyed with pthread_attr_destroy when no longer needed. */ -extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; -#endif -#endif - -/* Functions for scheduling control. */ - -/* Set the scheduling parameters for TARGET_THREAD according to POLICY - and *PARAM. */ -extern int pthread_setschedparam (pthread_t __target_thread, int __policy, - const struct sched_param *__param) - __THROW; - -/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ -extern int pthread_getschedparam (pthread_t __target_thread, - int *__restrict __policy, - struct sched_param *__restrict __param) - __THROW; - -#ifdef __USE_UNIX98 -/* Determine level of concurrency. */ -extern int pthread_getconcurrency (void) __THROW; - -/* Set new concurrency level to LEVEL. */ -extern int pthread_setconcurrency (int __level) __THROW; -#endif - -#ifdef __USE_GNU -/* Same thing, different name */ -#define pthread_yield() sched_yield() -#endif - -/* Functions for mutex handling. */ - -/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the - default values if later is NULL. */ -extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, - const pthread_mutexattr_t *__restrict - __mutex_attr) __THROW; - -/* Destroy MUTEX. */ -extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; - -/* Try to lock MUTEX. */ -extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; - -/* Wait until lock for MUTEX becomes available and lock it. */ -extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; - -#ifdef __USE_XOPEN2K -/* Wait until lock becomes available, or specified time passes. */ -extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, - const struct timespec *__restrict - __abstime) __THROW; -#endif - -/* Unlock MUTEX. */ -extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; - - -/* Functions for handling mutex attributes. */ - -/* Initialize mutex attribute object ATTR with default attributes - (kind is PTHREAD_MUTEX_TIMED_NP). */ -extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; - -/* Destroy mutex attribute object ATTR. */ -extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; - -/* Get the process-shared flag of the mutex attribute ATTR. */ -extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t * - __restrict __attr, - int *__restrict __pshared) __THROW; - -/* Set the process-shared flag of the mutex attribute ATTR. */ -extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, - int __pshared) __THROW; - -#ifdef __USE_UNIX98 -/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, - PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or - PTHREAD_MUTEX_DEFAULT). */ -extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) - __THROW; - -/* Return in *KIND the mutex kind attribute in *ATTR. */ -extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict - __attr, int *__restrict __kind) __THROW; -#endif - - -/* Functions for handling conditional variables. */ - -/* Initialize condition variable COND using attributes ATTR, or use - the default values if later is NULL. */ -extern int pthread_cond_init (pthread_cond_t *__restrict __cond, - const pthread_condattr_t *__restrict - __cond_attr) __THROW; -libpthread_hidden_proto(pthread_cond_init) - -/* Destroy condition variable COND. */ -extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; -libpthread_hidden_proto(pthread_cond_destroy) - -/* Wake up one thread waiting for condition variable COND. */ -extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; -libpthread_hidden_proto(pthread_cond_signal) - -/* Wake up all threads waiting for condition variables COND. */ -extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; -libpthread_hidden_proto(pthread_cond_broadcast) - -/* Wait for condition variable COND to be signaled or broadcast. - MUTEX is assumed to be locked before. */ -extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, - pthread_mutex_t *__restrict __mutex); -libpthread_hidden_proto(pthread_cond_wait) - -/* Wait for condition variable COND to be signaled or broadcast until - ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an - absolute time specification; zero is the beginning of the epoch - (00:00:00 GMT, January 1, 1970). */ -extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, - pthread_mutex_t *__restrict __mutex, - const struct timespec *__restrict - __abstime); -libpthread_hidden_proto(pthread_cond_timedwait) - -/* Functions for handling condition variable attributes. */ - -/* Initialize condition variable attribute ATTR. */ -extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; -libpthread_hidden_proto(pthread_condattr_init) - -/* Destroy condition variable attribute ATTR. */ -extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; -libpthread_hidden_proto(pthread_condattr_destroy) - -/* Get the process-shared flag of the condition variable attribute ATTR. */ -extern int pthread_condattr_getpshared (const pthread_condattr_t * - __restrict __attr, - int *__restrict __pshared) __THROW; - -/* Set the process-shared flag of the condition variable attribute ATTR. */ -extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, - int __pshared) __THROW; - - -#if defined __USE_UNIX98 || defined __USE_XOPEN2K -/* Functions for handling read-write locks. */ - -/* Initialize read-write lock RWLOCK using attributes ATTR, or use - the default values if later is NULL. */ -extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, - const pthread_rwlockattr_t *__restrict - __attr) __THROW; - -/* Destroy read-write lock RWLOCK. */ -extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; - -/* Acquire read lock for RWLOCK. */ -extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; - -/* Try to acquire read lock for RWLOCK. */ -extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; - -# ifdef __USE_XOPEN2K -/* Try to acquire read lock for RWLOCK or return after specfied time. */ -extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, - const struct timespec *__restrict - __abstime) __THROW; -# endif - -/* Acquire write lock for RWLOCK. */ -extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; - -/* Try to acquire write lock for RWLOCK. */ -extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; - -# ifdef __USE_XOPEN2K -/* Try to acquire write lock for RWLOCK or return after specfied time. */ -extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, - const struct timespec *__restrict - __abstime) __THROW; -# endif - -/* Unlock RWLOCK. */ -extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; - - -/* Functions for handling read-write lock attributes. */ - -/* Initialize attribute object ATTR with default values. */ -extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; - -/* Destroy attribute object ATTR. */ -extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; - -/* Return current setting of process-shared attribute of ATTR in PSHARED. */ -extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * - __restrict __attr, - int *__restrict __pshared) __THROW; - -/* Set process-shared attribute of ATTR to PSHARED. */ -extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, - int __pshared) __THROW; - -/* Return current setting of reader/writer preference. */ -extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *__attr, - int *__pref) __THROW; - -/* Set reader/write preference. */ -extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, - int __pref) __THROW; -#endif - -#if 0 -/* Not yet implemented in uClibc! */ - -#ifdef __USE_XOPEN2K -/* The IEEE Std. 1003.1j-2000 introduces functions to implement - spinlocks. */ - -/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can - be shared between different processes. */ -extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) - __THROW; - -/* Destroy the spinlock LOCK. */ -extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; - -/* Wait until spinlock LOCK is retrieved. */ -extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; - -/* Try to lock spinlock LOCK. */ -extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; - -/* Release spinlock LOCK. */ -extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; - - -/* Barriers are a also a new feature in 1003.1j-2000. */ - -extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, - const pthread_barrierattr_t *__restrict - __attr, unsigned int __count) __THROW; - -extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; - -extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; - -extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; - -extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t * - __restrict __attr, - int *__restrict __pshared) __THROW; - -extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, - int __pshared) __THROW; - -extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; -#endif -#endif - - -/* Functions for handling thread-specific data. */ - -/* Create a key value identifying a location in the thread-specific - data area. Each thread maintains a distinct thread-specific data - area. DESTR_FUNCTION, if non-NULL, is called with the value - associated to that key when the key is destroyed. - DESTR_FUNCTION is not called if the value associated is NULL when - the key is destroyed. */ -extern int pthread_key_create (pthread_key_t *__key, - void (*__destr_function) (void *)) __THROW; - -/* Destroy KEY. */ -extern int pthread_key_delete (pthread_key_t __key) __THROW; - -/* Store POINTER in the thread-specific data slot identified by KEY. */ -extern int pthread_setspecific (pthread_key_t __key, - const void *__pointer) __THROW; - -/* Return current value of the thread-specific data slot identified by KEY. */ -extern void *pthread_getspecific (pthread_key_t __key) __THROW; - - -/* Functions for handling initialization. */ - -/* Guarantee that the initialization function INIT_ROUTINE will be called - only once, even if pthread_once is executed several times with the - same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or - extern variable initialized to PTHREAD_ONCE_INIT. - - The initialization functions might throw exception which is why - this function is not marked with __THROW. */ -extern int pthread_once (pthread_once_t *__once_control, - void (*__init_routine) (void)); - - -/* Functions for handling cancellation. */ - -/* Set cancelability state of current thread to STATE, returning old - state in *OLDSTATE if OLDSTATE is not NULL. */ -extern int pthread_setcancelstate (int __state, int *__oldstate); - -/* Set cancellation state of current thread to TYPE, returning the old - type in *OLDTYPE if OLDTYPE is not NULL. */ -extern int pthread_setcanceltype (int __type, int *__oldtype); - -/* Cancel THREAD immediately or at the next possibility. */ -extern int pthread_cancel (pthread_t __cancelthread); - -/* Test for pending cancellation for the current thread and terminate - the thread as per pthread_exit(PTHREAD_CANCELED) if it has been - cancelled. */ -extern void pthread_testcancel (void); - - -/* Install a cleanup handler: ROUTINE will be called with arguments ARG - when the thread is cancelled or calls pthread_exit. ROUTINE will also - be called with arguments ARG when the matching pthread_cleanup_pop - is executed with non-zero EXECUTE argument. - pthread_cleanup_push and pthread_cleanup_pop are macros and must always - be used in matching pairs at the same nesting level of braces. */ - -#define pthread_cleanup_push(routine,arg) \ - { struct _pthread_cleanup_buffer _buffer; \ - _pthread_cleanup_push (&_buffer, (routine), (arg)); - -extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, - void (*__routine) (void *), - void *__arg) __THROW; - -/* Remove a cleanup handler installed by the matching pthread_cleanup_push. - If EXECUTE is non-zero, the handler function is called. */ - -#define pthread_cleanup_pop(execute) \ - _pthread_cleanup_pop (&_buffer, (execute)); } - -extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, - int __execute) __THROW; - -/* Install a cleanup handler as pthread_cleanup_push does, but also - saves the current cancellation type and set it to deferred cancellation. */ - -#ifdef __USE_GNU -# define pthread_cleanup_push_defer_np(routine,arg) \ - { struct _pthread_cleanup_buffer _buffer; \ - _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); - -extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, - void (*__routine) (void *), - void *__arg) __THROW; -extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, - void (*__routine) (void *), - void *__arg) __THROW; - -/* Remove a cleanup handler as pthread_cleanup_pop does, but also - restores the cancellation type that was in effect when the matching - pthread_cleanup_push_defer was called. */ - -# define pthread_cleanup_pop_restore_np(execute) \ - _pthread_cleanup_pop_restore (&_buffer, (execute)); } - -extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, - int __execute) __THROW; -extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, - int __execute) __THROW; -#endif - - -#if 0 -/* Not yet implemented in uClibc! */ - -#ifdef __USE_XOPEN2K -/* Get ID of CPU-time clock for thread THREAD_ID. */ -extern int pthread_getcpuclockid (pthread_t __thread_id, - clockid_t *__clock_id) __THROW; -#endif -#endif - - -/* Functions for handling signals. */ -#include <bits/sigthread.h> - - -/* Functions for handling process creation and process execution. */ - -/* Install handlers to be called when a new process is created with FORK. - The PREPARE handler is called in the parent process just before performing - FORK. The PARENT handler is called in the parent process just after FORK. - The CHILD handler is called in the child process. Each of the three - handlers can be NULL, meaning that no handler needs to be called at that - point. - PTHREAD_ATFORK can be called several times, in which case the PREPARE - handlers are called in LIFO order (last added with PTHREAD_ATFORK, - first called before FORK), and the PARENT and CHILD handlers are called - in FIFO (first added, first called). */ - -extern int pthread_atfork (void (*__prepare) (void), - void (*__parent) (void), - void (*__child) (void)) __THROW; - -/* Terminate all threads in the program except the calling process. - Should be called just before invoking one of the exec*() functions. */ - -extern void pthread_kill_other_threads_np (void) __THROW; - -__END_DECLS - -#endif /* pthread.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/pthread/tls.h b/libpthread/linuxthreads.old/sysdeps/pthread/tls.h deleted file mode 100644 index 2068f1e77..000000000 --- a/libpthread/linuxthreads.old/sysdeps/pthread/tls.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Definition for thread-local data handling. Generic version. - 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 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, see - <http://www.gnu.org/licenses/>. */ - -/* By default no TLS support is available. This is signaled by the - absence of the symbol USE_TLS. */ -#undef USE_TLS - - -/* An architecture-specific version of this file has to defined a - number of symbols: - - TLS_TCB_AT_TP or TLS_DTV_AT_TP - - The presence of one of these symbols signals which variant of - the TLS ABI is used. There are in the moment two variants - available: - - * the thread pointer points to a thread control block - - * the thread pointer points to the dynamic thread vector - - - TLS_TCB_SIZE - - This is the size of the thread control block structure. How - this is actually defined depends on the ABI. The thread control - block could be internal descriptor of the thread library or - just a data structure which allows finding the DTV. - - TLS_INIT_TCB_SIZE - - Similarly, but this value is only used at startup and in the - dynamic linker itself. There are no threads in use at that time. - - - TLS_TCB_ALIGN - - Alignment requirements for the TCB structure. - - TLS_INIT_TCB_ALIGN - - Similarly, but for the structure used at startup time. - - - INSTALL_DTV(tcb, init_dtv) - - This macro must install the given initial DTV into the thread control - block TCB. The normal runtime functionality must then be able to - use the value. - - - TLS_INIT_TP(tcb, firstcall) - - This macro must initialize the thread pointer to enable normal TLS - operation. The first parameter is a pointer to the thread control - block. The second parameter specifies whether this is the first - call for the TCB. ld.so calls this macro more than once. - - - THREAD_DTV() - - This macro returns the address of the DTV of the current thread. - This normally is done using the the thread register which points - to the dtv or the TCB (from which the DTV can found). - */ diff --git a/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h deleted file mode 100644 index 7d1484e71..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - SuperH version. - Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Niibe Yutaka <gniibe@m17n.org>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef __ASSEMBLER__ -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -extern long int testandset (int *spinlock); - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - int ret; - - __asm__ __volatile__( - "tas.b @%1\n\t" - "movt %0" - : "=r" (ret) - : "r" (spinlock) - : "memory", "cc"); - - return (ret == 0); -} - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* Maximum size of the stack if the rlimit is unlimited. */ -#define ARCH_STACK_MAX_SIZE 32*1024*1024 - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("r15"); - -/* Return the thread descriptor for the current thread. */ -struct _pthread_descr_struct; -#define THREAD_SELF \ - ({ struct _pthread_descr_struct *self; \ - __asm__("stc gbr,%0" : "=r" (self)); self;}) - -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) \ - ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) - -/* Access to data in the thread descriptor is easy. */ -#define THREAD_GETMEM(descr, member) \ - ((void) sizeof (descr), THREAD_SELF->member) -#define THREAD_GETMEM_NC(descr, member) \ - ((void) sizeof (descr), THREAD_SELF->member) -#define THREAD_SETMEM(descr, member, value) \ - ((void) sizeof (descr), THREAD_SELF->member = (value)) -#define THREAD_SETMEM_NC(descr, member, value) \ - ((void) sizeof (descr), THREAD_SELF->member = (value)) -#endif /* __ASSEMBLER__ */ - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sh/tls.h b/libpthread/linuxthreads.old/sysdeps/sh/tls.h deleted file mode 100644 index 25bef830f..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sh/tls.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Definition for thread-local data handling. linuxthreads/SH version. - Copyright (C) 2002, 2003, 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 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _TLS_H -#define _TLS_H - -# include <pt-machine.h> - -#ifndef __ASSEMBLER__ -# include <stdbool.h> -# include <stddef.h> -# include <stdint.h> - -/* Type for the dtv. */ -typedef union dtv -{ - size_t counter; - void *pointer; -} dtv_t; - - -typedef struct -{ - void *tcb; /* Pointer to the TCB. Not necessary the - thread descriptor used by libpthread. */ - dtv_t *dtv; - void *self; /* Pointer to the thread descriptor. */ -} tcbhead_t; - - -/* We can support TLS only if the floating-stack support is available. */ -#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT - -/* Get system call information. */ -# include <sysdep.h> - -/* Signal that TLS support is available. */ -//# define USE_TLS 1 - - -/* Get the thread descriptor definition. */ -# include <linuxthreads/descr.h> - -/* This is the size of the initial TCB. */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) - -/* Alignment requirements for the initial TCB. */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) - -/* This is the size of the TCB. */ -# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) - -/* Alignment requirements for the TCB. */ -# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) - -/* The TLS blocks start right after the TCB. */ -# define TLS_DTV_AT_TP 1 - - -/* Install the dtv pointer. The pointer passed is to the element with - index -1 which contain the length. */ -# define INSTALL_DTV(descr, dtvp) \ - ((tcbhead_t *) (descr))->dtv = dtvp + 1 - -/* Install new dtv for current thread. */ -# define INSTALL_NEW_DTV(dtv) \ - ({ struct _pthread_descr_struct *__descr; \ - THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) - -/* Return dtv of given thread descriptor. */ -# define GET_DTV(descr) \ - (((tcbhead_t *) (descr))->dtv) - -/* Code to initially initialize the thread pointer. This might need - special attention since 'errno' is not yet available and if the - operation can cause a failure 'errno' must not be touched. */ -# define TLS_INIT_TP(descr, secondcall) \ - ({ \ - void *_descr = (descr); \ - int result; \ - tcbhead_t *head = _descr; \ - \ - head->tcb = _descr; \ - /* For now the thread descriptor is at the same address. */ \ - head->self = _descr; \ - \ - __asm__ ("ldc %0,gbr" : : "r" (_descr)); \ - \ - 0; \ - }) - - -/* Return the address of the dtv for the current thread. */ -# define THREAD_DTV() \ - ({ struct _pthread_descr_struct *__descr; \ - THREAD_GETMEM (__descr, p_header.data.dtvp); }) - -#endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ -#endif /* __ASSEMBLER__ */ - -#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch b/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch deleted file mode 100644 index ddb56645c..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch +++ /dev/null @@ -1,30 +0,0 @@ -# Makefile for uClibc -# -# Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> -# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org> -# -# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. -# - -libpthread_ARCH_DIR:=$(top_srcdir)libpthread/linuxthreads.old/sysdeps/sh64 -libpthread_ARCH_OUT:=$(top_builddir)libpthread/linuxthreads.old/sysdeps/sh64 - -libpthread_ARCH_SRC:=$(wildcard $(libpthread_ARCH_DIR)/*.c) -libpthread_ARCH_OBJ:=$(patsubst $(libpthread_ARCH_DIR)/%.c,$(libpthread_ARCH_OUT)/%.o,$(libpthread_ARCH_SRC)) - -libpthread-a-y+=$(libpthread_ARCH_OBJ) -libpthread-so-y+=$(libpthread_ARCH_OBJ:.o=.os) - -libpthread-multi-y+=$(libpthread_ARCH_SRC) - -objclean-y += CLEAN_$($(top_builddir),,$(libpthread_ARCH_OUT)) - -# We need to build as SHcompact for tas.. -$(libpthread_ARCH_OBJ): %.o : %.c - $(compile.c:32media=compact) - -$(libpthread_ARCH_OBJ:.o=.os): %.os : %.c - $(compile.c:32media=compact) - -CLEAN_$($(top_builddir),,$(libpthread_ARCH_OUT)): - $(do_rm) $(addprefix $(libpthread_ARCH_OUT)/*., o os) diff --git a/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c b/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c deleted file mode 100644 index 1c187c85c..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Cloned for uClibc by Paul Mundt, December 2003 */ -/* Modified by SuperH, Inc. September 2003 */ - -/* Machine-dependent pthreads configuration and inline functions. - SH5 version. - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Niibe Yutaka <gniibe@m17n.org>. - - 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, - see <http://www.gnu.org/licenses/>. */ - -#include "pt-machine.h" - -/* Spinlock implementation; required. */ - -/* The SH5 does not have a suitable test-and-set instruction (SWAP only - operates on an aligned quad word). So we use the SH4 version instead. - This must be seperately compiled in SHcompact mode, so it cannot be - inline. */ - -long int testandset (int *spinlock) -{ - int ret; - - __asm__ __volatile__( - "tas.b @%1\n\t" - "movt %0" - : "=r" (ret) - : "r" (spinlock) - : "memory", "cc"); - - return (ret == 0); -} - diff --git a/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h deleted file mode 100644 index 9b1fc74cd..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Cloned for uClibc by Paul Mundt, December 2003 */ -/* Modified by SuperH, Inc. September 2003 */ - -/* Machine-dependent pthreads configuration and inline functions. - SuperH version. - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Niibe Yutaka <gniibe@m17n.org>. - - 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, - see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("r15"); - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h deleted file mode 100644 index d502c759a..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - sparc version. - Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Richard Henderson <rth@tamu.edu>. - - 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; see the file COPYING.LIB. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - int ret; - - __asm__ __volatile__("ldstub %1,%0" - : "=r"(ret), "=m"(*spinlock) - : "m"(*spinlock)); - - return ret; -} - - -/* Memory barrier; default is to do nothing */ -#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") - - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) -register char *stack_pointer __asm__("%sp"); - - -/* Registers %g6 and %g7 are reserved by the ABI for "system use". - %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ -struct _pthread_descr_struct; -register struct _pthread_descr_struct *__thread_self __asm__("%g7"); - -/* Return the thread descriptor for the current thread. */ -#define THREAD_SELF __thread_self - -/* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) - -/* Access to data in the thread descriptor is easy. */ -#define THREAD_GETMEM(descr, member) \ - ((void) sizeof (descr), THREAD_SELF->member) -#define THREAD_GETMEM_NC(descr, member) \ - ((void) sizeof (descr), THREAD_SELF->member) -#define THREAD_SETMEM(descr, member, value) \ - ((void) sizeof (descr), THREAD_SELF->member = (value)) -#define THREAD_SETMEM_NC(descr, member, value) \ - ((void) sizeof (descr), THREAD_SELF->member = (value)) - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* Maximum size of the stack if the rlimit is unlimited. */ -#define ARCH_STACK_MAX_SIZE 8*1024*1024 - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/sparc/tcb-offsets.h b/libpthread/linuxthreads.old/sysdeps/sparc/tcb-offsets.h deleted file mode 100644 index 6d6f111f4..000000000 --- a/libpthread/linuxthreads.old/sysdeps/sparc/tcb-offsets.h +++ /dev/null @@ -1 +0,0 @@ -#include "../../../linuxthreads/sysdeps/pthread/tcb-offsets.h" diff --git a/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h deleted file mode 100644 index 34de63b9f..000000000 --- a/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * sysdeps/v850/pt-machine.h -- v850-specific pthread definitions - * - * Copyright (C) 2002 NEC Electronics Corporation - * Copyright (C) 2002 Miles Bader <miles@gnu.org> - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License. See the file COPYING.LIB in the main - * directory of this archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef PT_EI -# define PT_EI __extern_always_inline -#endif - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME __stack_pointer -register char *__stack_pointer __asm__ ("sp"); - -#define HAS_COMPARE_AND_SWAP - -/* Atomically: If *PTR == OLD, set *PTR to NEW and return true, - otherwise do nothing and return false. */ -PT_EI int -__compare_and_swap (long *ptr, long old, long new) -{ - unsigned long psw; - - /* disable interrupts */ - __asm__ __volatile__ ("stsr psw, %0; di" : "=&r" (psw)); - - if (likely (*ptr == old)) - { - *ptr = new; - __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */ - return 1; - } - else - { - __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */ - return 0; - } -} -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h deleted file mode 100644 index ed1fa30b1..000000000 --- a/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - x86-64 version. - Copyright (C) 2001, 2002, 2003, 2004 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 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <features.h> - -#ifndef __ASSEMBLER__ -# include <stddef.h> /* For offsetof. */ -# include <stdlib.h> /* For abort(). */ -# include <asm/prctl.h> - - -# ifndef PT_EI -# define PT_EI __extern_always_inline -# endif - -extern long int testandset (int *); -extern int __compare_and_swap (long int *, long int, long int); - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -# define CURRENT_STACK_FRAME stack_pointer -register char * stack_pointer __asm__ ("%rsp") __attribute_used__; - - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *__spinlock) -{ - long int ret; - - __asm__ __volatile__ ( - "xchgl %k0, %1" - : "=r"(ret), "=m"(*__spinlock) - : "0"(1), "m"(*__spinlock) - : "memory"); - - return ret; -} - - -/* Compare-and-swap for semaphores. */ -# define HAS_COMPARE_AND_SWAP - -PT_EI int -__compare_and_swap (long int *__p, long int __oldval, long int __newval) -{ - char ret; - long int readval; - - __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" - : "=q" (ret), "=m" (*__p), "=a" (readval) - : "r" (__newval), "m" (*__p), "a" (__oldval) - : "memory"); - return ret; -} - -#endif /* !__ASSEMBLER__ */ - -/* We want the OS to assign stack addresses. */ -#define FLOATING_STACKS 1 - -/* Maximum size of the stack if the rlimit is unlimited. */ -#define ARCH_STACK_MAX_SIZE 32*1024*1024 - -/* The ia32e really want some help to prevent overheating. */ -#define BUSY_WAIT_NOP __asm__ ("rep; nop") - -#endif /* pt-machine.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h b/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h deleted file mode 100644 index 24ed3fca9..000000000 --- a/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Definitions for thread-local data handling. linuxthreads/x86-64 version. - Copyright (C) 2002, 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 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _TLS_H -#define _TLS_H - -#ifndef __ASSEMBLER__ - -# include <pt-machine.h> -# include <stdbool.h> -# include <stddef.h> - -/* Type for the dtv. */ -typedef union dtv -{ - size_t counter; - struct - { - void *val; - bool is_static; - } pointer; -} dtv_t; - - -typedef struct -{ - void *tcb; /* Pointer to the TCB. Not necessary the - thread descriptor used by libpthread. */ - dtv_t *dtv; - void *self; /* Pointer to the thread descriptor. */ - int multiple_threads; -} tcbhead_t; - -#else /* __ASSEMBLER__ */ -# include <tcb-offsets.h> -#endif - - -#ifdef HAVE_TLS_SUPPORT - -/* Signal that TLS support is available. */ -# define USE_TLS 1 - -# ifndef __ASSEMBLER__ -/* Get system call information. */ -# include <sysdep.h> - -/* Get the thread descriptor definition. */ -# include <linuxthreads/descr.h> - -/* This is the size of the initial TCB. */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) - -/* Alignment requirements for the initial TCB. */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) - -/* This is the size of the TCB. */ -# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) - -/* Alignment requirements for the TCB. */ -# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) - -/* The TCB can have any size and the memory following the address the - thread pointer points to is unspecified. Allocate the TCB there. */ -# define TLS_TCB_AT_TP 1 - - -/* Install the dtv pointer. The pointer passed is to the element with - index -1 which contain the length. */ -# define INSTALL_DTV(descr, dtvp) \ - ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 - -/* Install new dtv for current thread. */ -# define INSTALL_NEW_DTV(dtv) \ - ({ struct _pthread_descr_struct *__descr; \ - THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) - -/* Return dtv of given thread descriptor. */ -# define GET_DTV(descr) \ - (((tcbhead_t *) (descr))->dtv) - -/* Code to initially initialize the thread pointer. This might need - special attention since 'errno' is not yet available and if the - operation can cause a failure 'errno' must not be touched. */ -# define TLS_INIT_TP(descr, secondcall) \ - ({ \ - void *_descr = (descr); \ - tcbhead_t *head = _descr; \ - long int _result; \ - \ - head->tcb = _descr; \ - /* For now the thread descriptor is at the same address. */ \ - head->self = _descr; \ - \ - __asm__ __volatile__ ("syscall" \ - : "=a" (_result) \ - : "0" ((unsigned long int) __NR_arch_prctl), \ - "D" ((unsigned long int) ARCH_SET_FS), \ - "S" (_descr) \ - : "memory", "cc", "r11", "cx"); \ - \ - _result ? "cannot set %fs base address for thread-local storage" : 0; \ - }) - -/* Indicate that dynamic linker shouldn't try to initialize TLS even - when no PT_TLS segments are found in the program and libraries - it is linked against. */ -# define TLS_INIT_TP_EXPENSIVE 1 - -/* Return the address of the dtv for the current thread. */ -# define THREAD_DTV() \ - ({ struct _pthread_descr_struct *__descr; \ - THREAD_GETMEM (__descr, p_header.data.dtvp); }) - -# endif /* HAVE_TLS_SUPPORT */ -#endif /* __ASSEMBLER__ */ - -#endif /* tls.h */ diff --git a/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h b/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h deleted file mode 100644 index 2c68ddfb5..000000000 --- a/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Machine-dependent pthreads configuration and inline functions. - Xtensa version. - - Copyright (C) 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 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _PT_MACHINE_H -#define _PT_MACHINE_H 1 - -#include <sys/syscall.h> -#include <asm/unistd.h> - -#ifndef PT_EI -# define PT_EI extern inline __attribute__ ((gnu_inline)) -#endif - -#define MEMORY_BARRIER() __asm__ ("memw" : : : "memory") -#define HAS_COMPARE_AND_SWAP - -extern long int testandset (int *spinlock); -extern int __compare_and_swap (long int *p, long int oldval, long int newval); - -/* Spinlock implementation; required. */ -PT_EI long int -testandset (int *spinlock) -{ - unsigned long tmp; - __asm__ volatile ( -" movi %0, 0 \n" -" wsr %0, SCOMPARE1 \n" -" movi %0, 1 \n" -" s32c1i %0, %1, 0 \n" - : "=&a" (tmp) - : "a" (spinlock) - : "memory" - ); - return tmp; -} - -PT_EI int -__compare_and_swap (long int *p, long int oldval, long int newval) -{ - unsigned long tmp; - unsigned long value; - __asm__ volatile ( -"1: l32i %0, %2, 0 \n" -" bne %0, %4, 2f \n" -" wsr %0, SCOMPARE1 \n" -" mov %1, %0 \n" -" mov %0, %3 \n" -" s32c1i %0, %2, 0 \n" -" bne %1, %0, 1b \n" -"2: \n" - : "=&a" (tmp), "=&a" (value) - : "a" (p), "a" (newval), "a" (oldval) - : "memory" ); - - return tmp == oldval; -} - -/* Get some notion of the current stack. Need not be exactly the top - of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME __builtin_frame_address (0) - -#endif /* _PT_MACHINE_H */ diff --git a/libpthread/linuxthreads.old/wrapsyscall.c b/libpthread/linuxthreads.old/wrapsyscall.c deleted file mode 100644 index 668b3911c..000000000 --- a/libpthread/linuxthreads.old/wrapsyscall.c +++ /dev/null @@ -1,246 +0,0 @@ -/* Wrapper around system calls to provide cancellation points. - Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - - 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, - see <http://www.gnu.org/licenses/>. */ - -#include <fcntl.h> -#include <sys/mman.h> -#include <pthread.h> -#include <unistd.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdlib.h> -#include <termios.h> -#include <sys/epoll.h> -#include <sys/resource.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <sys/syscall.h> - - -#ifndef __PIC__ -/* We need a hook to force this file to be linked in when static - libpthread is used. */ -const char __pthread_provide_wrappers = 0; -#endif - -/* Using private interface to libc (__libc_foo) to implement - * cancellable versions of some libc functions */ -#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \ -res_type __libc_##name param_list; \ -res_type \ -__attribute__ ((weak)) \ -name param_list \ -{ \ - res_type result; \ - int oldtype; \ - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ - result = __libc_##name params; \ - pthread_setcanceltype (oldtype, NULL); \ - return result; \ -} - -#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \ -res_type __libc_##name param_list; \ -res_type \ -__attribute__ ((weak)) \ -name param_list \ -{ \ - res_type result; \ - int oldtype; \ - va_list ap; \ - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ - va_start (ap, last_arg); \ - result = __libc_##name params; \ - va_end (ap); \ - pthread_setcanceltype (oldtype, NULL); \ - return result; \ -} - - -/* close(2). */ -CANCELABLE_SYSCALL (int, close, (int fd), (fd)) - - -/* fcntl(2). */ -CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...), - (fd, cmd, va_arg (ap, long int)), cmd) - -#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 32 -/* fcntl64(2). */ -CANCELABLE_SYSCALL_VA (int, fcntl64, (int fd, int cmd, ...), - (fd, cmd, va_arg (ap, long int)), cmd) -#endif - - -/* fsync(2). */ -CANCELABLE_SYSCALL (int, fsync, (int fd), (fd)) - - -/* lseek(2). */ -CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), - (fd, offset, whence)) - -#ifdef __UCLIBC_HAS_LFS__ -/* lseek64(2). */ -CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), - (fd, offset, whence)) -#endif - -#if defined(__NR_msync) && defined(__ARCH_USE_MMU__) - -/* msync(2). */ -CANCELABLE_SYSCALL (int, msync, (void *addr, size_t length, int flags), - (addr, length, flags)) -#endif - - -/* nanosleep(2). */ -libpthread_hidden_proto(nanosleep) -CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time, - struct timespec *remaining), - (requested_time, remaining)) -libpthread_hidden_def(nanosleep) - - -/* open(2). */ -CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...), - (pathname, flags, va_arg (ap, mode_t)), flags) - - -#ifdef __UCLIBC_HAS_LFS__ -/* open64(3). */ -CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...), - (pathname, flags, va_arg (ap, mode_t)), flags) -#endif - -/* pause(2). */ -CANCELABLE_SYSCALL (int, pause, (void), ()) - - -/* Enable this if enabling these in syscalls.c */ -/* pread(3). */ -CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, - off_t offset), - (fd, buf, count, offset)) - - -#if defined __UCLIBC_HAS_LFS__ && defined __NR_pread64 -/* pread64(3). */ -CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, - off64_t offset), - (fd, buf, count, offset)) -#endif - -/* pwrite(3). */ -CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, - off_t offset), - (fd, buf, n, offset)) - - -#if defined __UCLIBC_HAS_LFS__ && defined __NR_pwrited64 -/* pwrite64(3). */ -CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, - off64_t offset), - (fd, buf, n, offset)) -#endif - -/* read(2). */ -CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), - (fd, buf, count)) - - -/* system(3). */ -CANCELABLE_SYSCALL (int, system, (const char *line), (line)) - - -/* tcdrain(2). */ -CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd)) - - -/* wait(2). */ -CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc)) - - -/* waitpid(2). */ -libpthread_hidden_proto(waitpid) -CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc, - int options), - (pid, stat_loc, options)) -libpthread_hidden_def(waitpid) - - -/* write(2). */ -CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n), - (fd, buf, n)) - -#if defined __UCLIBC_HAS_SOCKET__ -/* The following system calls are thread cancellation points specified - in XNS. */ - -/* accept(2). */ -CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr, - socklen_t *addr_len), - (fd, addr, addr_len)) - -/* connect(2). */ -CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr, - socklen_t len), - (fd, addr, len)) - -/* recv(2). */ -CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags), - (fd, buf, n, flags)) - -/* recvfrom(2). */ -CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags, - __SOCKADDR_ARG addr, socklen_t *addr_len), - (fd, buf, n, flags, addr, addr_len)) - -/* recvmsg(2). */ -CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags), - (fd, message, flags)) - -/* send(2). */ -CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n, - int flags), - (fd, buf, n, flags)) - -/* sendmsg(2). */ -CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, - int flags), - (fd, message, flags)) - -/* sendto(2). */ -CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, - int flags, __CONST_SOCKADDR_ARG addr, - socklen_t addr_len), - (fd, buf, n, flags, addr, addr_len)) -#endif /* __UCLIBC_HAS_SOCKET__ */ - -#ifdef __UCLIBC_HAS_EPOLL__ -# include <sys/epoll.h> -# ifdef __NR_epoll_wait -CANCELABLE_SYSCALL (int, epoll_wait, (int epfd, struct epoll_event *events, int maxevents, int timeout), - (epfd, events, maxevents, timeout)) -# endif -# ifdef __NR_epoll_pwait -CANCELABLE_SYSCALL (int, epoll_pwait, (int epfd, struct epoll_event *events, int maxevents, int timeout, - const sigset_t *set), - (epfd, events, maxevents, timeout, set)) -# endif -#endif |