d3d33afe9f
This patch adds pthread compatibility by using libmthread. To use this with a program using pthreads, you have to replace #include <pthread> with #define _MTHREADIFY_PTHREADS #include <minix/mthreads> 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
145 lines
4.6 KiB
C
145 lines
4.6 KiB
C
#define _MTHREADIFY_PTHREADS
|
|
#include <minix/mthread.h>
|
|
#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
|
|
|