Track mutex/rwlock/condvar status. This allows us to get rid of
the pthread_np calls which will not likely exist on other platforms.
This commit is contained in:
parent
f8474b32a7
commit
a25e3b17bc
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rumpuser_pth.c,v 1.23 2009/01/07 22:50:08 pooka Exp $ */
|
||||
/* $NetBSD: rumpuser_pth.c,v 1.24 2009/01/10 22:28:42 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
|
||||
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_pth.c,v 1.23 2009/01/07 22:50:08 pooka Exp $");
|
||||
__RCSID("$NetBSD: rumpuser_pth.c,v 1.24 2009/01/10 22:28:42 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -65,16 +65,51 @@ do { \
|
|||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define RUMTX_INCRECURSION(mtx) ((mtx)->recursion++)
|
||||
#define RUMTX_DECRECURSION(mtx) ((mtx)->recursion--)
|
||||
struct rumpuser_mtx {
|
||||
pthread_mutex_t pthmtx;
|
||||
pthread_t owner;
|
||||
unsigned recursion;
|
||||
};
|
||||
|
||||
#define RURW_SETWRITE(rw) \
|
||||
do { \
|
||||
assert(rw->readers == 0 && rw->writer == NULL); \
|
||||
rw->writer = pthread_self(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define RURW_CLRWRITE(rw) \
|
||||
do { \
|
||||
assert(rw->readers == 0 && rw->writer != NULL); \
|
||||
rw->writer = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define RURW_INCREAD(rw) \
|
||||
do { \
|
||||
assert(rw->writer == NULL); \
|
||||
pthread_spin_lock(&rw->spin); \
|
||||
((rw)->readers++); \
|
||||
pthread_spin_unlock(&rw->spin); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define RURW_DECREAD(rw) \
|
||||
do { \
|
||||
assert(rw->readers > 0 && rw->writer == NULL); \
|
||||
pthread_spin_lock(&rw->spin); \
|
||||
((rw)->readers--); \
|
||||
pthread_spin_unlock(&rw->spin); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define RURW_AMWRITER(rw) (rw->writer == pthread_self())
|
||||
#define RURW_HASREAD(rw) (rw->readers != 0)
|
||||
|
||||
struct rumpuser_rw {
|
||||
pthread_rwlock_t pthrw;
|
||||
pthread_spinlock_t spin;
|
||||
unsigned readers;
|
||||
pthread_t writer;
|
||||
};
|
||||
|
||||
struct rumpuser_cv {
|
||||
pthread_cond_t pthcv;
|
||||
int nwaiters;
|
||||
};
|
||||
|
||||
struct rumpuser_mtx rumpuser_aio_mtx;
|
||||
|
@ -181,6 +216,8 @@ rumpuser_mutex_init(struct rumpuser_mtx **mtx)
|
|||
{
|
||||
NOFAIL(*mtx = malloc(sizeof(struct rumpuser_mtx)));
|
||||
NOFAIL_ERRNO(pthread_mutex_init(&((*mtx)->pthmtx), NULL));
|
||||
(*mtx)->owner = NULL;
|
||||
(*mtx)->recursion = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -193,28 +230,59 @@ rumpuser_mutex_recursive_init(struct rumpuser_mtx **mtx)
|
|||
|
||||
NOFAIL(*mtx = malloc(sizeof(struct rumpuser_mtx)));
|
||||
NOFAIL_ERRNO(pthread_mutex_init(&((*mtx)->pthmtx), &mattr));
|
||||
(*mtx)->owner = NULL;
|
||||
(*mtx)->recursion = 0;
|
||||
|
||||
pthread_mutexattr_destroy(&mattr);
|
||||
}
|
||||
|
||||
static void
|
||||
mtxenter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
if (mtx->recursion++ == 0) {
|
||||
assert(mtx->owner == NULL);
|
||||
mtx->owner = pthread_self();
|
||||
} else {
|
||||
assert(mtx->owner == pthread_self());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mtxexit(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
assert(mtx->owner != NULL);
|
||||
if (--mtx->recursion == 0)
|
||||
mtx->owner = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(pthread_mutex_lock(&mtx->pthmtx)));
|
||||
mtxenter(mtx);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
int rv;
|
||||
|
||||
return pthread_mutex_trylock(&mtx->pthmtx) == 0;
|
||||
rv = pthread_mutex_trylock(&mtx->pthmtx);
|
||||
if (rv == 0) {
|
||||
mtxenter(mtx);
|
||||
}
|
||||
|
||||
return rv == 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
mtxexit(mtx);
|
||||
NOFAIL_ERRNO(pthread_mutex_unlock(&mtx->pthmtx));
|
||||
}
|
||||
|
||||
|
@ -230,7 +298,7 @@ int
|
|||
rumpuser_mutex_held(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
return pthread_mutex_held_np(&mtx->pthmtx);
|
||||
return mtx->owner == pthread_self();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -239,32 +307,50 @@ rumpuser_rw_init(struct rumpuser_rw **rw)
|
|||
|
||||
NOFAIL(*rw = malloc(sizeof(struct rumpuser_rw)));
|
||||
NOFAIL_ERRNO(pthread_rwlock_init(&((*rw)->pthrw), NULL));
|
||||
NOFAIL_ERRNO(pthread_spin_init(&((*rw)->spin), PTHREAD_PROCESS_SHARED));
|
||||
(*rw)->readers = 0;
|
||||
(*rw)->writer = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_enter(struct rumpuser_rw *rw, int write)
|
||||
{
|
||||
|
||||
if (write)
|
||||
if (write) {
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(pthread_rwlock_wrlock(&rw->pthrw)));
|
||||
else
|
||||
RURW_SETWRITE(rw);
|
||||
} else {
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(pthread_rwlock_rdlock(&rw->pthrw)));
|
||||
RURW_INCREAD(rw);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryenter(struct rumpuser_rw *rw, int write)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (write)
|
||||
return pthread_rwlock_trywrlock(&rw->pthrw) == 0;
|
||||
else
|
||||
return pthread_rwlock_tryrdlock(&rw->pthrw) == 0;
|
||||
if (write) {
|
||||
rv = pthread_rwlock_trywrlock(&rw->pthrw);
|
||||
if (rv == 0)
|
||||
RURW_SETWRITE(rw);
|
||||
} else {
|
||||
rv = pthread_rwlock_tryrdlock(&rw->pthrw);
|
||||
if (rv == 0)
|
||||
RURW_INCREAD(rw);
|
||||
}
|
||||
|
||||
return rv == 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_exit(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
if (RURW_AMWRITER(rw))
|
||||
RURW_CLRWRITE(rw);
|
||||
else
|
||||
RURW_DECREAD(rw);
|
||||
NOFAIL_ERRNO(pthread_rwlock_unlock(&rw->pthrw));
|
||||
}
|
||||
|
||||
|
@ -273,6 +359,7 @@ rumpuser_rw_destroy(struct rumpuser_rw *rw)
|
|||
{
|
||||
|
||||
NOFAIL_ERRNO(pthread_rwlock_destroy(&rw->pthrw));
|
||||
NOFAIL_ERRNO(pthread_spin_destroy(&rw->spin));
|
||||
free(rw);
|
||||
}
|
||||
|
||||
|
@ -280,21 +367,21 @@ int
|
|||
rumpuser_rw_held(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
return pthread_rwlock_held_np(&rw->pthrw);
|
||||
return rw->readers || rw->writer;
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_rdheld(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
return pthread_rwlock_rdheld_np(&rw->pthrw);
|
||||
return RURW_HASREAD(rw);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_wrheld(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
return pthread_rwlock_wrheld_np(&rw->pthrw);
|
||||
return RURW_AMWRITER(rw);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -303,6 +390,7 @@ rumpuser_cv_init(struct rumpuser_cv **cv)
|
|||
|
||||
NOFAIL(*cv = malloc(sizeof(struct rumpuser_cv)));
|
||||
NOFAIL_ERRNO(pthread_cond_init(&((*cv)->pthcv), NULL));
|
||||
(*cv)->nwaiters = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -317,7 +405,12 @@ void
|
|||
rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
cv->nwaiters++;
|
||||
assert(mtx->recursion == 1);
|
||||
mtxexit(mtx);
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx)));
|
||||
mtxenter(mtx);
|
||||
cv->nwaiters--;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -333,7 +426,11 @@ rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
|
|||
ts.tv_sec += ts.tv_nsec / 1000000000;
|
||||
ts.tv_nsec %= 1000000000;
|
||||
|
||||
cv->nwaiters++;
|
||||
mtxexit(mtx);
|
||||
KLOCK_WRAP(rv = pthread_cond_timedwait(&cv->pthcv, &mtx->pthmtx, &ts));
|
||||
mtxenter(mtx);
|
||||
cv->nwaiters--;
|
||||
if (rv != 0 && rv != ETIMEDOUT)
|
||||
abort();
|
||||
|
||||
|
@ -360,7 +457,7 @@ int
|
|||
rumpuser_cv_has_waiters(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
return pthread_cond_has_waiters_np(&cv->pthcv);
|
||||
return cv->nwaiters;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue