From d82e4c7bb231c9e0f835bd46467563ac3b56cebe Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 26 Jun 2000 01:47:56 +0000 Subject: Update. 2000-06-25 Ulrich Drepper * Makefile (tests): Add ex10. Add rules to build it. * Versions [GLIBC_2.2] (libpthread): Add pthread_mutex_timedlock, pthread_rwlock_timedrdlock, and pthread_rwlock_timedwrlock. * condvar.c (pthread_cond_wait): Allow mutex of kind PTHREAD_MUTEX_TIMED_NP. (pthread_cond_timedwait_relative): Likewise. * mutex.c (__pthread_mutex_init): Default is PTHREAD_MUTEX_TIMED_NP. (__pthread_mutex_trylock): Use __pthread_alt_trylock for PTHREAD_MUTEX_ERRORCHECK_NP. Handle PTHREAD_MUTEX_TIMED_NP. (__pthread_mutex_lock): Use __pthread_alt_lock for PTHREAD_MUTEX_ERRORCHECK_NP. Handle PTHREAD_MUTEX_TIMED_NP. (__pthread_mutex_timedlock): New function. (__pthread_mutex_unlock): Use __pthread_alt_unlock for PTHREAD_MUTEX_ERRORCHECK_NP. Handle PTHREAD_MUTEX_TIMED_NP. (__pthread_mutexattr_init): Use PTHREAD_MUTEX_TIMED_NP. (__pthread_mutexattr_settype): Allow PTHREAD_MUTEX_TIMED_NP. * spinlock.c: Implement alternate fastlocks. * spinlock.h: Add prototypes. * Examples/ex10.c: New file. * sysdeps/pthread/pthread.h: Add prototypes for new functions. Patch by Kaz Kylheku . * rwlock.c (__pthread_rwlock_rdlock): Optimize loop a bit. (__pthread_rwlock_timedrdlock): New function. (__pthread_rwlock_timedwrlock): New function. Use laternate fastlock function everywhere. --- linuxthreads/rwlock.c | 121 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 22 deletions(-) (limited to 'linuxthreads/rwlock.c') diff --git a/linuxthreads/rwlock.c b/linuxthreads/rwlock.c index 9da87d25d1..6ee5b62247 100644 --- a/linuxthreads/rwlock.c +++ b/linuxthreads/rwlock.c @@ -184,7 +184,7 @@ rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, int __pthread_rwlock_init (pthread_rwlock_t *rwlock, - const pthread_rwlockattr_t *attr) + const pthread_rwlockattr_t *attr) { __pthread_init_lock(&rwlock->__rw_lock); rwlock->__rw_readers = 0; @@ -214,10 +214,10 @@ __pthread_rwlock_destroy (pthread_rwlock_t *rwlock) int readers; _pthread_descr writer; - __pthread_lock (&rwlock->__rw_lock, NULL); + __pthread_alt_lock (&rwlock->__rw_lock, NULL); readers = rwlock->__rw_readers; writer = rwlock->__rw_writer; - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); if (readers > 0 || writer != NULL) return EBUSY; @@ -236,23 +236,23 @@ __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) have_lock_already = rwlock_have_already(&self, rwlock, &existing, &out_of_mem); + if (self == NULL) + self = thread_self (); + for (;;) { - if (self == NULL) - self = thread_self (); - - __pthread_lock (&rwlock->__rw_lock, self); + __pthread_alt_lock (&rwlock->__rw_lock, self); if (rwlock_can_rdlock(rwlock, have_lock_already)) break; enqueue (&rwlock->__rw_read_waiting, self); - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); suspend (self); /* This is not a cancellation point */ } ++rwlock->__rw_readers; - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); if (have_lock_already || out_of_mem) { @@ -266,6 +266,51 @@ __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) } strong_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) +int +__pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + for (;;) + { + if (__pthread_alt_timedlock (&rwlock->__rw_lock, self, abstime) == 0) + return ETIMEDOUT; + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_alt_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } + + ++rwlock->__rw_readers; + __pthread_alt_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + existing->pr_lock_count++; + else + self->p_untracked_readlock_count++; + } + + return 0; +} +strong_alias (__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock) + int __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) { @@ -277,7 +322,7 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) have_lock_already = rwlock_have_already(&self, rwlock, &existing, &out_of_mem); - __pthread_lock (&rwlock->__rw_lock, self); + __pthread_alt_lock (&rwlock->__rw_lock, self); /* 0 is passed to here instead of have_lock_already. This is to meet Single Unix Spec requirements: @@ -291,7 +336,7 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) retval = 0; } - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); if (retval == 0) { @@ -316,35 +361,67 @@ __pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) while(1) { - __pthread_lock (&rwlock->__rw_lock, self); + __pthread_alt_lock (&rwlock->__rw_lock, self); if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) { rwlock->__rw_writer = self; - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); return 0; } /* Suspend ourselves, then try again */ enqueue (&rwlock->__rw_write_waiting, self); - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); suspend (self); /* This is not a cancellation point */ } } strong_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) +int +__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + self = thread_self (); + + while(1) + { + if (__pthread_alt_timedlock (&rwlock->__rw_lock, self, abstime) == 0) + return ETIMEDOUT; + + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_alt_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_alt_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } +} +strong_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock) + + int __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) { int result = EBUSY; - __pthread_lock (&rwlock->__rw_lock, NULL); + __pthread_alt_lock (&rwlock->__rw_lock, NULL); if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) { rwlock->__rw_writer = thread_self (); result = 0; } - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); return result; } @@ -357,13 +434,13 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock) pthread_descr torestart; pthread_descr th; - __pthread_lock (&rwlock->__rw_lock, NULL); + __pthread_alt_lock (&rwlock->__rw_lock, NULL); if (rwlock->__rw_writer != NULL) { /* Unlocking a write lock. */ if (rwlock->__rw_writer != thread_self ()) { - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); return EPERM; } rwlock->__rw_writer = NULL; @@ -375,14 +452,14 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock) /* Restart all waiting readers. */ torestart = rwlock->__rw_read_waiting; rwlock->__rw_read_waiting = NULL; - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); while ((th = dequeue (&torestart)) != NULL) restart (th); } else { /* Restart one waiting writer. */ - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); restart (th); } } @@ -391,7 +468,7 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock) /* Unlocking a read lock. */ if (rwlock->__rw_readers == 0) { - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); return EPERM; } @@ -402,7 +479,7 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock) else th = NULL; - __pthread_unlock (&rwlock->__rw_lock); + __pthread_alt_unlock (&rwlock->__rw_lock); if (th != NULL) restart (th); -- cgit v1.2.3