minix/lib/libmthread/rwlock.c
Lionel Sambuc d3d33afe9f 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 <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
2014-07-28 17:05:08 +02:00

137 lines
3.2 KiB
C

#include <minix/mthread.h>
#include "global.h"
/*===========================================================================*
* mthread_rwlock_init *
*===========================================================================*/
int mthread_rwlock_init(rwlock)
mthread_rwlock_t *rwlock; /* The rwlock to be initialized */
{
/* Initialize a readers/writer lock. */
int r;
if (!rwlock)
return EINVAL;
rwlock->writer = NO_THREAD;
rwlock->readers = 0;
r = mthread_mutex_init(&rwlock->queue, NULL);
if (r != 0)
return r;
r = mthread_event_init(&rwlock->drain);
if (r != 0)
mthread_mutex_destroy(&rwlock->queue);
return r;
}
/*===========================================================================*
* mthread_rwlock_destroy *
*===========================================================================*/
int mthread_rwlock_destroy(rwlock)
mthread_rwlock_t *rwlock; /* The rwlock to be destroyed */
{
/* Destroy a readers/writer lock. */
int r;
if (!rwlock)
return EINVAL;
assert(rwlock->writer == NO_THREAD);
assert(rwlock->readers == 0);
r = mthread_event_destroy(&rwlock->drain);
if (r != 0)
return r;
return mthread_mutex_destroy(&rwlock->queue);
}
/*===========================================================================*
* mthread_rwlock_rdlock *
*===========================================================================*/
int mthread_rwlock_rdlock(rwlock)
mthread_rwlock_t *rwlock; /* The rwlock to be read locked */
{
/* Acquire a reader lock. */
int r;
if (!rwlock)
return EINVAL;
r = mthread_mutex_lock(&rwlock->queue);
if (r != 0)
return r;
r = mthread_mutex_unlock(&rwlock->queue);
if (r != 0)
return r;
rwlock->readers++;
return 0;
}
/*===========================================================================*
* mthread_rwlock_wrlock *
*===========================================================================*/
int mthread_rwlock_wrlock(rwlock)
mthread_rwlock_t *rwlock; /* The rwlock to be write locked */
{
/* Acquire a writer lock. */
int r;
if (!rwlock)
return EINVAL;
r = mthread_mutex_lock(&rwlock->queue);
if (r != 0)
return r;
rwlock->writer = current_thread;
if (rwlock->readers > 0)
r = mthread_event_wait(&rwlock->drain);
if (r == 0)
assert(rwlock->readers == 0);
return r;
}
/*===========================================================================*
* mthread_rwlock_unlock *
*===========================================================================*/
int mthread_rwlock_unlock(rwlock)
mthread_rwlock_t *rwlock; /* The rwlock to be unlocked */
{
/* Release a lock. */
int r;
r = 0;
if (!rwlock)
return EINVAL;
if (rwlock->writer == current_thread) {
rwlock->writer = NO_THREAD;
r = mthread_mutex_unlock(&rwlock->queue);
} else {
assert(rwlock->readers > 0);
rwlock->readers--;
if (rwlock->readers == 0 && rwlock->writer != NO_THREAD)
r = mthread_event_fire(&rwlock->drain);
}
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)