version 1.13.4.1, 2008/09/16 18:49:33 |
version 1.14, 2006/12/23 05:14:47 |
Line 44 __RCSID("$NetBSD$"); |
|
Line 44 __RCSID("$NetBSD$"); |
|
#include "pthread.h" |
#include "pthread.h" |
#include "pthread_int.h" |
#include "pthread_int.h" |
|
|
|
#ifdef PTHREAD_SA |
static void pthread_rwlock__callback(void *); |
static void pthread_rwlock__callback(void *); |
|
#endif |
|
|
__strong_alias(__libc_rwlock_init,pthread_rwlock_init) |
__strong_alias(__libc_rwlock_init,pthread_rwlock_init) |
__strong_alias(__libc_rwlock_rdlock,pthread_rwlock_rdlock) |
__strong_alias(__libc_rwlock_rdlock,pthread_rwlock_rdlock) |
Line 116 pthread_rwlock_rdlock(pthread_rwlock_t * |
|
Line 118 pthread_rwlock_rdlock(pthread_rwlock_t * |
|
*/ |
*/ |
while ((rwlock->ptr_writer != NULL) || |
while ((rwlock->ptr_writer != NULL) || |
(!PTQ_EMPTY(&rwlock->ptr_wblocked))) { |
(!PTQ_EMPTY(&rwlock->ptr_wblocked))) { |
|
#ifdef PTHREAD_SA |
PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep); |
PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep); |
/* Locking a rwlock is not a cancellation point; don't check */ |
/* Locking a rwlock is not a cancellation point; don't check */ |
pthread_spinlock(self, &self->pt_statelock); |
pthread_spinlock(self, &self->pt_statelock); |
if (pthread_check_defsig(self)) { |
|
pthread_spinunlock(self, &self->pt_statelock); |
|
PTQ_REMOVE(&rwlock->ptr_rblocked, self, pt_sleep); |
|
pthread_spinunlock(self, &rwlock->ptr_interlock); |
|
pthread__signal_deferred(self, self); |
|
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
continue; |
|
} |
|
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_sleepobj = rwlock; |
self->pt_sleepobj = rwlock; |
self->pt_sleepq = &rwlock->ptr_rblocked; |
self->pt_sleepq = &rwlock->ptr_rblocked; |
Line 135 pthread_rwlock_rdlock(pthread_rwlock_t * |
|
Line 130 pthread_rwlock_rdlock(pthread_rwlock_t * |
|
pthread__block(self, &rwlock->ptr_interlock); |
pthread__block(self, &rwlock->ptr_interlock); |
/* interlock is not held when we return */ |
/* interlock is not held when we return */ |
pthread_spinlock(self, &rwlock->ptr_interlock); |
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
#else /* PTHREAD_SA */ |
|
(void)pthread__park(self, &rwlock->ptr_interlock, rwlock, |
|
&rwlock->ptr_rblocked, NULL, 1); |
|
#endif /* PTHREAD_SA */ |
} |
} |
|
|
rwlock->ptr_nreaders++; |
rwlock->ptr_nreaders++; |
Line 203 pthread_rwlock_wrlock(pthread_rwlock_t * |
|
Line 202 pthread_rwlock_wrlock(pthread_rwlock_t * |
|
return EDEADLK; |
return EDEADLK; |
} |
} |
#endif |
#endif |
|
#ifdef PTHREAD_SA |
PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep); |
PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep); |
/* Locking a rwlock is not a cancellation point; don't check */ |
/* Locking a rwlock is not a cancellation point; don't check */ |
pthread_spinlock(self, &self->pt_statelock); |
pthread_spinlock(self, &self->pt_statelock); |
if (pthread_check_defsig(self)) { |
|
pthread_spinunlock(self, &self->pt_statelock); |
|
PTQ_REMOVE(&rwlock->ptr_wblocked, self, pt_sleep); |
|
pthread_spinunlock(self, &rwlock->ptr_interlock); |
|
pthread__signal_deferred(self, self); |
|
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
continue; |
|
} |
|
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_sleepobj = rwlock; |
self->pt_sleepobj = rwlock; |
self->pt_sleepq = &rwlock->ptr_wblocked; |
self->pt_sleepq = &rwlock->ptr_wblocked; |
Line 222 pthread_rwlock_wrlock(pthread_rwlock_t * |
|
Line 214 pthread_rwlock_wrlock(pthread_rwlock_t * |
|
pthread__block(self, &rwlock->ptr_interlock); |
pthread__block(self, &rwlock->ptr_interlock); |
/* interlock is not held when we return */ |
/* interlock is not held when we return */ |
pthread_spinlock(self, &rwlock->ptr_interlock); |
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
#else |
|
(void)pthread__park(self, &rwlock->ptr_interlock, rwlock, |
|
&rwlock->ptr_wblocked, NULL, 1); |
|
#endif |
} |
} |
|
|
rwlock->ptr_writer = self; |
rwlock->ptr_writer = self; |
Line 269 pthread_rwlock_timedrdlock(pthread_rwloc |
|
Line 265 pthread_rwlock_timedrdlock(pthread_rwloc |
|
const struct timespec *abs_timeout) |
const struct timespec *abs_timeout) |
{ |
{ |
pthread_t self; |
pthread_t self; |
|
#ifdef PTHREAD_SA |
struct pthread_rwlock__waitarg wait; |
struct pthread_rwlock__waitarg wait; |
struct pt_alarm_t alarm; |
struct pt_alarm_t alarm; |
|
#endif |
int retval; |
int retval; |
|
|
#ifdef ERRORCHECK |
#ifdef ERRORCHECK |
Line 300 pthread_rwlock_timedrdlock(pthread_rwloc |
|
Line 298 pthread_rwlock_timedrdlock(pthread_rwloc |
|
retval = 0; |
retval = 0; |
while ((retval == 0) && ((rwlock->ptr_writer != NULL) || |
while ((retval == 0) && ((rwlock->ptr_writer != NULL) || |
(!PTQ_EMPTY(&rwlock->ptr_wblocked)))) { |
(!PTQ_EMPTY(&rwlock->ptr_wblocked)))) { |
|
#ifdef PTHREAD_SA |
wait.ptw_thread = self; |
wait.ptw_thread = self; |
wait.ptw_rwlock = rwlock; |
wait.ptw_rwlock = rwlock; |
wait.ptw_queue = &rwlock->ptr_rblocked; |
wait.ptw_queue = &rwlock->ptr_rblocked; |
/* Locking a rwlock is not a cancellation point; don't check */ |
|
pthread_spinlock(self, &self->pt_statelock); |
|
if (pthread_check_defsig(self)) { |
|
pthread_spinunlock(self, &self->pt_statelock); |
|
pthread_spinunlock(self, &rwlock->ptr_interlock); |
|
pthread__signal_deferred(self, self); |
|
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
continue; |
|
} |
|
pthread__alarm_add(self, &alarm, abs_timeout, |
pthread__alarm_add(self, &alarm, abs_timeout, |
pthread_rwlock__callback, &wait); |
pthread_rwlock__callback, &wait); |
PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep); |
PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep); |
|
/* Locking a rwlock is not a cancellation point; don't check */ |
|
pthread_spinlock(self, &self->pt_statelock); |
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_sleepobj = rwlock; |
self->pt_sleepobj = rwlock; |
self->pt_sleepq = &rwlock->ptr_rblocked; |
self->pt_sleepq = &rwlock->ptr_rblocked; |
Line 326 pthread_rwlock_timedrdlock(pthread_rwloc |
|
Line 318 pthread_rwlock_timedrdlock(pthread_rwloc |
|
if (pthread__alarm_fired(&alarm)) |
if (pthread__alarm_fired(&alarm)) |
retval = ETIMEDOUT; |
retval = ETIMEDOUT; |
pthread_spinlock(self, &rwlock->ptr_interlock); |
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
#else |
|
retval = pthread__park(self, &rwlock->ptr_interlock, rwlock, |
|
&rwlock->ptr_rblocked, abs_timeout, 1); |
|
#endif |
} |
} |
|
|
/* One last chance to get the lock, in case it was released between |
/* One last chance to get the lock, in case it was released between |
|
|
pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, |
pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, |
const struct timespec *abs_timeout) |
const struct timespec *abs_timeout) |
{ |
{ |
|
#ifdef PTHREAD_SA |
struct pthread_rwlock__waitarg wait; |
struct pthread_rwlock__waitarg wait; |
struct pt_alarm_t alarm; |
struct pt_alarm_t alarm; |
|
#endif |
pthread_t self; |
pthread_t self; |
int retval; |
int retval; |
extern int pthread__started; |
extern int pthread__started; |
Line 384 pthread_rwlock_timedwrlock(pthread_rwloc |
|
Line 382 pthread_rwlock_timedwrlock(pthread_rwloc |
|
return EDEADLK; |
return EDEADLK; |
} |
} |
#endif |
#endif |
|
#ifdef PTHREAD_SA |
wait.ptw_thread = self; |
wait.ptw_thread = self; |
wait.ptw_rwlock = rwlock; |
wait.ptw_rwlock = rwlock; |
wait.ptw_queue = &rwlock->ptr_wblocked; |
wait.ptw_queue = &rwlock->ptr_wblocked; |
/* Locking a rwlock is not a cancellation point; don't check */ |
|
pthread_spinlock(self, &self->pt_statelock); |
|
if (pthread_check_defsig(self)) { |
|
pthread_spinunlock(self, &self->pt_statelock); |
|
pthread_spinunlock(self, &rwlock->ptr_interlock); |
|
pthread__signal_deferred(self, self); |
|
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
continue; |
|
} |
|
pthread__alarm_add(self, &alarm, abs_timeout, |
pthread__alarm_add(self, &alarm, abs_timeout, |
pthread_rwlock__callback, &wait); |
pthread_rwlock__callback, &wait); |
PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep); |
PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep); |
|
/* Locking a rwlock is not a cancellation point; don't check */ |
|
pthread_spinlock(self, &self->pt_statelock); |
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_state = PT_STATE_BLOCKED_QUEUE; |
self->pt_sleepobj = rwlock; |
self->pt_sleepobj = rwlock; |
self->pt_sleepq = &rwlock->ptr_wblocked; |
self->pt_sleepq = &rwlock->ptr_wblocked; |
Line 410 pthread_rwlock_timedwrlock(pthread_rwloc |
|
Line 402 pthread_rwlock_timedwrlock(pthread_rwloc |
|
if (pthread__alarm_fired(&alarm)) |
if (pthread__alarm_fired(&alarm)) |
retval = ETIMEDOUT; |
retval = ETIMEDOUT; |
pthread_spinlock(self, &rwlock->ptr_interlock); |
pthread_spinlock(self, &rwlock->ptr_interlock); |
|
#else |
|
retval = pthread__park(self, &rwlock->ptr_interlock, rwlock, |
|
&rwlock->ptr_wblocked, abs_timeout, 1); |
|
#endif |
} |
} |
|
|
if ((rwlock->ptr_nreaders == 0) && (rwlock->ptr_writer == NULL)) { |
if ((rwlock->ptr_nreaders == 0) && (rwlock->ptr_writer == NULL)) { |
Line 422 pthread_rwlock_timedwrlock(pthread_rwloc |
|
Line 418 pthread_rwlock_timedwrlock(pthread_rwloc |
|
} |
} |
|
|
|
|
|
#ifdef PTHREAD_SA |
static void |
static void |
pthread_rwlock__callback(void *arg) |
pthread_rwlock__callback(void *arg) |
{ |
{ |
Line 440 pthread_rwlock__callback(void *arg) |
|
Line 437 pthread_rwlock__callback(void *arg) |
|
*/ |
*/ |
if (a->ptw_thread->pt_state == PT_STATE_BLOCKED_QUEUE) { |
if (a->ptw_thread->pt_state == PT_STATE_BLOCKED_QUEUE) { |
PTQ_REMOVE(a->ptw_queue, a->ptw_thread, pt_sleep); |
PTQ_REMOVE(a->ptw_queue, a->ptw_thread, pt_sleep); |
pthread__sched(self, a->ptw_thread, 0); |
pthread__sched(self, a->ptw_thread); |
} |
} |
pthread_spinunlock(self, &a->ptw_rwlock->ptr_interlock); |
pthread_spinunlock(self, &a->ptw_rwlock->ptr_interlock); |
|
|
} |
} |
|
#endif |
|
|
|
|
int |
int |
Line 497 pthread_rwlock_unlock(pthread_rwlock_t * |
|
Line 495 pthread_rwlock_unlock(pthread_rwlock_t * |
|
#endif |
#endif |
} |
} |
|
|
|
#ifdef PTHREAD_SA |
if (writer != NULL) |
if (writer != NULL) |
pthread__sched(self, writer, 0); |
pthread__sched(self, writer); |
else |
else |
pthread__sched_sleepers(self, &blockedq); |
pthread__sched_sleepers(self, &blockedq); |
|
|
pthread_spinunlock(self, &rwlock->ptr_interlock); |
pthread_spinunlock(self, &rwlock->ptr_interlock); |
|
#else /* PTHREAD_SA */ |
|
if (writer != NULL) |
|
pthread__unpark(self, &rwlock->ptr_interlock, rwlock, writer); |
|
else |
|
pthread__unpark_all(self, &rwlock->ptr_interlock, rwlock, |
|
&blockedq); |
|
#endif /* PTHREAD_SA */ |
|
|
return 0; |
return 0; |
} |
} |