pthread_rwlock_unlock

- Allow callers to try and release an unheld rwlock. Just return EPERM
  as mandated by IEEE Std 1003.1.
- Use pthread__atomic_swap_ptr() to set in the new lock value. At this
  point the lock word can't have changed.

pthread__rwlock_wrlock, pthread__rwlock_rdlock:

- Mask out the waiter bits in the lock word before checking to see if
  the current thread is about to lock against itself.
This commit is contained in:
ad 2007-09-21 16:21:54 +00:00
parent 2d6848b0e4
commit 9212747aea

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_rwlock2.c,v 1.3 2007/09/10 11:34:06 skrll Exp $ */
/* $NetBSD: pthread_rwlock2.c,v 1.4 2007/09/21 16:21:54 ad Exp $ */
/*-
* Copyright (c) 2002, 2006, 2007 The NetBSD Foundation, Inc.
@ -37,10 +37,9 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: pthread_rwlock2.c,v 1.3 2007/09/10 11:34:06 skrll Exp $");
__RCSID("$NetBSD: pthread_rwlock2.c,v 1.4 2007/09/21 16:21:54 ad Exp $");
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include "pthread.h"
@ -141,7 +140,7 @@ pthread__rwlock_rdlock(pthread_rwlock_t *ptr, const struct timespec *ts)
continue;
}
if (owner == (uintptr_t)self)
if ((owner & RW_THREAD) == (uintptr_t)self)
return EDEADLK;
/*
@ -254,7 +253,7 @@ pthread__rwlock_wrlock(pthread_rwlock_t *ptr, const struct timespec *ts)
continue;
}
if (owner == (uintptr_t)self)
if ((owner & RW_THREAD) == (uintptr_t)self)
return EDEADLK;
/*
@ -391,8 +390,9 @@ pthread_rwlock_unlock(pthread_rwlock_t *ptr)
* the read-release and write-release path similar.
*/
owner = (uintptr_t)ptr->ptr_owner;
pthread__error(EINVAL, "releasing unheld rwlock", owner != 0);
if (owner == 0) {
return EPERM;
}
if ((owner & RW_WRITE_LOCKED) != 0) {
decr = (uintptr_t)self | RW_WRITE_LOCKED;
pthread__error(EPERM, "releasing rwlock held by another thread",
@ -444,8 +444,8 @@ pthread_rwlock_unlock(pthread_rwlock_t *ptr)
* Set in the new value. The lock becomes owned
* by the writer that we are about to wake.
*/
while (!rw_cas(ptr, &owner, new))
;
(void)pthread__atomic_swap_ptr(&ptr->ptr_owner,
(void *)new);
/* Wake the writer. */
PTQ_REMOVE(&ptr->ptr_wblocked, thread, pt_sleep);
@ -471,8 +471,8 @@ pthread_rwlock_unlock(pthread_rwlock_t *ptr)
* Set in the new value. The lock becomes owned
* by the readers that we are about to wake.
*/
while (!rw_cas(ptr, &owner, new))
;
(void)pthread__atomic_swap_ptr(&ptr->ptr_owner,
(void *)new);
/* Wake up all sleeping readers. */
ptr->ptr_nreaders = 0;