171b3fa15SDavid Xu /* 2d3b15642Szrj * Copyright (c) 2006, David Xu <davidxu@freebsd.org> 371b3fa15SDavid Xu * All rights reserved. 471b3fa15SDavid Xu * 571b3fa15SDavid Xu * Redistribution and use in source and binary forms, with or without 671b3fa15SDavid Xu * modification, are permitted provided that the following conditions 771b3fa15SDavid Xu * are met: 871b3fa15SDavid Xu * 1. Redistributions of source code must retain the above copyright 9d3b15642Szrj * notice unmodified, this list of conditions, and the following 10d3b15642Szrj * disclaimer. 1171b3fa15SDavid Xu * 2. Redistributions in binary form must reproduce the above copyright 1271b3fa15SDavid Xu * notice, this list of conditions and the following disclaimer in the 1371b3fa15SDavid Xu * documentation and/or other materials provided with the distribution. 1471b3fa15SDavid Xu * 1571b3fa15SDavid Xu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1671b3fa15SDavid Xu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1771b3fa15SDavid Xu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1871b3fa15SDavid Xu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1971b3fa15SDavid Xu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2071b3fa15SDavid Xu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2171b3fa15SDavid Xu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2271b3fa15SDavid Xu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2371b3fa15SDavid Xu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2471b3fa15SDavid Xu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2571b3fa15SDavid Xu * 2671b3fa15SDavid Xu * $FreeBSD: src/lib/libpthread/thread/thr_rtld.c,v 1.5 2003/11/05 18:19:24 deischen Exp $ 2771b3fa15SDavid Xu */ 289e2ee207SJoerg Sonnenberger 29*19451dc5Szrj #include <machine/tls.h> 3071b3fa15SDavid Xu #include <stdlib.h> 3171b3fa15SDavid Xu #include <pthread.h> 3271b3fa15SDavid Xu 3371b3fa15SDavid Xu #include "rtld_lock.h" 3471b3fa15SDavid Xu #include "thr_private.h" 3571b3fa15SDavid Xu 3671b3fa15SDavid Xu static int _thr_rtld_clr_flag(int); 3771b3fa15SDavid Xu static void *_thr_rtld_lock_create(void); 3871b3fa15SDavid Xu static void _thr_rtld_lock_destroy(void *); 3971b3fa15SDavid Xu static void _thr_rtld_lock_release(void *); 4071b3fa15SDavid Xu static void _thr_rtld_rlock_acquire(void *); 4171b3fa15SDavid Xu static int _thr_rtld_set_flag(int); 4271b3fa15SDavid Xu static void _thr_rtld_wlock_acquire(void *); 4371b3fa15SDavid Xu 4471b3fa15SDavid Xu static void * 4571b3fa15SDavid Xu _thr_rtld_lock_create(void) 4671b3fa15SDavid Xu { 4771b3fa15SDavid Xu pthread_rwlock_t prwlock; 4871b3fa15SDavid Xu if (_pthread_rwlock_init(&prwlock, NULL)) 4971b3fa15SDavid Xu return (NULL); 5071b3fa15SDavid Xu return (prwlock); 5171b3fa15SDavid Xu } 5271b3fa15SDavid Xu 5371b3fa15SDavid Xu static void 5471b3fa15SDavid Xu _thr_rtld_lock_destroy(void *lock) 5571b3fa15SDavid Xu { 5671b3fa15SDavid Xu pthread_rwlock_t prwlock; 5771b3fa15SDavid Xu 5871b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 5971b3fa15SDavid Xu if (prwlock != NULL) 6071b3fa15SDavid Xu _pthread_rwlock_destroy(&prwlock); 6171b3fa15SDavid Xu } 6271b3fa15SDavid Xu 6371b3fa15SDavid Xu static void 6471b3fa15SDavid Xu _thr_rtld_rlock_acquire(void *lock) 6571b3fa15SDavid Xu { 6671b3fa15SDavid Xu pthread_rwlock_t prwlock; 6771b3fa15SDavid Xu 6871b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 6971b3fa15SDavid Xu _thr_rwlock_rdlock(&prwlock); 7071b3fa15SDavid Xu } 7171b3fa15SDavid Xu 7271b3fa15SDavid Xu static void 7371b3fa15SDavid Xu _thr_rtld_wlock_acquire(void *lock) 7471b3fa15SDavid Xu { 7571b3fa15SDavid Xu pthread_rwlock_t prwlock; 7671b3fa15SDavid Xu 7771b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 7871b3fa15SDavid Xu _thr_rwlock_wrlock(&prwlock); 7971b3fa15SDavid Xu } 8071b3fa15SDavid Xu 8171b3fa15SDavid Xu static void 8271b3fa15SDavid Xu _thr_rtld_lock_release(void *lock) 8371b3fa15SDavid Xu { 8471b3fa15SDavid Xu pthread_rwlock_t prwlock; 8571b3fa15SDavid Xu 8671b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 8771b3fa15SDavid Xu _thr_rwlock_unlock(&prwlock); 8871b3fa15SDavid Xu } 8971b3fa15SDavid Xu 9071b3fa15SDavid Xu 9171b3fa15SDavid Xu static int 9271b3fa15SDavid Xu _thr_rtld_set_flag(int mask) 9371b3fa15SDavid Xu { 9471b3fa15SDavid Xu struct pthread *curthread; 9571b3fa15SDavid Xu int bits; 9671b3fa15SDavid Xu 979e2ee207SJoerg Sonnenberger curthread = tls_get_curthread(); 9871b3fa15SDavid Xu if (curthread != NULL) { 9971b3fa15SDavid Xu bits = curthread->rtld_bits; 10071b3fa15SDavid Xu curthread->rtld_bits |= mask; 10171b3fa15SDavid Xu } else { 10271b3fa15SDavid Xu bits = 0; 10371b3fa15SDavid Xu PANIC("No current thread in rtld call"); 10471b3fa15SDavid Xu } 10571b3fa15SDavid Xu 10671b3fa15SDavid Xu return (bits); 10771b3fa15SDavid Xu } 10871b3fa15SDavid Xu 10971b3fa15SDavid Xu static int 11071b3fa15SDavid Xu _thr_rtld_clr_flag(int mask) 11171b3fa15SDavid Xu { 11271b3fa15SDavid Xu struct pthread *curthread; 11371b3fa15SDavid Xu int bits; 11471b3fa15SDavid Xu 1159e2ee207SJoerg Sonnenberger curthread = tls_get_curthread(); 11671b3fa15SDavid Xu if (curthread != NULL) { 11771b3fa15SDavid Xu bits = curthread->rtld_bits; 11871b3fa15SDavid Xu curthread->rtld_bits &= ~mask; 11971b3fa15SDavid Xu } else { 12071b3fa15SDavid Xu bits = 0; 12171b3fa15SDavid Xu PANIC("No current thread in rtld call"); 12271b3fa15SDavid Xu } 12371b3fa15SDavid Xu return (bits); 12471b3fa15SDavid Xu } 12571b3fa15SDavid Xu 12671b3fa15SDavid Xu void 12771b3fa15SDavid Xu _thr_rtld_init(void) 12871b3fa15SDavid Xu { 12971b3fa15SDavid Xu struct RtldLockInfo li; 13071b3fa15SDavid Xu 13171b3fa15SDavid Xu li.lock_create = _thr_rtld_lock_create; 13271b3fa15SDavid Xu li.lock_destroy = _thr_rtld_lock_destroy; 13371b3fa15SDavid Xu li.rlock_acquire = _thr_rtld_rlock_acquire; 13471b3fa15SDavid Xu li.wlock_acquire = _thr_rtld_wlock_acquire; 13571b3fa15SDavid Xu li.lock_release = _thr_rtld_lock_release; 13671b3fa15SDavid Xu li.thread_set_flag = _thr_rtld_set_flag; 13771b3fa15SDavid Xu li.thread_clr_flag = _thr_rtld_clr_flag; 13871b3fa15SDavid Xu li.at_fork = NULL; 13971b3fa15SDavid Xu _rtld_thread_init(&li); 14071b3fa15SDavid Xu } 14171b3fa15SDavid Xu 14271b3fa15SDavid Xu void 14371b3fa15SDavid Xu _thr_rtld_fini(void) 14471b3fa15SDavid Xu { 14571b3fa15SDavid Xu _rtld_thread_init(NULL); 14671b3fa15SDavid Xu } 147