diff options
author | kib <kib@FreeBSD.org> | 2008-12-02 11:58:31 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-12-02 11:58:31 +0000 |
commit | af7a67c13ca3d0aea828b69672928819ce3cafc1 (patch) | |
tree | b23ed20daecc73be355f5025496a06fa66e978c8 /lib/libthr | |
parent | ade687809e3b9101f41cc7ab57fee5e8056b7381 (diff) | |
download | FreeBSD-src-af7a67c13ca3d0aea828b69672928819ce3cafc1.zip FreeBSD-src-af7a67c13ca3d0aea828b69672928819ce3cafc1.tar.gz |
Provide custom simple allocator for rtld locks in libthr. The allocator
does not use any external symbols, thus avoiding possible recursion into
rtld to resolve symbols, when called.
Reviewed by: kan, davidxu
Tested by: rink
MFC after: 1 month
Diffstat (limited to 'lib/libthr')
-rw-r--r-- | lib/libthr/thread/thr_fork.c | 2 | ||||
-rw-r--r-- | lib/libthr/thread/thr_rtld.c | 46 |
2 files changed, 24 insertions, 24 deletions
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index 0288dc2..bc410d1 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -106,7 +106,7 @@ _fork(void) pid_t ret; int errsave; int unlock_malloc; - int rtld_locks[16]; + int rtld_locks[MAX_RTLD_LOCKS]; if (!_thr_is_inited()) return (__sys_fork()); diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index a8cd61d..8e09494 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -50,42 +50,42 @@ static int _thr_rtld_set_flag(int); static void _thr_rtld_wlock_acquire(void *); struct rtld_lock { - struct urwlock lock; - void *base; + struct urwlock lock; + char _pad[CACHE_LINE_SIZE - sizeof(struct urwlock)]; }; +static struct rtld_lock lock_place[MAX_RTLD_LOCKS] __aligned(CACHE_LINE_SIZE); +static int busy_places; + static void * _thr_rtld_lock_create(void) { - void *base; - char *p; - uintptr_t r; - struct rtld_lock *l; - size_t size; - - size = CACHE_LINE_SIZE; - while (size < sizeof(struct rtld_lock)) - size <<= 1; - base = calloc(1, size); - p = (char *)base; - if ((uintptr_t)p % CACHE_LINE_SIZE != 0) { - free(base); - base = calloc(1, size + CACHE_LINE_SIZE); - p = (char *)base; - if ((r = (uintptr_t)p % CACHE_LINE_SIZE) != 0) - p += CACHE_LINE_SIZE - r; + int locki; + struct rtld_lock *l; + static const char fail[] = "_thr_rtld_lock_create failed\n"; + + for (locki = 0; locki < MAX_RTLD_LOCKS; locki++) { + if ((busy_places & (1 << locki)) == 0) + break; } - l = (struct rtld_lock *)p; + if (locki == MAX_RTLD_LOCKS) { + write(2, fail, sizeof(fail) - 1); + return (NULL); + } + busy_places |= (1 << locki); + + l = &lock_place[locki]; l->lock.rw_flags = URWLOCK_PREFER_READER; - l->base = base; return (l); } static void _thr_rtld_lock_destroy(void *lock) { - struct rtld_lock *l = (struct rtld_lock *)lock; - free(l->base); + int locki; + + locki = (struct rtld_lock *)lock - &lock_place[0]; + busy_places &= ~(1 << locki); } #define SAVE_ERRNO() { \ |