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 2916fb9086SImre Vadász #include "namespace.h" 3019451dc5Szrj #include <machine/tls.h> 3171b3fa15SDavid Xu #include <stdlib.h> 32*fcaa7a3aSMatthew Dillon #include <string.h> 3371b3fa15SDavid Xu #include <pthread.h> 3471b3fa15SDavid Xu 3516fb9086SImre Vadász #include "un-namespace.h" 3671b3fa15SDavid Xu #include "rtld_lock.h" 3771b3fa15SDavid Xu #include "thr_private.h" 3871b3fa15SDavid Xu 3971b3fa15SDavid Xu static int _thr_rtld_clr_flag(int); 4071b3fa15SDavid Xu static void *_thr_rtld_lock_create(void); 4171b3fa15SDavid Xu static void _thr_rtld_lock_destroy(void *); 4271b3fa15SDavid Xu static void _thr_rtld_lock_release(void *); 4371b3fa15SDavid Xu static void _thr_rtld_rlock_acquire(void *); 4471b3fa15SDavid Xu static int _thr_rtld_set_flag(int); 4571b3fa15SDavid Xu static void _thr_rtld_wlock_acquire(void *); 4671b3fa15SDavid Xu 4771b3fa15SDavid Xu static void * 4871b3fa15SDavid Xu _thr_rtld_lock_create(void) 4971b3fa15SDavid Xu { 5071b3fa15SDavid Xu pthread_rwlock_t prwlock; 5171b3fa15SDavid Xu if (_pthread_rwlock_init(&prwlock, NULL)) 5271b3fa15SDavid Xu return (NULL); 5371b3fa15SDavid Xu return (prwlock); 5471b3fa15SDavid Xu } 5571b3fa15SDavid Xu 5671b3fa15SDavid Xu static void 5771b3fa15SDavid Xu _thr_rtld_lock_destroy(void *lock) 5871b3fa15SDavid Xu { 5971b3fa15SDavid Xu pthread_rwlock_t prwlock; 6071b3fa15SDavid Xu 6171b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 6271b3fa15SDavid Xu if (prwlock != NULL) 6371b3fa15SDavid Xu _pthread_rwlock_destroy(&prwlock); 6471b3fa15SDavid Xu } 6571b3fa15SDavid Xu 6671b3fa15SDavid Xu static void 6771b3fa15SDavid Xu _thr_rtld_rlock_acquire(void *lock) 6871b3fa15SDavid Xu { 6971b3fa15SDavid Xu pthread_rwlock_t prwlock; 7071b3fa15SDavid Xu 7171b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 7216fb9086SImre Vadász _pthread_rwlock_rdlock(&prwlock); 7371b3fa15SDavid Xu } 7471b3fa15SDavid Xu 7571b3fa15SDavid Xu static void 7671b3fa15SDavid Xu _thr_rtld_wlock_acquire(void *lock) 7771b3fa15SDavid Xu { 7871b3fa15SDavid Xu pthread_rwlock_t prwlock; 7971b3fa15SDavid Xu 8071b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 8116fb9086SImre Vadász _pthread_rwlock_wrlock(&prwlock); 8271b3fa15SDavid Xu } 8371b3fa15SDavid Xu 8471b3fa15SDavid Xu static void 8571b3fa15SDavid Xu _thr_rtld_lock_release(void *lock) 8671b3fa15SDavid Xu { 8771b3fa15SDavid Xu pthread_rwlock_t prwlock; 8871b3fa15SDavid Xu 8971b3fa15SDavid Xu prwlock = (pthread_rwlock_t)lock; 9016fb9086SImre Vadász _pthread_rwlock_unlock(&prwlock); 9171b3fa15SDavid Xu } 9271b3fa15SDavid Xu 9371b3fa15SDavid Xu 9471b3fa15SDavid Xu static int 9571b3fa15SDavid Xu _thr_rtld_set_flag(int mask) 9671b3fa15SDavid Xu { 9771b3fa15SDavid Xu struct pthread *curthread; 9871b3fa15SDavid Xu int bits; 9971b3fa15SDavid Xu 1009e2ee207SJoerg Sonnenberger curthread = tls_get_curthread(); 10171b3fa15SDavid Xu if (curthread != NULL) { 10271b3fa15SDavid Xu bits = curthread->rtld_bits; 10371b3fa15SDavid Xu curthread->rtld_bits |= mask; 10471b3fa15SDavid Xu } else { 10571b3fa15SDavid Xu bits = 0; 10671b3fa15SDavid Xu PANIC("No current thread in rtld call"); 10771b3fa15SDavid Xu } 10871b3fa15SDavid Xu 10971b3fa15SDavid Xu return (bits); 11071b3fa15SDavid Xu } 11171b3fa15SDavid Xu 11271b3fa15SDavid Xu static int 11371b3fa15SDavid Xu _thr_rtld_clr_flag(int mask) 11471b3fa15SDavid Xu { 11571b3fa15SDavid Xu struct pthread *curthread; 11671b3fa15SDavid Xu int bits; 11771b3fa15SDavid Xu 1189e2ee207SJoerg Sonnenberger curthread = tls_get_curthread(); 11971b3fa15SDavid Xu if (curthread != NULL) { 12071b3fa15SDavid Xu bits = curthread->rtld_bits; 12171b3fa15SDavid Xu curthread->rtld_bits &= ~mask; 12271b3fa15SDavid Xu } else { 12371b3fa15SDavid Xu bits = 0; 12471b3fa15SDavid Xu PANIC("No current thread in rtld call"); 12571b3fa15SDavid Xu } 12671b3fa15SDavid Xu return (bits); 12771b3fa15SDavid Xu } 12871b3fa15SDavid Xu 12971b3fa15SDavid Xu void 13071b3fa15SDavid Xu _thr_rtld_init(void) 13171b3fa15SDavid Xu { 13271b3fa15SDavid Xu struct RtldLockInfo li; 133*fcaa7a3aSMatthew Dillon static int once = 0; 13471b3fa15SDavid Xu 135*fcaa7a3aSMatthew Dillon memset(&li, 0, sizeof(li)); 13671b3fa15SDavid Xu li.lock_create = _thr_rtld_lock_create; 13771b3fa15SDavid Xu li.lock_destroy = _thr_rtld_lock_destroy; 13871b3fa15SDavid Xu li.rlock_acquire = _thr_rtld_rlock_acquire; 13971b3fa15SDavid Xu li.wlock_acquire = _thr_rtld_wlock_acquire; 14071b3fa15SDavid Xu li.lock_release = _thr_rtld_lock_release; 14171b3fa15SDavid Xu li.thread_set_flag = _thr_rtld_set_flag; 14271b3fa15SDavid Xu li.thread_clr_flag = _thr_rtld_clr_flag; 14371b3fa15SDavid Xu li.at_fork = NULL; 14471b3fa15SDavid Xu _rtld_thread_init(&li); 145*fcaa7a3aSMatthew Dillon if (once == 0) { 146*fcaa7a3aSMatthew Dillon once = 1; 147*fcaa7a3aSMatthew Dillon _thr_atfork_kern(_rtld_thread_prefork, 148*fcaa7a3aSMatthew Dillon _rtld_thread_postfork, 149*fcaa7a3aSMatthew Dillon _rtld_thread_childfork); 150*fcaa7a3aSMatthew Dillon } 15171b3fa15SDavid Xu } 15271b3fa15SDavid Xu 15371b3fa15SDavid Xu void 15471b3fa15SDavid Xu _thr_rtld_fini(void) 15571b3fa15SDavid Xu { 15671b3fa15SDavid Xu _rtld_thread_init(NULL); 15771b3fa15SDavid Xu } 158