From d3d33afe9f58deb8d30c3b4e29c969b33f9c3c34 Mon Sep 17 00:00:00 2001 From: Lionel Sambuc Date: Tue, 14 Jan 2014 13:48:43 +0100 Subject: [PATCH] Experimental pthread compatibility library This patch adds pthread compatibility by using libmthread. To use this with a program using pthreads, you have to replace #include with #define _MTHREADIFY_PTHREADS #include This also changes the initialization function to be a constructor, which is implicitly called before the call to main. This allows for conformance with pthreads, while not paying a high price by checking on each mthread_* call whether the library has been initialized or not. As mthread_init is now a constructor, it also has been set as static, and relevent calls removed from programs using it. Change-Id: I2aa375db557958d2bee9a70d285aabb990c88f00 --- distrib/sets/lists/minix/mi | 3 + include/minix/mthread.h | 96 ++++++++++++++++++++- lib/Makefile | 6 +- lib/libblockdriver/driver_mt.c | 2 - lib/libmthread/Makefile | 13 +-- lib/libmthread/allocate.c | 23 +++-- lib/libmthread/attribute.c | 29 ++----- lib/libmthread/condition.c | 16 +--- lib/libmthread/event.c | 8 ++ lib/libmthread/key.c | 14 +-- lib/libmthread/mutex.c | 16 ---- lib/libmthread/proto.h | 2 - lib/libmthread/pthread_compat.c | 145 ++++++++++++++++++++++++++++++++ lib/libmthread/rwlock.c | 7 ++ lib/libmthread/scheduler.c | 11 ++- lib/libmthread/shlib_version | 2 + servers/vfs/threads.h | 1 - servers/vfs/worker.c | 1 - share/mk/bsd.lib.mk | 2 +- share/mk/bsd.prog.mk | 1 + test/test59.c | 1 - 21 files changed, 306 insertions(+), 93 deletions(-) create mode 100644 lib/libmthread/pthread_compat.c create mode 100644 lib/libmthread/shlib_version diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index b07ba24fa..96d26bc03 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -1836,6 +1836,9 @@ ./usr/lib/libm.so minix-sys ./usr/lib/libmthread.a minix-sys ./usr/lib/libmthread_pic.a minix-sys +./usr/lib/libmthread.so.0.0 minix-sys +./usr/lib/libmthread.so.0 minix-sys +./usr/lib/libmthread.so minix-sys ./usr/lib/libnetdriver.a minix-sys ./usr/lib/libnetdriver_pic.a minix-sys ./usr/lib/libnetsock.a minix-sys diff --git a/include/minix/mthread.h b/include/minix/mthread.h index 54281adc8..bb4ba56d6 100644 --- a/include/minix/mthread.h +++ b/include/minix/mthread.h @@ -71,6 +71,7 @@ typedef struct { #define MTHREAD_STACK_MIN MINSIGSTKSZ #define MTHREAD_KEYS_MAX 128 +__BEGIN_DECLS /* allocate.c */ int mthread_create(mthread_thread_t *thread, mthread_attr_t *tattr, void *(*proc)(void *), void *arg); @@ -138,8 +139,101 @@ int mthread_rwlock_wrlock(mthread_rwlock_t *rwlock); int mthread_rwlock_unlock(mthread_rwlock_t *rwlock); /* schedule.c */ -void mthread_init(void); int mthread_yield(void); void mthread_yield_all(void); +__END_DECLS +#if defined(_MTHREADIFY_PTHREADS) +typedef mthread_thread_t pthread_t; +typedef mthread_once_t pthread_once_t; +typedef mthread_key_t pthread_key_t; +typedef mthread_cond_t pthread_cond_t; +typedef mthread_mutex_t pthread_mutex_t; +typedef mthread_condattr_t pthread_condattr_t; +typedef mthread_mutexattr_t pthread_mutexattr_t; +typedef mthread_attr_t pthread_attr_t; +typedef mthread_event_t pthread_event_t; +typedef mthread_rwlock_t pthread_rwlock_t; + +/* LSC: No equivalent, so void* for now. */ +typedef void *pthread_rwlockattr_t; + +#define PTHREAD_ONCE_INIT 0 +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +__BEGIN_DECLS +/* allocate.c */ +int pthread_create(pthread_t *thread, pthread_attr_t *tattr, void + *(*proc)(void *), void *arg); +int pthread_detach(pthread_t thread); +int pthread_equal(pthread_t l, pthread_t r); +void pthread_exit(void *value); +int pthread_join(pthread_t thread, void **value); +int pthread_once(pthread_once_t *once, void (*proc)(void)); +pthread_t pthread_self(void); + +/* attribute.c */ +int pthread_attr_destroy(pthread_attr_t *tattr); +int pthread_attr_getdetachstate(pthread_attr_t *tattr, int + *detachstate); +int pthread_attr_getstack(pthread_attr_t *tattr, void **stackaddr, + size_t *stacksize); +int pthread_attr_getstacksize(pthread_attr_t *tattr, size_t *stacksize); +int pthread_attr_init(pthread_attr_t *tattr); +int pthread_attr_setdetachstate(pthread_attr_t *tattr, int detachstate); +int pthread_attr_setstack(pthread_attr_t *tattr, void *stackaddr, size_t + stacksize); +int pthread_attr_setstacksize(pthread_attr_t *tattr, size_t stacksize); + +/* condition.c */ +int pthread_cond_broadcast(pthread_cond_t *cond); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cattr); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); + +/* key.c */ +int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)); +int pthread_key_delete(pthread_key_t key); +void *pthread_getspecific(pthread_key_t key); +int pthread_setspecific(pthread_key_t key, void *value); + +/* mutex.c */ +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t + *mattr); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); + +/* event.c */ +int pthread_event_destroy(pthread_event_t *event); +int pthread_event_init(pthread_event_t *event); +int pthread_event_wait(pthread_event_t *event); +int pthread_event_fire(pthread_event_t *event); +int pthread_event_fire_all(pthread_event_t *event); + +/* rwlock.c */ +int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); +int pthread_rwlock_init(pthread_rwlock_t *rwlock, + pthread_rwlockattr_t *UNUSED(attr)); +int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); +int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); +int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); + +/* schedule.c */ +int pthread_yield(void); +int sched_yield(void); +void pthread_yield_all(void); + +/* LSC: FIXME: Maybe we should really do something with those... */ +#define pthread_mutexattr_init(u) (0) +#define pthread_mutexattr_destroy(u) (0) + +#define PTHREAD_MUTEX_RECURSIVE 0 +#define pthread_mutexattr_settype(x, y) (EINVAL) +__END_DECLS + +#endif /* defined(_MTHREADIFY_PTHREADS) */ #endif diff --git a/lib/Makefile b/lib/Makefile index 19fc36bdb..ef93459b4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -19,11 +19,14 @@ SUBDIR+= ../external/gpl3/gcc/lib/libgcc .WAIT . endif .endif -#LSC MINIX libc depends on libminlib because of minix/malloc-debug.c +#LSC MINIX libc depends on +# - libminlib because of minix/malloc-debug.c +# - libmthread because of sys/lib/libunwind SUBDIR+= libminlib SUBDIR+= .WAIT SUBDIR+= libsys +SUBDIR+= libmthread SUBDIR+= .WAIT SUBDIR+= libc @@ -43,7 +46,6 @@ SUBDIR+= libasyn \ libinputdriver \ libminc \ libminixfs \ - libmthread \ libnetdriver \ libsffs \ libtimers \ diff --git a/lib/libblockdriver/driver_mt.c b/lib/libblockdriver/driver_mt.c index 6a8a5ef67..fb1df760e 100644 --- a/lib/libblockdriver/driver_mt.c +++ b/lib/libblockdriver/driver_mt.c @@ -343,8 +343,6 @@ static void master_init(struct blockdriver *bdp) assert(bdp != NULL); assert(bdp->bdr_device != NULL); - mthread_init(); - bdtab = bdp; /* Initialize device-specific data structures. */ diff --git a/lib/libmthread/Makefile b/lib/libmthread/Makefile index f5449c433..909782ca2 100644 --- a/lib/libmthread/Makefile +++ b/lib/libmthread/Makefile @@ -5,14 +5,15 @@ LIB= mthread SRCS= \ allocate.c \ attribute.c \ - mutex.c \ - event.c \ - rwlock.c \ - misc.c \ - queue.c \ condition.c \ + event.c \ + key.c \ + misc.c \ + mutex.c \ + pthread_compat.c \ + queue.c \ + rwlock.c \ scheduler.c \ - key.c WARNS?= 4 diff --git a/lib/libmthread/allocate.c b/lib/libmthread/allocate.c index 4a6945922..776525414 100644 --- a/lib/libmthread/allocate.c +++ b/lib/libmthread/allocate.c @@ -36,7 +36,6 @@ mthread_thread_t l; mthread_thread_t r; { /* Compare two thread ids */ - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ return(l == r); } @@ -54,8 +53,6 @@ void *arg; /* Register procedure proc for execution in a thread. */ mthread_thread_t thread; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (proc == NULL) return(EINVAL); @@ -88,7 +85,6 @@ mthread_thread_t detach; * this thread are automatically freed. */ mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ if (!isokthreadid(detach)) return(ESRCH); @@ -116,8 +112,6 @@ void *value; /* Make a thread stop running and store the result value. */ mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - tcb = mthread_find_tcb(current_thread); if (tcb->m_state == MS_EXITING) /* Already stopping, nothing to do. */ @@ -226,7 +220,7 @@ static int mthread_increase_thread_pool(void) /*===========================================================================* * mthread_init * *===========================================================================*/ -void mthread_init(void) +static void __attribute__((__constructor__, __used__)) mthread_init(void) { /* Initialize thread system; allocate thread structures and start creating * threads. @@ -267,8 +261,6 @@ void **value; mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (!isokthreadid(join)) return(ESRCH); else if (join == current_thread) @@ -323,8 +315,6 @@ void (*proc)(void); { /* Run procedure proc just once */ - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (once == NULL || proc == NULL) return(EINVAL); @@ -341,8 +331,6 @@ mthread_thread_t mthread_self(void) { /* Return the thread id of the thread calling this function. */ - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - return(current_thread); } @@ -529,3 +517,12 @@ static void mthread_trampoline(void) mthread_exit(r); } +/* pthread compatibility layer. */ +__weak_alias(pthread_create, mthread_create) +__weak_alias(pthread_detach, mthread_detach) +__weak_alias(pthread_equal, mthread_equal) +__weak_alias(pthread_exit, mthread_exit) +__weak_alias(pthread_join, mthread_join) +__weak_alias(pthread_once, mthread_once) +__weak_alias(pthread_self, mthread_self) + diff --git a/lib/libmthread/attribute.c b/lib/libmthread/attribute.c index 0a96bbb2a..fe63352cc 100644 --- a/lib/libmthread/attribute.c +++ b/lib/libmthread/attribute.c @@ -46,8 +46,6 @@ mthread_attr_t *attr; { /* Invalidate attribute and deallocate resources. */ - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -72,8 +70,6 @@ mthread_attr_t *attr; /* Attribute */ /* Initialize the attribute to a known state. */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EAGAIN); else if (mthread_attr_valid(attr)) @@ -102,8 +98,6 @@ int *detachstate; /* Get detachstate of a thread attribute */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -127,8 +121,6 @@ int detachstate; /* Set detachstate of a thread attribute */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -156,8 +148,6 @@ size_t *stacksize; /* Get stack attribute */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -182,8 +172,6 @@ size_t *stacksize; /* Get stack size attribute */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -208,8 +196,6 @@ size_t stacksize; /* Set stack attribute */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -239,8 +225,6 @@ size_t stacksize; /* Set stack size attribute */ struct __mthread_attr *a; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (attr == NULL) return(EINVAL); @@ -283,8 +267,6 @@ mthread_attr_t *a; /* Check to see if attribute is on the list of valid attributes */ struct __mthread_attr *loopitem; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - loopitem = va_front; while (loopitem != NULL) { @@ -307,8 +289,6 @@ int mthread_attr_verify(void) /* Return true when no attributes are in use */ struct __mthread_attr *loopitem; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - loopitem = va_front; while (loopitem != NULL) { @@ -320,4 +300,13 @@ int mthread_attr_verify(void) } #endif +/* pthread compatibility layer. */ +__weak_alias(pthread_attr_destroy, mthread_attr_destroy) +__weak_alias(pthread_attr_getdetachstate, mthread_attr_getdetachstate) +__weak_alias(pthread_attr_getstack, mthread_attr_getstack) +__weak_alias(pthread_attr_getstacksize, mthread_attr_getstacksize) +__weak_alias(pthread_attr_init, mthread_attr_init) +__weak_alias(pthread_attr_setdetachstate, mthread_attr_setdetachstate) +__weak_alias(pthread_attr_setstack, mthread_attr_setstack) +__weak_alias(pthread_attr_setstacksize, mthread_attr_setstacksize) diff --git a/lib/libmthread/condition.c b/lib/libmthread/condition.c index ec3bcc43d..3488a5f7c 100644 --- a/lib/libmthread/condition.c +++ b/lib/libmthread/condition.c @@ -58,8 +58,6 @@ mthread_cond_t *cond; mthread_thread_t t; mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (cond == NULL) return(EINVAL); else if (!mthread_cond_valid(cond)) @@ -89,8 +87,6 @@ mthread_cond_t *cond; mthread_thread_t t; mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (cond == NULL) return(EINVAL); else if (!mthread_cond_valid(cond)) @@ -126,8 +122,6 @@ mthread_condattr_t *cattr; /* Initialize condition variable to a known state. cattr is ignored */ struct __mthread_cond *c; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (cond == NULL) return(EINVAL); else if (cattr != NULL) @@ -181,8 +175,6 @@ mthread_cond_t *cond; mthread_thread_t t; mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (cond == NULL) return(EINVAL); else if (!mthread_cond_valid(cond)) @@ -214,8 +206,6 @@ mthread_cond_t *c; /* Check to see if cond is on the list of valid conditions */ struct __mthread_cond *loopitem; - MTHREAD_CHECK_INIT(); - loopitem = vc_front; while (loopitem != NULL) { @@ -237,8 +227,6 @@ int mthread_cond_verify(void) { /* Return true in case no condition variables are in use. */ - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - return(vc_front == NULL); } #endif @@ -256,8 +244,6 @@ mthread_mutex_t *mutex; struct __mthread_cond *c; struct __mthread_mutex *m; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (cond == NULL || mutex == NULL) return(EINVAL); @@ -284,4 +270,6 @@ mthread_mutex_t *mutex; return(0); } +/* pthread compatibility layer. */ +__weak_alias(pthread_cond_init, mthread_cond_init) diff --git a/lib/libmthread/event.c b/lib/libmthread/event.c index 1dea4e87e..e26da58fc 100644 --- a/lib/libmthread/event.c +++ b/lib/libmthread/event.c @@ -124,3 +124,11 @@ mthread_event_t *event; /* The event to be fired */ return mthread_mutex_unlock(&event->mutex); } + +/* pthread compatibility layer. */ +__weak_alias(pthread_event_destroy, mthread_event_destroy) +__weak_alias(pthread_event_init, mthread_event_init) +__weak_alias(pthread_event_wait, mthread_event_wait) +__weak_alias(pthread_event_fire, mthread_event_fire) +__weak_alias(pthread_event_fire_all, mthread_event_fire_all) + diff --git a/lib/libmthread/key.c b/lib/libmthread/key.c index f07b26f45..cfb3b55f2 100644 --- a/lib/libmthread/key.c +++ b/lib/libmthread/key.c @@ -34,7 +34,6 @@ int mthread_key_create(mthread_key_t *key, void (*destructor)(void *)) */ mthread_key_t k; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ keys_used = 1; /* We do not yet allocate storage space for the values here, because we can @@ -65,8 +64,6 @@ int mthread_key_delete(mthread_key_t key) /* Free up a key, as well as any associated storage space. */ - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (key < 0 || key >= MTHREAD_KEYS_MAX || !keys[key].used) return(EINVAL); @@ -85,8 +82,6 @@ void *mthread_getspecific(mthread_key_t key) /* Get this thread's local value for the given key. The default is NULL. */ - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (key < 0 || key >= MTHREAD_KEYS_MAX || !keys[key].used) return(NULL); @@ -109,8 +104,6 @@ int mthread_setspecific(mthread_key_t key, void *value) */ void **p; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (key < 0 || key >= MTHREAD_KEYS_MAX || !keys[key].used) return(EINVAL); @@ -188,3 +181,10 @@ void mthread_cleanup_values(void) } } while (found); } + +/* pthread compatibility layer. */ +__weak_alias(pthread_key_create, mthread_key_create) +__weak_alias(pthread_key_delete, mthread_key_delete) +__weak_alias(pthread_getspecific, mthread_getspecific) +__weak_alias(pthread_setspecific, mthread_setspecific) + diff --git a/lib/libmthread/mutex.c b/lib/libmthread/mutex.c index 06009b88c..7f4683a6d 100644 --- a/lib/libmthread/mutex.c +++ b/lib/libmthread/mutex.c @@ -56,8 +56,6 @@ mthread_mutex_t *mutex; mthread_thread_t t; mthread_tcb_t *tcb; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (mutex == NULL) return(EINVAL); @@ -95,8 +93,6 @@ mthread_mutexattr_t *mattr; /* Mutex attribute */ struct __mthread_mutex *m; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (mutex == NULL) return(EAGAIN); else if (mattr != NULL) @@ -127,8 +123,6 @@ mthread_mutex_t *mutex; /* Mutex that is to be locked */ struct __mthread_mutex *m; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (mutex == NULL) return(EINVAL); @@ -180,8 +174,6 @@ mthread_mutex_t *mutex; /* Mutex that is to be locked */ struct __mthread_mutex *m; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (mutex == NULL) return(EINVAL); @@ -210,8 +202,6 @@ mthread_mutex_t *mutex; /* Mutex that is to be unlocked */ struct __mthread_mutex *m; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - if (mutex == NULL) return(EINVAL); @@ -237,8 +227,6 @@ mthread_mutex_t *m; /* Check to see if mutex is on the list of valid mutexes */ struct __mthread_mutex *loopitem; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - loopitem = vm_front; while (loopitem != NULL) { @@ -262,8 +250,6 @@ int mthread_mutex_verify(void) int r = 1; struct __mthread_mutex *loopitem; - MTHREAD_CHECK_INIT(); /* Make sure mthreads is initialized */ - #ifdef MTHREAD_STRICT loopitem = vm_front; @@ -277,5 +263,3 @@ int mthread_mutex_verify(void) return(r); } #endif - - diff --git a/lib/libmthread/proto.h b/lib/libmthread/proto.h index dc89ffbd2..7e80219e7 100644 --- a/lib/libmthread/proto.h +++ b/lib/libmthread/proto.h @@ -38,10 +38,8 @@ void mthread_init_valid_mutexes(void); #ifdef MTHREAD_STRICT int mthread_mutex_valid(mthread_mutex_t *mutex); -# define MTHREAD_CHECK_INIT() mthread_init() #else # define mthread_mutex_valid(x) ((*x)->mm_magic == MTHREAD_INIT_MAGIC) -# define MTHREAD_CHECK_INIT() #endif #ifdef MDEBUG diff --git a/lib/libmthread/pthread_compat.c b/lib/libmthread/pthread_compat.c new file mode 100644 index 000000000..00715802e --- /dev/null +++ b/lib/libmthread/pthread_compat.c @@ -0,0 +1,145 @@ +#define _MTHREADIFY_PTHREADS +#include +#include "global.h" +#include "proto.h" + +/* WARNING: + * The following works under the hypothesis that we have only green threads, + * which implies that we have no preemption, unless explicit yield or possible + * calls done to mthread functions. + * + * This has impact on the fact we do not maintain a table of currently being + * initialized mutexes or condition variables, to prevent double initialization + * and/or TOCTU problems. TOCTU could appear between the test against the + * initializer value, and the actual initialization, which could lead to double + * initialization of the same mutex AND get two threads at the same time in the + * critical section as they both hold a (different) mutex. + */ + + +/*===========================================================================* + * pthread_mutex_init * + *===========================================================================*/ +int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mattr) +{ + return mthread_mutex_init(mutex, mattr); +} + +/*===========================================================================* + * pthread_mutex_destroy * + *===========================================================================*/ +int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + if (PTHREAD_MUTEX_INITIALIZER == *mutex) { + *mutex = NULL; + return 0; + } + + return mthread_mutex_destroy(mutex); +} + +/*===========================================================================* + * pthread_mutex_lock * + *===========================================================================*/ +int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + if (PTHREAD_MUTEX_INITIALIZER == *mutex) { + mthread_mutex_init(mutex, NULL); + } + + return mthread_mutex_lock(mutex); +} + +/*===========================================================================* + * pthread_mutex_trylock * + *===========================================================================*/ +int pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + if (PTHREAD_MUTEX_INITIALIZER == *mutex) { + mthread_mutex_init(mutex, NULL); + } + + return pthread_mutex_trylock(mutex); +} + +/*===========================================================================* + * pthread_mutex_unlock * + *===========================================================================*/ +int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + if (PTHREAD_MUTEX_INITIALIZER == *mutex) { + mthread_mutex_init(mutex, NULL); + } + + return mthread_mutex_unlock(mutex); +} + +/*===========================================================================* + * pthread_cond_init * + *===========================================================================*/ +int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cattr) +{ + return mthread_cond_init(cond, cattr); +} + +/*===========================================================================* + * pthread_cond_broadcast * + *===========================================================================*/ +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + if (PTHREAD_COND_INITIALIZER == *cond) { + mthread_cond_init(cond, NULL); + } + + return mthread_cond_broadcast(cond); +} + +/*===========================================================================* + * pthread_cond_destroy * + *===========================================================================*/ +int pthread_cond_destroy(pthread_cond_t *cond) +{ + if (PTHREAD_COND_INITIALIZER == *cond) { + *cond = NULL; + return 0; + } + + return mthread_cond_destroy(cond); +} + +/*===========================================================================* + * pthread_cond_signal * + *===========================================================================*/ +int pthread_cond_signal(pthread_cond_t *cond) +{ + if (PTHREAD_COND_INITIALIZER == *cond) { + mthread_cond_init(cond, NULL); + } + + return mthread_cond_signal(cond); +} + +/*===========================================================================* + * pthread_cond_wait * + *===========================================================================*/ +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + if (PTHREAD_COND_INITIALIZER == *cond) { + mthread_cond_init(cond, NULL); + } + + return mthread_cond_wait(cond, mutex); +} + +/*===========================================================================* + * pthread_rwlock_init * + *===========================================================================*/ +int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *UNUSED(attr)) +{ + return mthread_rwlock_init(rwlock); +} + +#if !defined(__weak_alias) +#error __weak_alias is required to compile the pthread compat library +#endif + diff --git a/lib/libmthread/rwlock.c b/lib/libmthread/rwlock.c index f06c41cb6..95e255c4f 100644 --- a/lib/libmthread/rwlock.c +++ b/lib/libmthread/rwlock.c @@ -128,3 +128,10 @@ mthread_rwlock_t *rwlock; /* The rwlock to be unlocked */ return r; } + +/* pthread compatibility layer. */ +__weak_alias(pthread_rwlock_destroy, mthread_rwlock_destroy) +__weak_alias(pthread_rwlock_rdlock, mthread_rwlock_rdlock) +__weak_alias(pthread_rwlock_wrlock, mthread_rwlock_wrlock) +__weak_alias(pthread_rwlock_unlock, mthread_rwlock_unlock) + diff --git a/lib/libmthread/scheduler.c b/lib/libmthread/scheduler.c index 455525241..eb5a1c200 100644 --- a/lib/libmthread/scheduler.c +++ b/lib/libmthread/scheduler.c @@ -38,8 +38,6 @@ void mthread_schedule(void) mthread_tcb_t *new_tcb, *old_tcb; ucontext_t *new_ctx, *old_ctx; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - old_thread = current_thread; if (mthread_queue_isempty(&run_queue)) { @@ -154,8 +152,6 @@ int mthread_yield(void) mthread_tcb_t *tcb; mthread_thread_t t; - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - /* Detached threads cannot clean themselves up. This is a perfect moment to * do it */ for (t = (mthread_thread_t) 0; need_reset > 0 && t < no_threads; t++) { @@ -192,8 +188,6 @@ void mthread_yield_all(void) * this function will lead to a deadlock. */ - MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */ - if (yield_all) mthread_panic("Deadlock: two threads trying to yield_all"); yield_all = 1; @@ -214,3 +208,8 @@ void mthread_yield_all(void) yield_all = 0; } +/* pthread compatibility layer. */ +__weak_alias(pthread_yield, mthread_yield) +__weak_alias(sched_yield, mthread_yield) +__weak_alias(pthread_yield_all, mthread_yield_all) + diff --git a/lib/libmthread/shlib_version b/lib/libmthread/shlib_version new file mode 100644 index 000000000..97c9f92d6 --- /dev/null +++ b/lib/libmthread/shlib_version @@ -0,0 +1,2 @@ +major=0 +minor=0 diff --git a/servers/vfs/threads.h b/servers/vfs/threads.h index ff2f54b97..6758cd123 100644 --- a/servers/vfs/threads.h +++ b/servers/vfs/threads.h @@ -7,7 +7,6 @@ #define cond_t mthread_cond_t #define attr_t mthread_attr_t -#define threads_init mthread_init #define yield mthread_yield #define yield_all mthread_yield_all diff --git a/servers/vfs/worker.c b/servers/vfs/worker.c index b34dada80..8c1f0d771 100644 --- a/servers/vfs/worker.c +++ b/servers/vfs/worker.c @@ -24,7 +24,6 @@ void worker_init(void) struct worker_thread *wp; int i; - threads_init(); if (mthread_attr_init(&tattr) != 0) panic("failed to initialize attribute"); if (mthread_attr_setstacksize(&tattr, TH_STACKSIZE) != 0) diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index f75ef9890..40ccc9e2a 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -614,7 +614,7 @@ DPLIBC ?= ${DESTDIR}${LIBC_SO} .endif .else .if ${LIB} != "c" && ${LIB:Mgcc*} == "" \ - && ${LIB} != "minlib" && ${LIB} != "sys" && ${LIB} != "minc" # Minix-specific libs + && ${LIB} != "minlib" && ${LIB} != "sys" && ${LIB} != "minc" && ${LIB} != "mthread" # Minix-specific libs .if !empty(LIBC_SO) DPLIBC ?= ${DESTDIR}${LIBC_SO} .endif diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index 9aa3201d9..d4a390158 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -221,6 +221,7 @@ LIB${_lib:tu}= ${DESTDIR}/usr/lib/lib${_lib:S/xx/++/:S/atf_c/atf-c/}.a devman \ minc \ minlib \ + mthread \ netdriver \ sffs \ sys \ diff --git a/test/test59.c b/test/test59.c index b67d86236..8d99453ef 100644 --- a/test/test59.c +++ b/test/test59.c @@ -1116,7 +1116,6 @@ int main(void) once = MTHREAD_ONCE_INIT; start(59); - mthread_init(); test_scheduling(); test_mutex(); test_event();