diff options
author | mtm <mtm@FreeBSD.org> | 2004-01-29 12:03:17 +0000 |
---|---|---|
committer | mtm <mtm@FreeBSD.org> | 2004-01-29 12:03:17 +0000 |
commit | 31275ad8daf7ea3cb64999532ccd645cda8248c3 (patch) | |
tree | 484c31675a302bb35f6f4886daa36099e417299d /lib/libthr | |
parent | f488df6c994e9b1a8827ed7d4188574f09c815fb (diff) | |
download | FreeBSD-src-31275ad8daf7ea3cb64999532ccd645cda8248c3.zip FreeBSD-src-31275ad8daf7ea3cb64999532ccd645cda8248c3.tar.gz |
I update the rwlock code in libthr to be more standards compliant and
what do I get for my troubles? libc breaks offcourse!
Reimplement a hack (in libthr) that allows libc to use
rwlocks without initializing them first. The hack was reimplemented
so that only a private libc version of the rwlock locking functions
initializes an uninitialized rwlock. The application version will
correctly fail.
Diffstat (limited to 'lib/libthr')
-rw-r--r-- | lib/libthr/thread/thr_rwlock.c | 131 |
1 files changed, 119 insertions, 12 deletions
diff --git a/lib/libthr/thread/thr_rwlock.c b/lib/libthr/thread/thr_rwlock.c index 8644e1e..68ae192 100644 --- a/lib/libthr/thread/thr_rwlock.c +++ b/lib/libthr/thread/thr_rwlock.c @@ -42,17 +42,29 @@ */ enum rwlock_type {RWT_READ, RWT_WRITE}; +/* hack to accomodate libc */ +static struct umtx init_lock = UMTX_INITIALIZER; + +/* + * Single underscore versions are for libc useage. So, use double + * underscores for applications. + */ +__weak_reference(__pthread_rwlock_rdlock, pthread_rwlock_rdlock); +__weak_reference(__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); +__weak_reference(__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); +__weak_reference(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); +__weak_reference(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); +__weak_reference(__pthread_rwlock_wrlock, pthread_rwlock_wrlock); + +/* + * No difference between libc and application usage. + */ __weak_reference(_pthread_rwlock_destroy, pthread_rwlock_destroy); __weak_reference(_pthread_rwlock_init, pthread_rwlock_init); -__weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); -__weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); -__weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); -__weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); -__weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); __weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); -__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); static int insert_rwlock(struct pthread_rwlock *, enum rwlock_type); +static int rwlock_init_static(struct pthread_rwlock **rwlock); static int rwlock_rdlock_common(pthread_rwlock_t *, int, const struct timespec *); static int rwlock_wrlock_common(pthread_rwlock_t *, int, @@ -212,25 +224,59 @@ rwlock_rdlock_common(pthread_rwlock_t *rwlock, int nonblocking, } int -_pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) { return (rwlock_rdlock_common(rwlock, 0, NULL)); } int -_pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, +_pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +{ + int error; + + error = rwlock_init_static(rwlock); + if (error == 0) + error = rwlock_rdlock_common(rwlock, 0, NULL); + return (error); +} + +int +__pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *timeout) { return (rwlock_rdlock_common(rwlock, 0, timeout)); } int -_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, + const struct timespec *timeout) +{ + int error; + + error = rwlock_init_static(rwlock); + if (error == 0) + rwlock_rdlock_common(rwlock, 0, timeout); + return (error); +} + +int +__pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) { return (rwlock_rdlock_common(rwlock, 1, NULL)); } int +_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +{ + int error; + + error = rwlock_init_static(rwlock); + if (error == 0) + rwlock_rdlock_common(rwlock, 1, NULL); + return (error); +} + +int _pthread_rwlock_unlock (pthread_rwlock_t *rwlock) { struct rwlock_held *rh; @@ -293,24 +339,58 @@ out: } int -_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) { return (rwlock_wrlock_common(rwlock, 0, NULL)); } int -_pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, +_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +{ + int error; + + error = rwlock_init_static(rwlock); + if (error == 0) + error = rwlock_wrlock_common(rwlock, 0, NULL); + return (error); +} + +int +__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *timeout) { return (rwlock_wrlock_common(rwlock, 0, timeout)); } int -_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +_pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, + const struct timespec *timeout) +{ + int error; + + error = rwlock_init_static(rwlock); + if (error == 0) + rwlock_wrlock_common(rwlock, 0, timeout); + return (error); +} + +int +__pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) { return (rwlock_wrlock_common(rwlock, 1, NULL)); } +int +_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +{ + int error; + + error = rwlock_init_static(rwlock); + if (error == 0) + rwlock_wrlock_common(rwlock, 1, NULL); + return (error); +} + /* * If nonblocking is 0 this function will wait on the lock. If * it is greater than 0 it will return immediately with EBUSY. @@ -440,3 +520,30 @@ insert_rwlock(struct pthread_rwlock *prwlock, enum rwlock_type rwt) LIST_INSERT_HEAD(curthread->rwlockList, rh, rh_link); return (0); } + +/* + * libc version. + * There are several users of rwlocks in libc that depend on + * a bogus PTHREAD_RWLOCK_INITIALIZER to do for rwlocks that + * a similarly named symbol does for statically initialized mutexes. + * However, this symbol does not seem to be a valid POSIX symbol. Rather + * than fix libc, I choose to "fix" libthr. + */ +static int +rwlock_init_static(struct pthread_rwlock **rwlock) +{ + int error; + + /* + * The initial check is done without locks to not + * pessimize the common path. + */ + error = 0; + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) { + UMTX_LOCK(&init_lock); + if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) + error = _pthread_rwlock_init(rwlock, NULL); + UMTX_UNLOCK(&init_lock); + } + return (error); +} |