diff options
author | davidxu <davidxu@FreeBSD.org> | 2003-08-10 22:15:03 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2003-08-10 22:15:03 +0000 |
commit | 349a8e7e9bf3b0f9536820ffb38e4c2c85e411a6 (patch) | |
tree | 6421611b0ee9f5f5e41bd89036a4197cd073aac4 /lib/libkse/thread | |
parent | b213a2432e715efb62c35678c43365b8f84128f9 (diff) | |
download | FreeBSD-src-349a8e7e9bf3b0f9536820ffb38e4c2c85e411a6.zip FreeBSD-src-349a8e7e9bf3b0f9536820ffb38e4c2c85e411a6.tar.gz |
Tweak rtld lock to allow recursive on reader lock and detect recursive
on writer lock. This is first cut at rwlock for rtld.
Submitted by: desichen
Diffstat (limited to 'lib/libkse/thread')
-rw-r--r-- | lib/libkse/thread/thr_rtld.c | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/lib/libkse/thread/thr_rtld.c b/lib/libkse/thread/thr_rtld.c index b7043d0..110fc18 100644 --- a/lib/libkse/thread/thr_rtld.c +++ b/lib/libkse/thread/thr_rtld.c @@ -140,8 +140,11 @@ _thr_rtld_fini() #endif struct rtld_kse_lock { - struct lock lck; - kse_critical_t crit; + struct lock lck; + struct kse *owner; + kse_critical_t crit; + int count; + int write; }; static void * @@ -150,16 +153,23 @@ _thr_rtld_lock_create() struct rtld_kse_lock *l = malloc(sizeof(struct rtld_kse_lock)); _lock_init(&l->lck, LCK_ADAPTIVE, _kse_lock_wait, _kse_lock_wakeup); + l->owner = NULL; + l->count = 0; + l->write = 0; return (l); } static void _thr_rtld_lock_destroy(void *lock) { + /* XXX We really can not free memory after a fork() */ +#if 0 struct rtld_kse_lock *l = (struct rtld_kse_lock *)lock; - + _lock_destroy(&l->lck); free(l); +#endif + return; } static void @@ -167,10 +177,20 @@ _thr_rtld_rlock_acquire(void *lock) { struct rtld_kse_lock *l = (struct rtld_kse_lock *)lock; kse_critical_t crit; + struct kse *curkse; crit = _kse_critical_enter(); - KSE_LOCK_ACQUIRE(_get_curkse(), &l->lck); - l->crit = crit; + curkse = _get_curkse(); + if (l->owner == curkse) { + l->count++; + _kse_critical_leave(crit); /* probably not necessary */ + } else { + KSE_LOCK_ACQUIRE(curkse, &l->lck); + l->crit = crit; + l->owner = curkse; + l->count = 1; + l->write = 0; + } } static void @@ -178,20 +198,57 @@ _thr_rtld_wlock_acquire(void *lock) { struct rtld_kse_lock *l = (struct rtld_kse_lock *)lock; kse_critical_t crit; + struct kse *curkse; crit = _kse_critical_enter(); - KSE_LOCK_ACQUIRE(_get_curkse(), &l->lck); - l->crit = crit; + curkse = _get_curkse(); + if (l->owner == curkse) { + _kse_critical_leave(crit); + PANIC("Recursive write lock attempt on rtld lock"); + } else { + KSE_LOCK_ACQUIRE(curkse, &l->lck); + l->crit = crit; + l->owner = curkse; + l->count = 1; + l->write = 1; + } } static void _thr_rtld_lock_release(void *lock) { struct rtld_kse_lock *l = (struct rtld_kse_lock *)lock; - kse_critical_t crit = l->crit; + kse_critical_t crit; + struct kse *curkse; - KSE_LOCK_RELEASE(_get_curkse(), &l->lck); - _kse_critical_leave(crit); + crit = _kse_critical_enter(); + curkse = _get_curkse(); + if (l->owner != curkse) { + /* + * We might want to forcibly unlock the rtld lock + * and/or disable threaded mode so there is better + * chance that the panic will work. Otherwise, + * we could end up trying to take the rtld lock + * again. + */ + _kse_critical_leave(crit); + PANIC("Attempt to unlock rtld lock when not owner."); + } else { + l->count--; + if (l->count == 0) { + /* + * If there ever is a count associated with + * _kse_critical_leave(), we'll need to add + * another call to it here with the crit + * value from above. + */ + crit = l->crit; + l->owner = NULL; + l->write = 0; + KSE_LOCK_RELEASE(curkse, &l->lck); + } + _kse_critical_leave(crit); + } } |