git: 7865d159c5e1 - stable/14 - thr_rtld: accept read lock requests while owning the lock for write
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 10 May 2025 19:33:10 UTC
The branch stable/14 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=7865d159c5e1b825286777ec236b502ec1261dc0 commit 7865d159c5e1b825286777ec236b502ec1261dc0 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2025-05-02 15:09:46 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2025-05-10 18:57:45 +0000 thr_rtld: accept read lock requests while owning the lock for write PR: 286505 (cherry picked from commit 812c4bf3f17024f192980bbb8a781676cb9cf6b6) --- lib/libthr/thread/thr_rtld.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index 55197a9c5461..5195b208f287 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -51,8 +51,11 @@ static int _thr_rtld_set_flag(int); static void _thr_rtld_wlock_acquire(void *); struct rtld_lock { - struct urwlock lock; - char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock)]; + struct urwlock lock; + struct pthread *wowner; + u_int rlocks; + char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock) - + sizeof(struct pthread *) - sizeof(u_int)]; }; static struct rtld_lock lock_place[MAX_RTLD_LOCKS] __aligned(CACHE_LINE_SIZE); @@ -117,9 +120,13 @@ _thr_rtld_rlock_acquire(void *lock) SAVE_ERRNO(); l = (struct rtld_lock *)lock; - THR_CRITICAL_ENTER(curthread); - while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) - ; + if (l->wowner == curthread) { + l->rlocks++; + } else { + THR_CRITICAL_ENTER(curthread); + while (_thr_rwlock_rdlock(&l->lock, 0, NULL) != 0) + ; + } curthread->rdlock_count++; RESTORE_ERRNO(); } @@ -138,6 +145,7 @@ _thr_rtld_wlock_acquire(void *lock) THR_CRITICAL_ENTER(curthread); while (_thr_rwlock_wrlock(&l->lock, NULL) != 0) ; + l->wowner = curthread; RESTORE_ERRNO(); } @@ -165,6 +173,14 @@ _thr_rtld_lock_release(void *lock) l->lock.rw_blocked_readers = 0; l->lock.rw_blocked_writers = 0; } + if ((state & URWLOCK_WRITE_OWNER) != 0) { + if (l->rlocks > 0) { + l->rlocks--; + return; + } else { + l->wowner = NULL; + } + } if (_thr_rwlock_unlock(&l->lock) == 0) { if ((state & URWLOCK_WRITE_OWNER) == 0) curthread->rdlock_count--;