From 9097327dc1c667fc51b8e05cc7c0626fac96665d Mon Sep 17 00:00:00 2001 From: Guillaume Cottenceau Date: Mon, 14 May 2001 14:17:54 +0000 Subject: Initial revision --- mdk-stage1/dietlibc/libpthread/CHANGES | 45 +++ mdk-stage1/dietlibc/libpthread/Makefile | 139 +++++++++ mdk-stage1/dietlibc/libpthread/README | 42 +++ mdk-stage1/dietlibc/libpthread/pthread_atfork.c | 77 +++++ .../libpthread/pthread_attr_getdetachstate.c | 14 + .../libpthread/pthread_attr_getinheritsched.c | 13 + .../libpthread/pthread_attr_getschedparam.c | 13 + .../libpthread/pthread_attr_getschedpolicy.c | 13 + .../dietlibc/libpthread/pthread_attr_getscope.c | 13 + .../libpthread/pthread_attr_getstackaddr.c | 13 + .../libpthread/pthread_attr_getstacksize.c | 14 + mdk-stage1/dietlibc/libpthread/pthread_attr_init.c | 17 + .../libpthread/pthread_attr_setdetachstate.c | 18 ++ .../libpthread/pthread_attr_setinheritsched.c | 18 ++ .../libpthread/pthread_attr_setschedparam.c | 23 ++ .../libpthread/pthread_attr_setschedpolicy.c | 25 ++ .../dietlibc/libpthread/pthread_attr_setscope.c | 18 ++ .../libpthread/pthread_attr_setstackaddr.c | 13 + .../libpthread/pthread_attr_setstacksize.c | 17 + mdk-stage1/dietlibc/libpthread/pthread_cancel.c | 35 +++ .../dietlibc/libpthread/pthread_cleanup_pop.c | 27 ++ .../dietlibc/libpthread/pthread_cleanup_push.c | 23 ++ .../dietlibc/libpthread/pthread_cond_broadcast.c | 23 ++ .../dietlibc/libpthread/pthread_cond_destroy.c | 19 ++ mdk-stage1/dietlibc/libpthread/pthread_cond_init.c | 14 + .../dietlibc/libpthread/pthread_cond_signal.c | 24 ++ .../dietlibc/libpthread/pthread_cond_timedwait.c | 43 +++ mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c | 37 +++ mdk-stage1/dietlibc/libpthread/pthread_condattr.c | 15 + mdk-stage1/dietlibc/libpthread/pthread_create.c | 76 +++++ mdk-stage1/dietlibc/libpthread/pthread_detach.c | 36 +++ mdk-stage1/dietlibc/libpthread/pthread_exit.c | 17 + .../dietlibc/libpthread/pthread_getspecific.c | 20 ++ mdk-stage1/dietlibc/libpthread/pthread_join.c | 50 +++ .../dietlibc/libpthread/pthread_key_create.c | 35 +++ .../dietlibc/libpthread/pthread_key_delete.c | 21 ++ .../dietlibc/libpthread/pthread_mutex_destroy.c | 16 + .../dietlibc/libpthread/pthread_mutex_init.c | 18 ++ .../dietlibc/libpthread/pthread_mutex_lock.c | 33 ++ .../dietlibc/libpthread/pthread_mutex_trylock.c | 36 +++ .../dietlibc/libpthread/pthread_mutex_unlock.c | 34 ++ .../libpthread/pthread_mutexattr_getkind_np.c | 13 + .../dietlibc/libpthread/pthread_mutexattr_init.c | 15 + .../libpthread/pthread_mutexattr_setkind_np.c | 18 ++ mdk-stage1/dietlibc/libpthread/pthread_once.c | 9 + mdk-stage1/dietlibc/libpthread/pthread_self.c | 4 + .../dietlibc/libpthread/pthread_setcancelstate.c | 25 ++ .../dietlibc/libpthread/pthread_setcanceltype.c | 25 ++ .../dietlibc/libpthread/pthread_setspecific.c | 21 ++ mdk-stage1/dietlibc/libpthread/pthread_spinlock.c | 38 +++ mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c | 26 ++ mdk-stage1/dietlibc/libpthread/pthread_sys_close.c | 10 + .../dietlibc/libpthread/pthread_sys_create.c | 10 + mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c | 10 + mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c | 10 + .../dietlibc/libpthread/pthread_sys_logging.c | 31 ++ .../dietlibc/libpthread/pthread_sys_nanosleep.c | 11 + mdk-stage1/dietlibc/libpthread/pthread_sys_open.c | 12 + mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c | 10 + mdk-stage1/dietlibc/libpthread/pthread_sys_read.c | 10 + .../dietlibc/libpthread/pthread_sys_sigsuspend.c | 10 + .../dietlibc/libpthread/pthread_sys_tcdrain.c | 10 + .../dietlibc/libpthread/pthread_sys_waitpid.c | 10 + mdk-stage1/dietlibc/libpthread/pthread_sys_write.c | 10 + .../dietlibc/libpthread/pthread_testcancel.c | 16 + mdk-stage1/dietlibc/libpthread/test.c | 72 +++++ mdk-stage1/dietlibc/libpthread/thread_internal.c | 344 +++++++++++++++++++++ mdk-stage1/dietlibc/libpthread/thread_internal.h | 131 ++++++++ mdk-stage1/dietlibc/libpthread/thread_key.c | 41 +++ 69 files changed, 2149 insertions(+) create mode 100644 mdk-stage1/dietlibc/libpthread/CHANGES create mode 100644 mdk-stage1/dietlibc/libpthread/Makefile create mode 100644 mdk-stage1/dietlibc/libpthread/README create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_atfork.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getdetachstate.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_init.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cancel.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cond_init.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_condattr.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_create.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_detach.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_exit.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_getspecific.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_join.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_key_create.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_key_delete.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_once.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_self.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_setspecific.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_spinlock.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_close.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_create.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_open.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_read.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_sys_write.c create mode 100644 mdk-stage1/dietlibc/libpthread/pthread_testcancel.c create mode 100644 mdk-stage1/dietlibc/libpthread/test.c create mode 100644 mdk-stage1/dietlibc/libpthread/thread_internal.c create mode 100644 mdk-stage1/dietlibc/libpthread/thread_internal.h create mode 100644 mdk-stage1/dietlibc/libpthread/thread_key.c (limited to 'mdk-stage1/dietlibc/libpthread') diff --git a/mdk-stage1/dietlibc/libpthread/CHANGES b/mdk-stage1/dietlibc/libpthread/CHANGES new file mode 100644 index 000000000..d39d990ba --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/CHANGES @@ -0,0 +1,45 @@ +This is the pthread implementation of dietlibc. +Written from scratch by Olaf Dreesen. + +Thu Apr 12 16:47:12 MEST 2001 + + added conditional variables... + except pthread_cond_timedwait all should work man-page like + pthread_cond_timedwait dosen't handle cancel request according to man-page + + added thread specific key handling (all according to man-page) + +Fri Mar 30 18:47:37 MEST 2001 + + uff found some logic errors and fixed them. + pthread_create had a problem with user provided stacks. + + +Fri Mar 23 14:09:54 MET 2001 + + arg.. the kernel-header are so inconsistent... + on x86 it works on arm and sparc not due to MISSING defines, miss-places + includes and __KERNEL__ checks.... + the best in this category is that the kernel-header are changed that the + buggy (g)libc haven't to change... (f..k glibc, the headers HAVE to be + CONSISTENT) + a public defined symbol on arch X have to be in Y to unless marked... + that is mainly speaking SCHED.H ! arg.... + + +Wed Mar 14 04:28:45 MET 2001 + + I have implemented the "Manager Thread" so that nested thread creation + works. really ugly stuff... don't look at it unless you're sitting on solid + ground. + + +Mon Mar 12 16:16:00 CET 2001 + + first of all: + I strongly suggest NOT to use it yet, it's very, very, ... very + experimental. I guess you got the point. there is still much debug code, + incomplete functions and unusable states.... + + I'm still working on the final alpha... + diff --git a/mdk-stage1/dietlibc/libpthread/Makefile b/mdk-stage1/dietlibc/libpthread/Makefile new file mode 100644 index 000000000..06420f43a --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/Makefile @@ -0,0 +1,139 @@ +all: libpthread.a + +ARCH=$(shell uname -m | sed 's/i[4-9]86/i386/') + +CFLAGS=-pipe +CROSS= + +CC=gcc + +VPATH=../$(ARCH)/ + +PTHREAD_OBJS = \ + __testandset.o \ + \ + thread_internal.o \ + thread_key.o \ + \ + pthread_once.o pthread_spinlock.o \ + \ + pthread_create.o pthread_detach.o \ + pthread_join.o pthread_self.o \ + pthread_exit.o \ + \ + pthread_cleanup_push.o \ + pthread_cleanup_pop.o \ + \ + pthread_attr_getdetachstate.o \ + pthread_attr_getinheritsched.o \ + pthread_attr_getschedparam.o \ + pthread_attr_getschedpolicy.o \ + pthread_attr_getscope.o \ + pthread_attr_getstackaddr.o \ + pthread_attr_getstacksize.o \ + pthread_attr_init.o \ + pthread_attr_setdetachstate.o \ + pthread_attr_setinheritsched.o \ + pthread_attr_setschedparam.o \ + pthread_attr_setschedpolicy.o \ + pthread_attr_setscope.o \ + pthread_attr_setstackaddr.o \ + pthread_attr_setstacksize.o \ + \ + pthread_cancel.o pthread_setcancelstate.o \ + pthread_setcanceltype.o pthread_testcancel.o \ + \ + pthread_mutex_init.o \ + pthread_mutex_destroy.o \ + pthread_mutex_lock.o \ + pthread_mutex_trylock.o \ + pthread_mutex_unlock.o \ + \ + pthread_mutexattr_getkind_np.o \ + pthread_mutexattr_init.o \ + pthread_mutexattr_setkind_np.o \ + \ + pthread_condattr.o \ + pthread_cond_broadcast.o \ + pthread_cond_destroy.o \ + pthread_cond_init.o \ + pthread_cond_signal.o \ + pthread_cond_timedwait.o \ + pthread_cond_wait.o \ + \ + pthread_key_create.o \ + pthread_key_delete.o \ + pthread_getspecific.o \ + pthread_setspecific.o \ + \ + pthread_atfork.o \ + pthread_sys_alloc.o \ + pthread_sys_close.o \ + pthread_sys_create.o \ + pthread_sys_fcntl.o \ + pthread_sys_fsync.o \ + pthread_sys_nanosleep.o \ + pthread_sys_logging.o \ + pthread_sys_open.o \ + pthread_sys_pause.o \ + pthread_sys_read.o \ + pthread_sys_sigsuspend.o \ + pthread_sys_tcdrain.o \ + pthread_sys_waitpid.o \ + pthread_sys_write.o + +%.o : %.c + $(CC) $(CFLAGS) -c -o $@ $? + +include ../$(ARCH)/Makefile.add + +ifeq ($(CFLAGS),-pipe) +CFLAGS+=-O -fomit-frame-pointer +endif + +#CFLAGS = -g +CFLAGS += -Wall + +CFLAGS += -I.. -I../include -Wall + +PWD=$(shell pwd) + +.SUFFIXES: +.SUFFIXES: .S .c + +% :: %,v + +%.o: %.S + $(CROSS)$(CC) -I. -Iinclude $(CFLAGS) -c $< + +%.o: %.c + $(CROSS)$(CC) -I. -Iinclude $(CFLAGS) -c $< +# $(CROSS)strip -x -R .comment -R .note $@ + +libpthread.a: $(PTHREAD_OBJS) + ar cr $@ $^ + +libpthread.so: libpthread.a + $(CROSS)ld -whole-archive -shared -o $@ $^ + + +clean: + $(RM) *.o *.a *.so *.out *~ + +exports: libpthread.a + nm -g libpthread.a | grep -w T | awk '{ print $$3 }' | sort -u > exports + +.PHONY: test.out + +test.out: test.o libpthread.a $(LIBS) + $(CROSS)$(CC) -g $(CFLAGS) -nostdlib ../bin-$(ARCH)/start.o -o $@ $^ ../bin-$(ARCH)/dietlibc.a -lgcc + + +.PHONY: sparc ppc mips arm alpha i386 + +sparc ppc alpha i386: + $(MAKE) ARCH=$@ CROSS=$@-linux- all t libdietc.so + +mips arm: + $(MAKE) ARCH=$@ CROSS=$@-linux-gnu- all t libdietc.so + diff --git a/mdk-stage1/dietlibc/libpthread/README b/mdk-stage1/dietlibc/libpthread/README new file mode 100644 index 000000000..3139c731d --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/README @@ -0,0 +1,42 @@ +LIBPTHREAD + + This is the pthread implementation of dietlibc. + Written from scratch by Olaf Dreesen. + +1. STATUS: incomplete but should work (or not... I had a lot of heisen-bugs...) + On non i386 archs the kernel header have major differences... + NO workaround yet for this problems... + +It's like linuxthreads a clone base thread implementation. + +I have implemented a "Manager Thread" with all the pain it involves... +Nested thread creation is now working fine... + + +2. HOW-TO make this lib: + + 1. generate the dietlibc in the parent directory. + and make sure you have WANT_THREAD_SAVE active in the file: + dietfeatures.h + + 2. change back here and type make + + and then you should have a libpthread.a + + +3. NOTES + +NON STANDARD SIGNAL HANDLING for the threads: + + SIGHUP the targeted thread is canceled + depends on the cancel type of the thread. + + ASYNCHRONOUS: the signal handler will KILL the thread immediately. + + DEFERRED: the signal handler mark its thread as canceled. + (only for the sig-handler to do some sane stuff...) + + SIGTERM the thread is KILLED + if the thread signaled is the main thread, then ALL child-threads + will get a SIGHUP and after some micros a SIGTERM.... + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_atfork.c b/mdk-stage1/dietlibc/libpthread/pthread_atfork.c new file mode 100644 index 000000000..2dc612dcc --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_atfork.c @@ -0,0 +1,77 @@ +#include +#include + +#include +#include "thread_internal.h" + +#define PTHREAD_NUM_ATFORK 4 + +static struct _pthread_fastlock __atfork_struct_lock; +static struct { + int used; + void (*prepare)(void); + void (*parent)(void); + void (*child)(void); +} pthread_atfork_buf[PTHREAD_NUM_ATFORK]; + +int pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + int i,ret=-1; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__atfork_struct_lock); + + for (i=0;i0) { /* parent */ + for (i=0;i +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + __THREAD_INIT(); + + *detachstate=attr->__detachstate; + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c new file mode 100644 index 000000000..314fd8ade --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getinheritsched.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + __THREAD_INIT(); + + *inherit = attr->__inheritsched; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c new file mode 100644 index 000000000..f0a9a07d1 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedparam.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) +{ + __THREAD_INIT(); + + param->sched_priority=attr->__schedparam.sched_priority; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c new file mode 100644 index 000000000..53f1bed8c --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getschedpolicy.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + __THREAD_INIT(); + + *policy = attr->__schedpolicy; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c new file mode 100644 index 000000000..99a33110d --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getscope.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + __THREAD_INIT(); + + *scope=PTHREAD_SCOPE_SYSTEM; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c new file mode 100644 index 000000000..d71421901 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstackaddr.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack) +{ + __THREAD_INIT(); + + *stack=attr->__stackaddr; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c new file mode 100644 index 000000000..4785979a0 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_getstacksize.c @@ -0,0 +1,14 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize) +{ + __THREAD_INIT(); + + *stacksize=attr->__stacksize; + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_init.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_init.c new file mode 100644 index 000000000..726e88fe5 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_init.c @@ -0,0 +1,17 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_init(pthread_attr_t *attr) +{ + __THREAD_INIT(); + + memset(attr,0,sizeof(pthread_attr_t)); + attr->__stacksize=PTHREAD_STACK_SIZE; + return 0; +} + +int pthread_attr_destroy(pthread_attr_t *attr) __attribute__((alias("pthread_attr_init"))); + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c new file mode 100644 index 000000000..690ad5f8e --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setdetachstate.c @@ -0,0 +1,18 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + __THREAD_INIT(); + + if ((detachstate == PTHREAD_CREATE_JOINABLE) || + (detachstate == PTHREAD_CREATE_DETACHED)) { + attr->__detachstate=detachstate; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c new file mode 100644 index 000000000..f38e6e35e --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setinheritsched.c @@ -0,0 +1,18 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + __THREAD_INIT(); + + if ((inherit==PTHREAD_INHERIT_SCHED) || + (inherit==PTHREAD_EXPLICIT_SCHED)) { + attr->__inheritsched=inherit; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c new file mode 100644 index 000000000..833c0111b --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedparam.c @@ -0,0 +1,23 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) +{ + __THREAD_INIT(); + + if ((attr->__schedpolicy == SCHED_OTHER) && (param->sched_priority == 0)) { + attr->__schedparam.sched_priority=0; + return 0; + } + if (((attr->__schedpolicy == SCHED_RR) || (attr->__schedpolicy == SCHED_RR)) + && ((param->sched_priority > 0) && (param->sched_priority < 100))) { + attr->__schedparam.sched_priority=param->sched_priority; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c new file mode 100644 index 000000000..e845bca32 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setschedpolicy.c @@ -0,0 +1,25 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + __THREAD_INIT(); + + if (policy==SCHED_OTHER) { + attr->__schedpolicy=policy; + return 0; + } + if ((policy==SCHED_FIFO) || (policy==SCHED_RR)) { + if (geteuid()==0) { + attr->__schedpolicy=policy; + return 0; + } + (*(__errno_location()))=ENOTSUP; + } + else + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c new file mode 100644 index 000000000..39088c9b2 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setscope.c @@ -0,0 +1,18 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + __THREAD_INIT(); + + if (scope==PTHREAD_SCOPE_SYSTEM) return 0; + + if (scope==PTHREAD_SCOPE_PROCESS) + (*(__errno_location()))=ENOTSUP; + else + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c new file mode 100644 index 000000000..4b320cd9d --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstackaddr.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack) +{ + __THREAD_INIT(); + + attr->__stackaddr=stack; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c new file mode 100644 index 000000000..cfbab7747 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_attr_setstacksize.c @@ -0,0 +1,17 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + __THREAD_INIT(); + + if (stacksize>=PTHREAD_STACK_SIZE) { + attr->__stacksize=stacksize; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cancel.c b/mdk-stage1/dietlibc/libpthread/pthread_cancel.c new file mode 100644 index 000000000..4c87a3ed1 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cancel.c @@ -0,0 +1,35 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cancel(pthread_t th) +{ + pthread_t j; + _pthread_descr thread; + + __THREAD_INIT(); + + j=__find_thread_id(th); + + if (j==-1) { + (*(__errno_location()))=ESRCH; + return -1; + } + thread = __get_thread_struct(j); + + if (thread==0) { + (*(__errno_location()))=ESRCH; + return -1; + } + + if (thread->cancelstate!=PTHREAD_CANCEL_DISABLE) { + thread->canceled=1; + if (thread->canceltype!=PTHREAD_CANCEL_DEFERRED) { + kill(thread->pid,SIGHUP); + } + } + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c new file mode 100644 index 000000000..641bb6083 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_pop.c @@ -0,0 +1,27 @@ +#include +#include + +#include +#include "thread_internal.h" + +void pthread_cleanup_pop(int execute) +{ + _pthread_descr this; + struct thread_cleanup_t tmp; + int i=PTHREAD_MAX_CLEANUP; + + __THREAD_INIT(); + + this = __thread_self(); + + while(i>0) { + if (this->cleanup_stack[--i].func) { + tmp.func=this->cleanup_stack[i].func; + tmp.arg=this->cleanup_stack[i].arg; + this->cleanup_stack[i].func=0; + break; + } + } + + if (execute) tmp.func(tmp.arg); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c new file mode 100644 index 000000000..cd2aabf71 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cleanup_push.c @@ -0,0 +1,23 @@ +#include +#include + +#include +#include "thread_internal.h" + +void pthread_cleanup_push(void (*func)(void*), void *arg) +{ + _pthread_descr this; + int i; + + __THREAD_INIT(); + + this = __thread_self(); + + for (i=0; icleanup_stack[i].func==0) { + this->cleanup_stack[i].func=func; + this->cleanup_stack[i].arg=arg; + break; + } + } +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c new file mode 100644 index 000000000..d3c2274f3 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_broadcast.c @@ -0,0 +1,23 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + _pthread_descr tmp; + + __THREAD_INIT(); + + __pthread_lock(&(cond->lock)); + while ((tmp=cond->wait_chain)) { + cond->wait_chain=tmp->waitnext; + tmp->waitnext=0; + tmp->waiting=0; + } + __pthread_unlock(&(cond->lock)); + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c new file mode 100644 index 000000000..9a6cc4f0b --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_destroy.c @@ -0,0 +1,19 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + __THREAD_INIT(); + + if (cond->wait_chain) { + (*__errno_location())=EBUSY; + return 1; + } + + memset(cond,0,sizeof(pthread_cond_t)); + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_init.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_init.c new file mode 100644 index 000000000..20b38bef2 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_init.c @@ -0,0 +1,14 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr) +{ + __THREAD_INIT(); + + memset(cond,0,sizeof(pthread_cond_t)); + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c new file mode 100644 index 000000000..60bf2119c --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_signal.c @@ -0,0 +1,24 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cond_signal(pthread_cond_t *cond) +{ + _pthread_descr tmp=0; + + __THREAD_INIT(); + + __pthread_lock(&(cond->lock)); + if ((tmp=cond->wait_chain)) cond->wait_chain=tmp->waitnext; + __pthread_unlock(&(cond->lock)); + + if (tmp) { + tmp->waitnext=0; + tmp->waiting=0; + } + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c new file mode 100644 index 000000000..6613f2ca9 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_timedwait.c @@ -0,0 +1,43 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + _pthread_descr tmp; + _pthread_descr this; + int ret; + + __THREAD_INIT(); + + this=__thread_self(); + + /* put in wait-chain */ + __pthread_lock(&(cond->lock)); + this->waiting=1; + if (cond->wait_chain) { + for(tmp=cond->wait_chain;tmp->waitnext;tmp=tmp->waitnext); + tmp->waitnext=this; + } else cond->wait_chain=this; + __pthread_unlock(&(cond->lock)); + + /* Aeh yeah / wait till signal */ + pthread_mutex_unlock(mutex); + ret=nanosleep(abstime,0); + pthread_mutex_lock(mutex); + + __TEST_CANCEL(); + + if (ret) { + if ((*__errno_location())!=EINTR) return -1; + return 0; + } + + (*__errno_location())=ETIMEDOUT; + return -1; +} + + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c b/mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c new file mode 100644 index 000000000..0c6c0ae13 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_cond_wait.c @@ -0,0 +1,37 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + _pthread_descr tmp; + _pthread_descr this; + + __THREAD_INIT(); + + this=__thread_self(); + + /* put in wait-chain */ + __pthread_lock(&(cond->lock)); + this->waiting=1; + if (cond->wait_chain) { + for(tmp=cond->wait_chain;tmp->waitnext;tmp=tmp->waitnext); + tmp->waitnext=this; + } else cond->wait_chain=this; + __pthread_unlock(&(cond->lock)); + + /* Aeh yeah / wait till signal */ + pthread_mutex_unlock(mutex); + while (this->waiting) { + __thread_wait_some_time(); + if (this->canceled) this->waiting=0; /* we got a cancel signal */ + } + pthread_mutex_lock(mutex); + + __TEST_CANCEL(); + return 0; +} + + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_condattr.c b/mdk-stage1/dietlibc/libpthread/pthread_condattr.c new file mode 100644 index 000000000..c537890ba --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_condattr.c @@ -0,0 +1,15 @@ +#include + +int pthread_condattr_init(pthread_condattr_t *attr) +{ + return 0; +} + +int pthread_condattr_destroy(pthread_condattr_t *attr) +__attribute__((alias("pthread_condattr_init"))); + +int pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) +__attribute__((alias("pthread_condattr_init"))); + +int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) +__attribute__((alias("pthread_condattr_init"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_create.c b/mdk-stage1/dietlibc/libpthread/pthread_create.c new file mode 100644 index 000000000..b4a499081 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_create.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#include +#include "thread_internal.h" + +int pthread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg) +{ + int ret=0; + _pthread_descr td; + pthread_attr_t default_attr; + + __THREAD_INIT(); + + if (start_routine==0) { + (*(__errno_location()))=EINVAL; + return -1; + } + + td = __thread_get_free(); + + if (td) { + if (!(attr)) { + pthread_attr_init(&default_attr); + attr=&default_attr; + } + + if ((td->policy!=SCHED_OTHER)&&(td->priority==0)) { + (*(__errno_location()))=EINVAL; + return -1; + } + + if (attr->__inheritsched==PTHREAD_INHERIT_SCHED) { + _pthread_descr this = __thread_self(); + td->policy = this->policy; + td->priority = this->priority; + } else { + td->policy = attr->__schedpolicy; + td->priority = attr->__schedparam.sched_priority; + } + + td->func = start_routine; + td->arg = arg; + + td->detached = attr->__detachstate; + + td->stack_size = attr->__stacksize; + + if (!(td->stack_addr)) { + char *stack=(char*)malloc(td->stack_size); + if (!(stack)) { + (*(__errno_location()))=EINVAL; + return -1; + } + td->stack_begin = stack; + td->stack_addr = stack+td->stack_size; + } else { + td->stack_begin = 0; + td->stack_addr = attr->__stackaddr; + } + + ret = signal_manager_thread(td); + + if (ret>1) + *thread=ret; + else + __thread_cleanup(td); + } + else + (*(__errno_location()))=EAGAIN; + + if (ret<2) return -1; + return ret; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_detach.c b/mdk-stage1/dietlibc/libpthread/pthread_detach.c new file mode 100644 index 000000000..c07280389 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_detach.c @@ -0,0 +1,36 @@ +#include + +#include +#include "thread_internal.h" + +int pthread_detach(pthread_t th) +{ + pthread_t j; + _pthread_descr thread; + + __THREAD_INIT(); + + j=__find_thread_id(th); + + if (j==-1) { + (*(__errno_location()))=ESRCH; + return -1; + } + thread = __get_thread_struct(j); + + if (thread==0) { + (*(__errno_location()))=ESRCH; + return -1; + } + + if (thread->detached) { + (*(__errno_location()))=EINVAL; + return -1; + } + + if (!thread->joined) { + thread->detached=1; + } + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_exit.c b/mdk-stage1/dietlibc/libpthread/pthread_exit.c new file mode 100644 index 000000000..41eac0a33 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_exit.c @@ -0,0 +1,17 @@ +#include +#include + +#include +#include "thread_internal.h" + +void pthread_exit(void *retval) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + this->retval = retval; + + longjmp(this->jmp_exit,1); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_getspecific.c b/mdk-stage1/dietlibc/libpthread/pthread_getspecific.c new file mode 100644 index 000000000..c2f84c814 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_getspecific.c @@ -0,0 +1,20 @@ +#include +#include + +#include +#include "thread_internal.h" + +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +const void *pthread_getspecific(pthread_key_t key) +{ + int id; + __THREAD_INIT(); + + id=__find_thread_id(getpid()); + + if ((key +#include +#include + +#include "thread_internal.h" +#include + +int pthread_join(pthread_t th, void **thread_return) +{ + pthread_t j; + _pthread_descr this, thread; + + __THREAD_INIT(); + + this = __thread_self(); + j=__find_thread_id(th); + + if (j==-1) { + (*(__errno_location()))=ESRCH; + return -1; + } + + thread = __get_thread_struct(j); + + /* error handling */ + if (thread==0) { + (*(__errno_location()))=ESRCH; + return -1; + } + + if (this==thread) { + (*(__errno_location()))=EDEADLK; + return -1; + } + + if (thread->detached || thread->joined) { + (*(__errno_location()))=EINVAL; + return -1; + } + + thread->joined=this; + this->join=1; + + while(this->join) __thread_wait_some_time(); + + if (thread_return) *thread_return=this->retval; + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_key_create.c b/mdk-stage1/dietlibc/libpthread/pthread_key_create.c new file mode 100644 index 000000000..44fccea6a --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_key_create.c @@ -0,0 +1,35 @@ +#include +#include + +#include +#include "thread_internal.h" + +extern struct _pthread_fastlock __thread_keys_lock; +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +int pthread_key_create(pthread_key_t *key, void (*destructor)(const void*)) +{ + int ret=-1,i; + + __THREAD_INIT(); + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_keys_lock); + + for (i=0; i +#include + +#include +#include "thread_internal.h" + +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +int pthread_key_delete(pthread_key_t key) +{ + __THREAD_INIT(); + + if (key>=PTHREAD_KEYS_MAX) { + (*__errno_location())=EINVAL; + return -1; + } + + __thread_keys[key].used=0; + + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c new file mode 100644 index 000000000..33a16abd4 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_destroy.c @@ -0,0 +1,16 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + __THREAD_INIT(); + + if ((mutex->owner)||(mutex->lock.__spinlock)) { + (*(__errno_location()))=EBUSY; + return -1; + } + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c new file mode 100644 index 000000000..b1797fb20 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_init.c @@ -0,0 +1,18 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutexattr) +{ + __THREAD_INIT(); + + memset(mutex,0,sizeof(pthread_mutex_t)); + if (mutexattr) { + mutex->kind=mutexattr->__mutexkind; + } + return 0; +} + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c new file mode 100644 index 000000000..0c3ade9e8 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_lock.c @@ -0,0 +1,33 @@ +#include +#include +#include + +#include +#include "thread_internal.h" + +/* will never return EINVAL ! */ + +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + + if (this!=mutex->owner) { + /* wait for mutex to free */ + __pthread_lock(&(mutex->lock)); + + mutex->owner=this; + } + else if (mutex->kind==PTHREAD_MUTEX_ERRORCHECK_NP) + { + (*(__errno_location()))=EDEADLK; + return -1; + } + + if (mutex->kind==PTHREAD_MUTEX_RECURSIVE_NP) ++(mutex->count); + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c new file mode 100644 index 000000000..fcf63f75e --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_trylock.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#include +#include "thread_internal.h" + +/* will never return EINVAL ! */ + +int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + + if (this!=mutex->owner) { + /* wait for mutex to free */ + if (__pthread_trylock(&(mutex->lock))) { + (*(__errno_location()))=EBUSY; + return -1; + } + + mutex->owner=this; + } + else if (mutex->kind==PTHREAD_MUTEX_ERRORCHECK_NP) + { + (*(__errno_location()))=EDEADLK; + return -1; + } + + if (mutex->kind==PTHREAD_MUTEX_RECURSIVE_NP) ++(mutex->count); + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c b/mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c new file mode 100644 index 000000000..0b5a1d0f7 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutex_unlock.c @@ -0,0 +1,34 @@ +#include +#include +#include + +#include +#include "thread_internal.h" + +/* will never return EINVAL ! */ + +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + _pthread_descr this; + + __THREAD_INIT(); + + this = __thread_self(); + + if (this==mutex->owner) { + if (mutex->kind==PTHREAD_MUTEX_RECURSIVE_NP) { + if (--(mutex->count)) + return 0; + } + + mutex->owner=0; + __pthread_unlock(&(mutex->lock)); + } + else if (mutex->kind==PTHREAD_MUTEX_ERRORCHECK_NP) + { + (*(__errno_location()))=EPERM; + return -1; + } + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c new file mode 100644 index 000000000..63cd9133c --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_getkind_np.c @@ -0,0 +1,13 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_mutexattr_getkind_np(const pthread_mutexattr_t *attr, int *kind) +{ + __THREAD_INIT(); + + *kind=attr->__mutexkind; + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c new file mode 100644 index 000000000..ff60e4c74 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_init.c @@ -0,0 +1,15 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + __THREAD_INIT(); + + attr->__mutexkind = 0; + return 0; +} + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) __attribute__((alias ("pthread_mutexattr_init"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c new file mode 100644 index 000000000..ac600f8ed --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_mutexattr_setkind_np.c @@ -0,0 +1,18 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) +{ + __THREAD_INIT(); + + if ((kind==PTHREAD_MUTEX_FAST_NP) || (kind==PTHREAD_MUTEX_RECURSIVE_NP) || + (kind==PTHREAD_MUTEX_ERRORCHECK_NP)) { + attr->__mutexkind=kind; + return 0; + } + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_once.c b/mdk-stage1/dietlibc/libpthread/pthread_once.c new file mode 100644 index 000000000..16d9cb392 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_once.c @@ -0,0 +1,9 @@ +#include +#include "thread_internal.h" + +int __pthread_once (pthread_once_t* once_control, void (*init_routine)(void)) +{ + if (!(__testandset(once_control))) init_routine(); + return 0; +} +int pthread_once (pthread_once_t* once_control, void (*init_routine)(void)) __attribute__((alias("__pthread_once"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_self.c b/mdk-stage1/dietlibc/libpthread/pthread_self.c new file mode 100644 index 000000000..394686dd4 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_self.c @@ -0,0 +1,4 @@ +#include +#include + +pthread_t pthread_self() { return getpid(); } diff --git a/mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c b/mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c new file mode 100644 index 000000000..b906492fb --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_setcancelstate.c @@ -0,0 +1,25 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_setcancelstate(int state, int *oldstate) +{ + _pthread_descr thread; + + __THREAD_INIT(); + + if ((state==PTHREAD_CANCEL_ENABLE) || (state==PTHREAD_CANCEL_DISABLE)) + { + thread = __thread_self(); + + if (oldstate) *oldstate = thread->cancelstate; + thread->cancelstate = state; + + return 0; + } + + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c b/mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c new file mode 100644 index 000000000..03d1f53de --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_setcanceltype.c @@ -0,0 +1,25 @@ +#include +#include + +#include +#include "thread_internal.h" + +int pthread_setcanceltype(int type, int *oldtype) +{ + _pthread_descr thread; + + __THREAD_INIT(); + + if ((type==PTHREAD_CANCEL_DEFERRED) || (type==PTHREAD_CANCEL_ASYNCHRONOUS)) + { + thread = __thread_self(); + + if (oldtype) *oldtype = thread->canceltype; + thread->canceltype = type; + + return 0; + } + + (*(__errno_location()))=EINVAL; + return -1; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_setspecific.c b/mdk-stage1/dietlibc/libpthread/pthread_setspecific.c new file mode 100644 index 000000000..78339c20b --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_setspecific.c @@ -0,0 +1,21 @@ +#include +#include + +#include +#include "thread_internal.h" + +extern struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; +int pthread_setspecific(pthread_key_t key, const void *value) +{ + int id; + __THREAD_INIT(); + + id=__find_thread_id(getpid()); + if ((key +#include +#include "thread_internal.h" + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + while (__testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + __libc_nanosleep(&tm, 0); + cnt = 0; + } + } +} + +void __pthread_lock(struct _pthread_fastlock * lock) +{ + __pthread_acquire(&lock->__spinlock); +} + +int __pthread_trylock(struct _pthread_fastlock * lock) +{ + return __testandset(&lock->__spinlock); +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ + return (lock->__spinlock = 0); +} + + diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c new file mode 100644 index 000000000..9f7d23d79 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_alloc.c @@ -0,0 +1,26 @@ +#include + +#include +#include "thread_internal.h" + +static pthread_mutex_t mutex_alloc = PTHREAD_MUTEX_INITIALIZER; + +void free(void *ptr) +{ + __NO_ASYNC_CANCEL_BEGIN; + pthread_mutex_lock(&mutex_alloc); + __libc_free(ptr); + pthread_mutex_unlock(&mutex_alloc); + __NO_ASYNC_CANCEL_END; +} + +void *malloc(size_t size) +{ + register void *ret; + __NO_ASYNC_CANCEL_BEGIN; + pthread_mutex_lock(&mutex_alloc); + ret=__libc_malloc(size); + pthread_mutex_unlock(&mutex_alloc); + __NO_ASYNC_CANCEL_END; + return ret; +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_close.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_close.c new file mode 100644 index 000000000..84d5d5f36 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_close.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int close(int fd) +{ + __TEST_CANCEL(); + return __libc_close(fd); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_create.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_create.c new file mode 100644 index 000000000..9d47844f5 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_create.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int creat(const char *pathname, mode_t mode) +{ + __TEST_CANCEL(); + return __libc_creat(pathname,mode); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c new file mode 100644 index 000000000..99210a488 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_fcntl.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int fcntl(int fd, int cmd, void *arg) +{ + __TEST_CANCEL(); + return __libc_fcntl(fd,cmd,arg); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c new file mode 100644 index 000000000..a2c995069 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_fsync.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int fsync(int fd) +{ + __TEST_CANCEL(); + return __libc_fsync(fd); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c new file mode 100644 index 000000000..6070ad219 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_logging.c @@ -0,0 +1,31 @@ +#include +#include + +#include +#include "thread_internal.h" + +static pthread_mutex_t mutex_syslog = PTHREAD_MUTEX_INITIALIZER; + +void closelog(void) +{ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&mutex_syslog); + pthread_mutex_lock(&mutex_syslog); + __libc_closelog(); + pthread_cleanup_pop(1); +} + +void openlog(const char *ident, int option, int facility) +{ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&mutex_syslog); + pthread_mutex_lock(&mutex_syslog); + __libc_openlog(ident, option, facility); + pthread_cleanup_pop(1); +} + +void vsyslog(int priority, const char *format, va_list arg_ptr) +{ + pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock,&mutex_syslog); + pthread_mutex_lock(&mutex_syslog); + __libc_vsyslog(priority, format, arg_ptr); + pthread_cleanup_pop(1); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c new file mode 100644 index 000000000..699de4654 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_nanosleep.c @@ -0,0 +1,11 @@ +#include +#include + +#include +#include "thread_internal.h" + +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + __TEST_CANCEL(); + return __libc_nanosleep(req,rem); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_open.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_open.c new file mode 100644 index 000000000..513f6a323 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_open.c @@ -0,0 +1,12 @@ +#include + +#include +#include "thread_internal.h" + +int __pthread_open(const char *pathname, int flags, mode_t mode) +{ + __TEST_CANCEL(); + return __libc_open(pathname,flags,mode); +} + +int open(const char *pathname, int flags, ...) __attribute__((alias("__pthread_open"))); diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c new file mode 100644 index 000000000..ab15ead11 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_pause.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int pause() +{ + __TEST_CANCEL(); + return __libc_pause(); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_read.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_read.c new file mode 100644 index 000000000..60f886003 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_read.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int read(int fd, void *buf, size_t count) +{ + __TEST_CANCEL(); + return __libc_read(fd,buf,count); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c new file mode 100644 index 000000000..72cd783ae --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_sigsuspend.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int sigsuspend(const sigset_t *mask) +{ + __TEST_CANCEL(); + return __libc_sigsuspend(mask); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c new file mode 100644 index 000000000..1ac33adfc --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_tcdrain.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int tcdrain(int fd) +{ + __TEST_CANCEL(); + return __libc_tcdrain(fd); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c new file mode 100644 index 000000000..76d5ddca7 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_waitpid.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +pid_t waitpid(pid_t pid, int *status, int options) +{ + __TEST_CANCEL(); + return __libc_waitpid(pid,status,options); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_sys_write.c b/mdk-stage1/dietlibc/libpthread/pthread_sys_write.c new file mode 100644 index 000000000..37541ae42 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_sys_write.c @@ -0,0 +1,10 @@ +#include + +#include +#include "thread_internal.h" + +int write(int fd, const void *buf, size_t count) +{ + __TEST_CANCEL(); + return __libc_write(fd,buf,count); +} diff --git a/mdk-stage1/dietlibc/libpthread/pthread_testcancel.c b/mdk-stage1/dietlibc/libpthread/pthread_testcancel.c new file mode 100644 index 000000000..68f91e743 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/pthread_testcancel.c @@ -0,0 +1,16 @@ +#include + +#include +#include "thread_internal.h" + +void pthread_testcancel() +{ + _pthread_descr thread; + __THREAD_INIT(); + + thread=__thread_self(); + + if (thread->canceled) { + pthread_exit(PTHREAD_CANCELED); + } +} diff --git a/mdk-stage1/dietlibc/libpthread/test.c b/mdk-stage1/dietlibc/libpthread/test.c new file mode 100644 index 000000000..3272c1753 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/test.c @@ -0,0 +1,72 @@ +#include +#include + +#include +#include + +#include + +int ra; + +void test(int sig) +{ + printf("SIGNAL %d in %d\n",sig,getpid()); + fflush(stdout); + signal(SIGHUP, test); +} + +void* thread(void* arg) +{ + int i; + for (i=0;i<10; i++) + { + printf("child %ld %8p\n", pthread_self(),arg); + sleep(1); + } + return arg; +} + +void* thread2(void *arg) +{ + pthread_t t; + int i; + + printf("child %ld %8p\n", pthread_self(),arg); + for (i=0; i<3; ++i) { + printf("child starting next in %d secs %ld %8p\n", 3-i, pthread_self(),arg); + sleep(1); + } + pthread_create(&t,0, thread, (void*)2); + printf("new child @ %ld\n",t); + return (void*)t; +} + +int main(int argc, char*argv[]) +{ + pthread_t t; + + signal(SIGHUP, test); + + pthread_create(&t,0, thread2, 0); + pthread_create(&t,0, thread, (void *)3); + pthread_create(&t,0, thread, (void *)1); + + puts("main"); + +#if 0 + { + int i; + for(i=0;i<4;i++) sleep(1); + } +#else + { + int *tt; + int i = pthread_join(t,(void*)&tt); + printf("join %d %p %d\n",i,tt,(*(__errno_location()))); + } +#endif + + puts("main exit"); + + return 0; +} diff --git a/mdk-stage1/dietlibc/libpthread/thread_internal.c b/mdk-stage1/dietlibc/libpthread/thread_internal.c new file mode 100644 index 000000000..a93806203 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/thread_internal.c @@ -0,0 +1,344 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "thread_internal.h" + +static struct _pthread_fastlock __thread_struct_lock = {0}; +static struct _pthread_descr_struct threads[PTHREAD_THREADS_MAX]; +static int _max_used_thread_id=1; +pthread_once_t __thread_inited; + +static struct _pthread_fastlock __manager_thread_signal_lock = {0}; +static struct _pthread_fastlock __manager_thread_data_lock = {1}; +static struct _pthread_fastlock __manager_thread_data_go_lock = {1}; + +//#define DEBUG + +/* find thread */ +int __find_thread_id(int pid) +{ + register int i; + for (i=0; i<_max_used_thread_id; i++) + if (threads[i].pid==pid) + return i; + return -1; +} + +/* get thread */ +_pthread_descr __get_thread_struct(int id) +{ + return threads+id; +} + +/* thread errno location */ +int *__errno_location(void) +{ + int id=0; + if (__thread_inited) id=__find_thread_id(getpid()); + if (id<0) + return 0; + else + return &threads[id].errno; +} + +/* thread self */ +_pthread_descr __thread_self() +{ + register int i=__find_thread_id(getpid()); + if (i<0) + return 0; + else + return threads+i; +} + +/* allocate a thread slot */ +_pthread_descr __thread_get_free() +{ + _pthread_descr ret=0; + int i; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_struct_lock); + + for (i=0; i=_max_used_thread_id) _max_used_thread_id=i+1; + break; + } + } + + __pthread_unlock(&__thread_struct_lock); + __NO_ASYNC_CANCEL_END; + return ret; +} + +/* sleep a little (reschedule for this time) */ +void __thread_wait_some_time() +{ + struct timespec reg; + reg.tv_sec=0; + reg.tv_nsec=SPIN_SLEEP_DURATION; + __libc_nanosleep(®,0); +} + +/* cleanup a thread struct */ +void __thread_cleanup(_pthread_descr th) +{ + /* lib provided stack should be freed */ + if (th->stack_begin) free(th->stack_begin); + + /* an other thread has joined this on */ + if (th->joined) { + th->joined->retval=th->retval; + th->joined->join=0; + th->joined=0; + } + th->pid=0; /* mark struct as free */ +} + +/* SIGHUP handler (thread cnacel) PTHREAD_CANCEL_ASYNCHRONOUS */ +static void __thread_cancel_handler(int sig) +{ + _pthread_descr this; + this = __thread_self(); + this->canceled=1; + if (this->canceltype==PTHREAD_CANCEL_ASYNCHRONOUS) + pthread_exit(PTHREAD_CANCELED); + signal( SIGHUP, __thread_cancel_handler ); +} + +/* kill ALL threads / other then prime task and manager thread */ +static void __kill_all_threads() +{ + int i; + + for (i=2; i<_max_used_thread_id; i++) { + if (threads[i].pid>1) { +#ifdef DEBUG + printf("CANCEL ! %d\n",threads[i].pid); +#endif + threads[i].canceled=1; + kill(threads[i].pid, SIGHUP); /* cancel thread */ + } + } + + __thread_wait_some_time(); + + for (i=2; i<_max_used_thread_id; i++) { + if (threads[i].pid>1) { +#ifdef DEBUG + printf("KILL ! %d\n",threads[i].pid); +#endif + kill(threads[i].pid, SIGTERM); /* KILL thread */ + } + } +} + +__attribute__((weak)) volatile void __thread_start__key(int id) { return; } +__attribute__((weak,alias("__thread_start__key"))) volatile void __thread_exit__key(int id); + +/* support for manager */ +static void *__mthread_starter(void *arg) +{ + _pthread_descr td = (_pthread_descr)arg; + int i = td->stack_size-4096; + + /* just to be sure */ + td->pid=getpid(); + + /* signal handling for a thread */ + signal(SIGTERM, _exit); + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, __thread_cancel_handler ); + + /* limit stack so that we NEVER have to worry */ + setrlimit(RLIMIT_STACK, (struct rlimit *)(&i)); + + /* set scheduler */ + if (td->policy!=SCHED_OTHER) { + struct sched_param sp; + sp.sched_priority=td->priority; + sched_setscheduler(td->pid,td->policy, &sp); + } + + /* thread_key glue */ + __thread_start__key(td-threads); + +#ifdef DEBUG + printf("in starter %d, parameter %8p\n", td->pid, td->func); +#endif + + if (!td->canceled) { + if (!(setjmp(td->jmp_exit))) { + td->retval=td->func(td->arg); +#ifdef DEBUG + } else { + printf("pthread_exit called in %d\n", td->pid); +#endif + } + } + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); + + /* thread_key glue */ + __thread_exit__key(td-threads); + +#ifdef DEBUG + printf("end starter %d, retval %8p\n", td->pid, td->retval); +#endif + + /* wake joined thread and put retval */ + if (td->joined) { + td->joined->retval=td->retval; + td->joined->join=0; + td->joined=0; + } + + /* execute all functions on the cleanup-stack */ + for (i=PTHREAD_MAX_CLEANUP;i;) { + if (td->cleanup_stack[--i].func) { + td->cleanup_stack[i].func(td->cleanup_stack[i].arg); + } + } + + return 0; +} + + +/* manager thread and signal handler */ +static char __manager_thread_stack[12*1024]; +static volatile _pthread_descr __manager_thread_data; +static void __manager_SIGCHLD(int sig) +{ + int pid, status, i; + + while(1) { + pid = __libc_waitpid (-1, &status, WNOHANG); + if (pid <= 0) break; + + for (i=0; i<_max_used_thread_id; i++) { + if (threads[i].pid==pid) { + __thread_cleanup(threads+i); + break; + } + } + } +} + +static void __manager_SIGTERM(int sig) +{ + __kill_all_threads(); + _exit(0); +} + +static void* __manager_thread(void *arg) +{ + struct sigaction sig_action_chld; + sig_action_chld.sa_handler = __manager_SIGCHLD; + sigemptyset(&sig_action_chld.sa_mask); + sig_action_chld.sa_flags = SA_RESTART; + + sigaction(SIGCHLD, &sig_action_chld, 0); + signal(SIGTERM, __manager_SIGTERM); + signal(SIGHUP, SIG_IGN); + + __pthread_unlock(&__manager_thread_data_go_lock); /* release init */ + while(1) { + do { + __thread_wait_some_time(); + if (getppid()<0) __manager_SIGTERM(0); + } while (__pthread_trylock(&__manager_thread_data_lock)); + + __manager_thread_data->pid = + __clone(__mthread_starter, + __manager_thread_data->stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, + __manager_thread_data); + __thread_wait_some_time(); +#ifdef DEBUG + printf("manager new thread %d\n",__manager_thread_data->pid); +#endif + __pthread_unlock(&__manager_thread_data_go_lock); /* release sender */ + } + return 0; +} + +/* pthread_create bottom half */ +int signal_manager_thread(_pthread_descr td) +{ + __NO_ASYNC_CANCEL_BEGIN; + + __pthread_lock(&__manager_thread_signal_lock); /* lock */ + + __manager_thread_data = td; + __thread_wait_some_time(); + __pthread_unlock(&__manager_thread_data_lock); /* signal manager to start */ + __thread_wait_some_time(); + __pthread_lock(&__manager_thread_data_go_lock); /* wait for manager */ + + __pthread_unlock(&__manager_thread_signal_lock); /* unlock */ + + __NO_ASYNC_CANCEL_END; + + return td->pid; +} + + +/* thread stop */ +static void __thread_main_exit() +{ + if (getpid()!=threads[0].pid) { +#ifdef DEBUG + printf("A THREAD ? %d\n",getpid()); +#endif + kill(threads[0].pid, SIGTERM); + while(1) __thread_wait_some_time(); + } +#ifdef DEBUG + else + printf("EXIT ! %d\n",getpid()); +#endif + + /* stop ALL threads */ + kill(threads[1].pid, SIGTERM); + __thread_wait_some_time(); + __kill_all_threads(); +} + +/* thread intern init */ +void __thread_init() +{ + if (atexit(__thread_main_exit)==-1) + exit(42); + +#ifdef DEBUG + printf("INIT ! %d\n",getpid()); + memset(threads,0,sizeof(threads)); +#endif + + threads[0].pid = getpid(); + + ++_max_used_thread_id; + threads[1].stack_size=sizeof(__manager_thread_stack); + threads[1].stack_addr=&__manager_thread_stack[sizeof(__manager_thread_stack)]; + threads[1].stack_begin=0; + threads[1].func=__manager_thread; + + threads[1].pid = __clone(__mthread_starter, threads[1].stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES, threads+1); + +#ifdef DEBUG + printf("manager thread @ : %d\n",threads[1].pid); +#endif + __pthread_lock(&__manager_thread_data_go_lock); /* wait for manager to be ready */ +} + diff --git a/mdk-stage1/dietlibc/libpthread/thread_internal.h b/mdk-stage1/dietlibc/libpthread/thread_internal.h new file mode 100644 index 000000000..5eb3bbd08 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/thread_internal.h @@ -0,0 +1,131 @@ +#ifndef __THREAD_INTERNAL_H__ +#define __THREAD_INTERNAL_H__ + +#include +#include +#include +#include "dietfeatures.h" +#ifndef WANT_THREAD_SAFE +#error "the diet libc is not compiled with thread safeness enabled!" +#endif + +/* cleanup */ +#define PTHREAD_MAX_CLEANUP 8 +struct thread_cleanup_t { + void (*func)(void*); + void *arg; +}; + +/* the thread descriptor / internal */ +struct _pthread_descr_struct { + /* runtime handling */ + struct _pthread_descr_struct *joined; /* a joined thread or NULL */ + + /* conditional variables */ + struct _pthread_descr_struct *waitnext; /* an other waiting thread or NULL */ + int waiting; /* internal waiting "lock" */ + + /* thread/process data */ + int pid; /* Process id */ + + int policy; /* thread scheduling policy */ + int priority; /* thread priority */ + + /* errno handling */ + int errno; + int h_errno; + + /* stack handling */ + unsigned int stack_size; /* stack size for setrlimit */ + void *stack_addr; /* stack address for clone */ + void *stack_begin; /* begin of lib-stack / lowest address (free) */ + + /* thread exit handling */ + void *retval; /* thread return value */ + int join; /* thread waits for other to return */ + jmp_buf jmp_exit; /* pthread_exit jump */ + + /* thread flags */ + int detached; /* thread is detached */ + int canceled; /* thread canceled */ + + /* cancel handling */ + int cancelstate; /* cancel state */ + int canceltype; /* type of cancellation */ + + /* thread basics */ + void* (*func) (void* arg); /* thread function */ + void* arg; /* thread argument */ + + /* create thread / manager thread lock */ + struct _pthread_fastlock *manager_lock; + + /* cleanup stack */ + struct thread_cleanup_t cleanup_stack[PTHREAD_MAX_CLEANUP]; + +} __attribute__ ((aligned(32))); + +/* thread keys */ +struct _thread_key { + int used; + void (*destructor)(const void*); + const void *tkd[PTHREAD_THREADS_MAX]; +}; + +/* internal stuff */ +int __testandset(int *spinlock); + +void __pthread_lock(struct _pthread_fastlock * lock); +int __pthread_trylock(struct _pthread_fastlock * lock); +int __pthread_unlock(struct _pthread_fastlock * lock); + +int __clone(void* (*fn)(void*), void* stack, int flags, void *arg); + +int __find_thread_id(int pid); +_pthread_descr __get_thread_struct(int id); + +_pthread_descr __thread_get_free(); +_pthread_descr __thread_self(); + +void __thread_cleanup(_pthread_descr th); + +void __thread_wait_some_time(); + +#define __NO_ASYNC_CANCEL_BEGIN { int oldtype; pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); +#define __NO_ASYNC_CANCEL_END pthread_setcanceltype(oldtype,0); pthread_testcancel(); } +#define __NO_ASYNC_CANCEL_STOP pthread_setcanceltype(oldtype,0); } + +/* manager thread stuff */ +int signal_manager_thread(_pthread_descr td); + +/* init stuff */ +extern pthread_once_t __thread_inited; +void __thread_init(); +#define __THREAD_INIT() __pthread_once(&__thread_inited, __thread_init) +#define __TEST_CANCEL() pthread_testcancel() + +/* diet libc syscalls */ + +void __libc_free(void *ptr); +void *__libc_malloc(size_t size); + +void __libc_closelog(void); +void __libc_openlog(const char *ident, int option, int facility); +void __libc_vsyslog(int priority, const char *format, va_list arg_ptr); + +pid_t __libc_fork(void); + +int __libc_close(int fd); +int __libc_creat(const char *pathname, mode_t mode); +int __libc_fcntl(int fd, int cmd, void *arg); +int __libc_fsync(int fd); +int __libc_nanosleep(const struct timespec *req, struct timespec *rem); +int __libc_open(const char *pathname, int flags, mode_t mode); +int __libc_pause(void); +int __libc_read(int fd, void *buf, size_t count); +int __libc_sigsuspend(const sigset_t *mask); +int __libc_tcdrain(int fd); +pid_t __libc_waitpid(pid_t pid, int *status, int options); +int __libc_write(int fd, const void *buf, size_t count); + +#endif diff --git a/mdk-stage1/dietlibc/libpthread/thread_key.c b/mdk-stage1/dietlibc/libpthread/thread_key.c new file mode 100644 index 000000000..b0f719fc9 --- /dev/null +++ b/mdk-stage1/dietlibc/libpthread/thread_key.c @@ -0,0 +1,41 @@ +#include +#include + +#include +#include "thread_internal.h" + +struct _pthread_fastlock __thread_keys_lock; +struct _thread_key __thread_keys[PTHREAD_KEYS_MAX]; + +void __thread_start__key(int id) +{ + int i; + + __NO_ASYNC_CANCEL_BEGIN; + __pthread_lock(&__thread_keys_lock); + + for (i=0; i