version 1.40, 2020/05/16 22:53:37 |
version 1.41, 2020/06/01 11:44:59 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/*- |
/*- |
* Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc. |
* Copyright (c) 2002, 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc. |
* All rights reserved. |
* All rights reserved. |
* |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* This code is derived from software contributed to The NetBSD Foundation |
Line 56 __RCSID("$NetBSD$"); |
|
Line 56 __RCSID("$NetBSD$"); |
|
|
|
static int pthread__rwlock_wrlock(pthread_rwlock_t *, const struct timespec *); |
static int pthread__rwlock_wrlock(pthread_rwlock_t *, const struct timespec *); |
static int pthread__rwlock_rdlock(pthread_rwlock_t *, const struct timespec *); |
static int pthread__rwlock_rdlock(pthread_rwlock_t *, const struct timespec *); |
static void pthread__rwlock_early(void *); |
static void pthread__rwlock_early(pthread_t, pthread_rwlock_t *, |
|
pthread_mutex_t *); |
|
|
int _pthread_rwlock_held_np(pthread_rwlock_t *); |
int _pthread_rwlock_held_np(pthread_rwlock_t *); |
int _pthread_rwlock_rdheld_np(pthread_rwlock_t *); |
int _pthread_rwlock_rdheld_np(pthread_rwlock_t *); |
Line 218 pthread__rwlock_rdlock(pthread_rwlock_t |
|
Line 219 pthread__rwlock_rdlock(pthread_rwlock_t |
|
ptr->ptr_nreaders++; |
ptr->ptr_nreaders++; |
self->pt_rwlocked = _RW_WANT_READ; |
self->pt_rwlocked = _RW_WANT_READ; |
self->pt_sleepobj = &ptr->ptr_rblocked; |
self->pt_sleepobj = &ptr->ptr_rblocked; |
self->pt_early = pthread__rwlock_early; |
|
error = pthread__park(self, interlock, &ptr->ptr_rblocked, |
error = pthread__park(self, interlock, &ptr->ptr_rblocked, |
ts, 0); |
ts, 0); |
|
|
|
if (self->pt_sleepobj != NULL) { |
|
pthread__rwlock_early(self, ptr, interlock); |
|
} |
|
|
/* Did we get the lock? */ |
/* Did we get the lock? */ |
if (self->pt_rwlocked == _RW_LOCKED) { |
if (self->pt_rwlocked == _RW_LOCKED) { |
#ifndef PTHREAD__ATOMIC_IS_MEMBAR |
#ifndef PTHREAD__ATOMIC_IS_MEMBAR |
Line 339 pthread__rwlock_wrlock(pthread_rwlock_t |
|
Line 343 pthread__rwlock_wrlock(pthread_rwlock_t |
|
PTQ_INSERT_TAIL(&ptr->ptr_wblocked, self, pt_sleep); |
PTQ_INSERT_TAIL(&ptr->ptr_wblocked, self, pt_sleep); |
self->pt_rwlocked = _RW_WANT_WRITE; |
self->pt_rwlocked = _RW_WANT_WRITE; |
self->pt_sleepobj = &ptr->ptr_wblocked; |
self->pt_sleepobj = &ptr->ptr_wblocked; |
self->pt_early = pthread__rwlock_early; |
|
error = pthread__park(self, interlock, &ptr->ptr_wblocked, |
error = pthread__park(self, interlock, &ptr->ptr_wblocked, |
ts, 0); |
ts, 0); |
|
|
|
if (self->pt_sleepobj != NULL) { |
|
pthread__rwlock_early(self, ptr, interlock); |
|
} |
|
|
/* Did we get the lock? */ |
/* Did we get the lock? */ |
if (self->pt_rwlocked == _RW_LOCKED) { |
if (self->pt_rwlocked == _RW_LOCKED) { |
#ifndef PTHREAD__ATOMIC_IS_MEMBAR |
#ifndef PTHREAD__ATOMIC_IS_MEMBAR |
Line 358 pthread__rwlock_wrlock(pthread_rwlock_t |
|
Line 365 pthread__rwlock_wrlock(pthread_rwlock_t |
|
} |
} |
} |
} |
|
|
|
|
int |
int |
pthread_rwlock_trywrlock(pthread_rwlock_t *ptr) |
pthread_rwlock_trywrlock(pthread_rwlock_t *ptr) |
{ |
{ |
Line 563 pthread_rwlock_unlock(pthread_rwlock_t * |
|
Line 569 pthread_rwlock_unlock(pthread_rwlock_t * |
|
* removed from the waiters lists. |
* removed from the waiters lists. |
*/ |
*/ |
static void |
static void |
pthread__rwlock_early(void *obj) |
pthread__rwlock_early(pthread_t self, pthread_rwlock_t *ptr, |
|
pthread_mutex_t *interlock) |
{ |
{ |
uintptr_t owner, set, new, next; |
uintptr_t owner, set, newval, next; |
pthread_rwlock_t *ptr; |
pthread_queue_t *queue; |
pthread_t self; |
|
u_int off; |
|
|
|
self = pthread__self(); |
pthread_mutex_lock(interlock); |
|
if ((queue = self->pt_sleepobj) == NULL) { |
switch (self->pt_rwlocked) { |
pthread_mutex_unlock(interlock); |
case _RW_WANT_READ: |
return; |
off = offsetof(pthread_rwlock_t, ptr_rblocked); |
|
break; |
|
case _RW_WANT_WRITE: |
|
off = offsetof(pthread_rwlock_t, ptr_wblocked); |
|
break; |
|
default: |
|
pthread__errorfunc(__FILE__, __LINE__, __func__, |
|
"bad value of pt_rwlocked"); |
|
off = 0; |
|
/* NOTREACHED */ |
|
break; |
|
} |
} |
|
PTQ_REMOVE(queue, self, pt_sleep); |
/* LINTED mind your own business */ |
self->pt_sleepobj = NULL; |
ptr = (pthread_rwlock_t *)((uint8_t *)obj - off); |
|
owner = (uintptr_t)ptr->ptr_owner; |
owner = (uintptr_t)ptr->ptr_owner; |
|
|
if ((owner & RW_THREAD) == 0) { |
if ((owner & RW_THREAD) == 0) { |
Line 604 pthread__rwlock_early(void *obj) |
|
Line 597 pthread__rwlock_early(void *obj) |
|
set = 0; |
set = 0; |
|
|
for (;; owner = next) { |
for (;; owner = next) { |
new = (owner & ~(RW_HAS_WAITERS | RW_WRITE_WANTED)) | set; |
newval = (owner & ~(RW_HAS_WAITERS | RW_WRITE_WANTED)) | set; |
next = rw_cas(ptr, owner, new); |
next = rw_cas(ptr, owner, newval); |
if (owner == next) |
if (owner == next) |
break; |
break; |
} |
} |
|
pthread_mutex_unlock(interlock); |
} |
} |
|
|
int |
int |