#include <sys/rwlock.h>
#include <sys/errno.h>
#include <sys/debug.h>
#include <sys/param.h>
#include <sys/thread.h>
int rwlock_init(lwp_rwlock_t *, int, void *);
int rwlock_destroy(lwp_rwlock_t *);
int rw_rdlock(lwp_rwlock_t *);
int rw_wrlock(lwp_rwlock_t *);
int rw_unlock(lwp_rwlock_t *);
int rw_tryrdlock(lwp_rwlock_t *);
int rw_trywrlock(lwp_rwlock_t *);
int _rw_read_held(void *);
int _rw_write_held(void *);
void
rw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg)
{
(void) rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
rwlp->rw_owner = _KTHREAD_INVALID;
}
void
rw_destroy(krwlock_t *rwlp)
{
(void) rwlock_destroy(&rwlp->rw_lock);
rwlp->rw_owner = _KTHREAD_INVALID;
}
void
rw_enter(krwlock_t *rwlp, krw_t rw)
{
int rc;
if (rw == RW_READER) {
rc = rw_rdlock(&rwlp->rw_lock);
} else {
rc = rw_wrlock(&rwlp->rw_lock);
rwlp->rw_owner = _curthread();
}
VERIFY(rc == 0);
}
void
rw_exit(krwlock_t *rwlp)
{
if (_rw_write_held(&rwlp->rw_lock)) {
ASSERT(rwlp->rw_owner == _curthread());
rwlp->rw_owner = _KTHREAD_INVALID;
} else {
ASSERT(_rw_read_held(&rwlp->rw_lock));
}
(void) rw_unlock(&rwlp->rw_lock);
}
int
rw_tryenter(krwlock_t *rwlp, krw_t rw)
{
int rv;
if (rw == RW_WRITER) {
rv = rw_trywrlock(&rwlp->rw_lock);
if (rv == 0)
rwlp->rw_owner = _curthread();
} else
rv = rw_tryrdlock(&rwlp->rw_lock);
return ((rv == 0) ? 1 : 0);
}
int
rw_tryupgrade(krwlock_t *rwlp)
{
return (0);
}
void
rw_downgrade(krwlock_t *rwlp)
{
ASSERT(rwlp->rw_owner == _curthread());
rwlp->rw_owner = _KTHREAD_INVALID;
VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
}
int
rw_read_held(krwlock_t *rwlp)
{
return (_rw_read_held(rwlp));
}
int
rw_write_held(krwlock_t *rwlp)
{
return (_rw_write_held(rwlp));
}
int
rw_lock_held(krwlock_t *rwlp)
{
return (rw_read_held(rwlp) || rw_write_held(rwlp));
}
void *
rw_owner(krwlock_t *rwlp)
{
return (rwlp->rw_owner);
}