Attempt to eliminate PLT relocations from rwlock aquire/release
path, making them suitable for direct use by the dynamic loader. Register libpthread-specific locking API with rtld on startup. This still has some rough edges with signals which should be addresses later. Approved by: re (scottl)
This commit is contained in:
parent
43dd76d242
commit
84d55c7fad
@ -14,12 +14,16 @@ CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR}/thread \
|
||||
-I${.CURDIR}/../../include
|
||||
CFLAGS+=-I${.CURDIR}/arch/${MACHINE_ARCH}/include
|
||||
CFLAGS+=-I${.CURDIR}/sys
|
||||
CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf
|
||||
CFLAGS+=-fno-builtin
|
||||
|
||||
# Uncomment this if you want libpthread to contain debug information for
|
||||
# thread locking.
|
||||
CFLAGS+=-D_LOCK_DEBUG
|
||||
#CFLAGS+= -g
|
||||
|
||||
LDADD+= -Wl,--version-script=${.CURDIR}/pthread.map
|
||||
|
||||
# enable extra internal consistancy checks
|
||||
CFLAGS+=-D_PTHREADS_INVARIANTS -Wall
|
||||
|
||||
@ -28,5 +32,6 @@ PRECIOUSLIB= yes
|
||||
|
||||
.include "${.CURDIR}/thread/Makefile.inc"
|
||||
.include "${.CURDIR}/sys/Makefile.inc"
|
||||
.include "${.CURDIR}/support/Makefile.inc"
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
10
lib/libkse/support/Makefile.inc
Normal file
10
lib/libkse/support/Makefile.inc
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/support
|
||||
|
||||
SRCS += thr_support.c
|
||||
SOBJS+= thr_libc.So
|
||||
|
||||
thr_libc.So: thr_support.So
|
||||
${CC} -nostdlib -L/usr/lib -o ${.TARGET} -Wl,-x,-r ${.ALLSRC} -lc_pic
|
||||
|
55
lib/libkse/support/thr_support.c
Normal file
55
lib/libkse/support/thr_support.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*-
|
||||
* Copyright 2003 Alexander Kabaev.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kse.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
__strong_reference(clock_gettime, _thr_clock_gettime);
|
||||
__strong_reference(kse_exit, _thr_kse_exit);
|
||||
__strong_reference(kse_wakeup, _thr_kse_wakeup);
|
||||
__strong_reference(kse_create, _thr_kse_create);
|
||||
__strong_reference(kse_thr_interrupt, _thr_kse_thr_interrupt);
|
||||
__strong_reference(kse_release, _thr_kse_release);
|
||||
|
||||
__strong_reference(sigaction, _thr_sigaction);
|
||||
__strong_reference(sigprocmask, _thr_sigprocmask);
|
||||
__strong_reference(sigemptyset, _thr_sigemptyset);
|
||||
__strong_reference(sigaddset, _thr_sigaddset);
|
||||
__strong_reference(sigfillset, _thr_sigfillset);
|
||||
__strong_reference(sigismember, _thr_sigismember);
|
||||
__strong_reference(sigdelset, _thr_sigdelset);
|
||||
|
||||
__strong_reference(memset, _thr_memset);
|
||||
__strong_reference(memcpy, _thr_memcpy);
|
||||
__strong_reference(strcpy, _thr_strcpy);
|
||||
__strong_reference(strlen, _thr_strlen);
|
||||
__strong_reference(bzero, _thr_bzero);
|
||||
|
@ -4,3 +4,4 @@
|
||||
|
||||
SRCS+= thr_error.c _atomic_lock.S ksd.c thr_enter_uts.S thr_getcontext.S \
|
||||
thr_switch.S lock.c
|
||||
|
||||
|
@ -71,6 +71,7 @@ SRCS+= \
|
||||
thr_read.c \
|
||||
thr_readv.c \
|
||||
thr_resume_np.c \
|
||||
thr_rtld.c \
|
||||
thr_rwlock.c \
|
||||
thr_rwlockattr.c \
|
||||
thr_select.c \
|
||||
|
@ -355,6 +355,8 @@ _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_cond_wait, _thr_cond_wait);
|
||||
|
||||
int
|
||||
__pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
@ -632,6 +634,8 @@ _pthread_cond_signal(pthread_cond_t * cond)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_cond_signal, _thr_cond_signal);
|
||||
|
||||
int
|
||||
_pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
{
|
||||
@ -673,7 +677,7 @@ _pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
/* There are no more waiting threads: */
|
||||
(*cond)->c_mutex = NULL;
|
||||
break;
|
||||
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
@ -689,6 +693,8 @@ _pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_cond_broadcast, _thr_cond_broadcast);
|
||||
|
||||
void
|
||||
_cond_wait_backout(struct pthread *curthread)
|
||||
{
|
||||
|
@ -47,16 +47,12 @@ __weak_reference(_pthread_exit, pthread_exit);
|
||||
void
|
||||
_thr_exit(char *fname, int lineno, char *msg)
|
||||
{
|
||||
char s[256];
|
||||
|
||||
/* Prepare an error message string: */
|
||||
snprintf(s, sizeof(s),
|
||||
/* Write an error message to the standard error file descriptor: */
|
||||
_thread_printf(2,
|
||||
"Fatal error '%s' at line %d in file %s (errno = %d)\n",
|
||||
msg, lineno, fname, errno);
|
||||
|
||||
/* Write the string to the standard error file descriptor: */
|
||||
__sys_write(2, s, strlen(s));
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -304,6 +304,8 @@ _libpthread_init(struct pthread *curthread)
|
||||
_thr_initial->kse->k_curthread = _thr_initial;
|
||||
_thr_initial->kse->k_flags |= KF_INITIALIZED;
|
||||
_kse_initial->k_curthread = _thr_initial;
|
||||
|
||||
_thr_rtld_init();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -718,6 +718,8 @@ __pthread_mutex_lock(pthread_mutex_t *m)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(__pthread_mutex_lock, _thr_mutex_lock);
|
||||
|
||||
int
|
||||
_pthread_mutex_lock(pthread_mutex_t *m)
|
||||
{
|
||||
@ -748,6 +750,8 @@ _pthread_mutex_unlock(pthread_mutex_t *m)
|
||||
return (mutex_unlock_common(m, /* add reference */ 0));
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_mutex_unlock, _thr_mutex_unlock);
|
||||
|
||||
int
|
||||
_mutex_cv_unlock(pthread_mutex_t *m)
|
||||
{
|
||||
|
@ -794,6 +794,11 @@ struct pthread {
|
||||
struct pthread_specific_elem *specific;
|
||||
int specific_data_count;
|
||||
|
||||
/*
|
||||
* Current locks bitmap for rtld.
|
||||
*/
|
||||
int rtld_bits;
|
||||
|
||||
/* Cleanup handlers Link List */
|
||||
struct pthread_cleanup *cleanup;
|
||||
char *fname; /* Ptr to source file name */
|
||||
@ -1084,6 +1089,8 @@ int _pthread_mutexattr_init(pthread_mutexattr_t *);
|
||||
int _pthread_mutexattr_destroy(pthread_mutexattr_t *);
|
||||
int _pthread_mutexattr_settype(pthread_mutexattr_t *, int);
|
||||
int _pthread_once(pthread_once_t *, void (*) (void));
|
||||
int _pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
||||
int _pthread_rwlock_destroy (pthread_rwlock_t *);
|
||||
struct pthread *_pthread_self(void);
|
||||
int _pthread_setspecific(pthread_key_t, const void *);
|
||||
struct pthread *_thr_alloc(struct pthread *);
|
||||
@ -1128,6 +1135,19 @@ void _thr_leave_cancellation_point(struct pthread *);
|
||||
int _thr_setconcurrency(int new_level);
|
||||
int _thr_setmaxconcurrency(void);
|
||||
|
||||
/*
|
||||
* Aliases for _pthread functions. Should be called instead of
|
||||
* originals if PLT replocation is unwanted at runtme.
|
||||
*/
|
||||
int _thr_cond_broadcast(pthread_cond_t *);
|
||||
int _thr_cond_signal(pthread_cond_t *);
|
||||
int _thr_cond_wait(pthread_cond_t *, pthread_mutex_t *);
|
||||
int _thr_mutex_lock(pthread_mutex_t *);
|
||||
int _thr_mutex_unlock(pthread_mutex_t *);
|
||||
int _thr_rwlock_rdlock (pthread_rwlock_t *);
|
||||
int _thr_rwlock_wrlock (pthread_rwlock_t *);
|
||||
int _thr_rwlock_unlock (pthread_rwlock_t *);
|
||||
|
||||
/* XXX - Stuff that goes away when my sources get more up to date. */
|
||||
/* #include <sys/kse.h> */
|
||||
#ifdef SYS_KSE_H
|
||||
|
137
lib/libkse/thread/thr_rtld.c
Normal file
137
lib/libkse/thread/thr_rtld.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Alexander Kabaev
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
#include <rtld_lock.h>
|
||||
#include "thr_private.h"
|
||||
|
||||
static void *_thr_rtld_lock_create();
|
||||
static void _thr_rtld_lock_destroy(void *);
|
||||
static void _thr_rtld_rlock_acquire(void *);
|
||||
static void _thr_rtld_wlock_acquire(void *);
|
||||
static void _thr_rtld_lock_release(void *);
|
||||
static int _thr_rtld_set_flag(int);
|
||||
static int _thr_rtld_clr_flag(int);
|
||||
|
||||
static void *
|
||||
_thr_rtld_lock_create()
|
||||
{
|
||||
pthread_rwlock_t prwlock;
|
||||
if (_pthread_rwlock_init(&prwlock, NULL))
|
||||
return (NULL);
|
||||
return (prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_lock_destroy(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
if (prwlock != NULL)
|
||||
_pthread_rwlock_destroy(&prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_rlock_acquire(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
_thr_rwlock_rdlock(&prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_wlock_acquire(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
_thr_rwlock_wrlock(&prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_lock_release(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
_thr_rwlock_unlock(&prwlock);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_thr_rtld_set_flag(int mask)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
int bits;
|
||||
|
||||
curthread = _get_curthread();
|
||||
|
||||
if (curthread != NULL) {
|
||||
bits = curthread->rtld_bits;
|
||||
curthread->rtld_bits |= mask;
|
||||
} else {
|
||||
bits = 0;
|
||||
PANIC("No current thread in rtld call");
|
||||
}
|
||||
|
||||
return (bits);
|
||||
}
|
||||
|
||||
static int
|
||||
_thr_rtld_clr_flag(int mask)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
int bits;
|
||||
|
||||
curthread = _get_curthread();
|
||||
|
||||
if (curthread != NULL) {
|
||||
bits = curthread->rtld_bits;
|
||||
curthread->rtld_bits &= ~mask;
|
||||
} else {
|
||||
bits = 0;
|
||||
PANIC("No current thread in rtld call");
|
||||
}
|
||||
return (bits);
|
||||
}
|
||||
|
||||
void
|
||||
_thr_rtld_init()
|
||||
{
|
||||
struct RtldLockInfo li;
|
||||
li.lock_create = _thr_rtld_lock_create;
|
||||
li.lock_destroy = _thr_rtld_lock_destroy;
|
||||
li.rlock_acquire = _thr_rtld_rlock_acquire;
|
||||
li.wlock_acquire = _thr_rtld_wlock_acquire;
|
||||
li.lock_release = _thr_rtld_lock_release;
|
||||
li.thread_set_flag = _thr_rtld_set_flag;
|
||||
li.thread_clr_flag = _thr_rtld_clr_flag;
|
||||
li.at_fork = NULL;
|
||||
_rtld_thread_init(&li);
|
||||
}
|
||||
|
||||
void
|
||||
_thr_rtld_fini()
|
||||
{
|
||||
_rtld_thread_init(NULL);
|
||||
}
|
@ -46,7 +46,6 @@ __weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
|
||||
__weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock);
|
||||
__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock);
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
@ -158,16 +157,16 @@ _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
}
|
||||
|
||||
/* grab the monitor lock */
|
||||
if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
|
||||
if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* give writers priority over readers */
|
||||
while (prwlock->blocked_writers || prwlock->state < 0) {
|
||||
ret = _pthread_cond_wait(&prwlock->read_signal, &prwlock->lock);
|
||||
ret = _thr_cond_wait(&prwlock->read_signal, &prwlock->lock);
|
||||
|
||||
if (ret != 0) {
|
||||
/* can't do a whole lot if this fails */
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
@ -184,11 +183,13 @@ _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
* lock. Decrementing 'state' is no good because we probably
|
||||
* don't have the monitor lock.
|
||||
*/
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_rwlock_rdlock, _thr_rwlock_rdlock);
|
||||
|
||||
int
|
||||
_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
@ -276,28 +277,30 @@ _pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
||||
return (EINVAL);
|
||||
|
||||
/* grab the monitor lock */
|
||||
if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
|
||||
if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (prwlock->state > 0) {
|
||||
if (--prwlock->state == 0 && prwlock->blocked_writers)
|
||||
ret = _pthread_cond_signal(&prwlock->write_signal);
|
||||
ret = _thr_cond_signal(&prwlock->write_signal);
|
||||
} else if (prwlock->state < 0) {
|
||||
prwlock->state = 0;
|
||||
|
||||
if (prwlock->blocked_writers)
|
||||
ret = _pthread_cond_signal(&prwlock->write_signal);
|
||||
ret = _thr_cond_signal(&prwlock->write_signal);
|
||||
else
|
||||
ret = _pthread_cond_broadcast(&prwlock->read_signal);
|
||||
ret = _thr_cond_broadcast(&prwlock->read_signal);
|
||||
} else
|
||||
ret = EINVAL;
|
||||
|
||||
/* see the comment on this in pthread_rwlock_rdlock */
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_rwlock_unlock, _thr_rwlock_unlock);
|
||||
|
||||
int
|
||||
_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
@ -318,17 +321,17 @@ _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
}
|
||||
|
||||
/* grab the monitor lock */
|
||||
if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
|
||||
if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0)
|
||||
return (ret);
|
||||
|
||||
while (prwlock->state != 0) {
|
||||
++prwlock->blocked_writers;
|
||||
|
||||
ret = _pthread_cond_wait(&prwlock->write_signal, &prwlock->lock);
|
||||
ret = _thr_cond_wait(&prwlock->write_signal, &prwlock->lock);
|
||||
|
||||
if (ret != 0) {
|
||||
--prwlock->blocked_writers;
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@ -339,7 +342,9 @@ _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
prwlock->state = -1;
|
||||
|
||||
/* see the comment on this in pthread_rwlock_rdlock */
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_rwlock_wrlock, _thr_rwlock_wrlock);
|
||||
|
@ -14,12 +14,16 @@ CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR}/thread \
|
||||
-I${.CURDIR}/../../include
|
||||
CFLAGS+=-I${.CURDIR}/arch/${MACHINE_ARCH}/include
|
||||
CFLAGS+=-I${.CURDIR}/sys
|
||||
CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf
|
||||
CFLAGS+=-fno-builtin
|
||||
|
||||
# Uncomment this if you want libpthread to contain debug information for
|
||||
# thread locking.
|
||||
CFLAGS+=-D_LOCK_DEBUG
|
||||
#CFLAGS+= -g
|
||||
|
||||
LDADD+= -Wl,--version-script=${.CURDIR}/pthread.map
|
||||
|
||||
# enable extra internal consistancy checks
|
||||
CFLAGS+=-D_PTHREADS_INVARIANTS -Wall
|
||||
|
||||
@ -28,5 +32,6 @@ PRECIOUSLIB= yes
|
||||
|
||||
.include "${.CURDIR}/thread/Makefile.inc"
|
||||
.include "${.CURDIR}/sys/Makefile.inc"
|
||||
.include "${.CURDIR}/support/Makefile.inc"
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
296
lib/libpthread/pthread.map
Normal file
296
lib/libpthread/pthread.map
Normal file
@ -0,0 +1,296 @@
|
||||
# $FreeBSD$
|
||||
LIBTHREAD_1_0 {
|
||||
global:
|
||||
___creat;
|
||||
__close;
|
||||
__error;
|
||||
__fcntl;
|
||||
__fsync;
|
||||
__msync;
|
||||
__nanosleep;
|
||||
__open;
|
||||
__poll;
|
||||
__pthread_cond_timedwait;
|
||||
__pthread_cond_wait;
|
||||
__pthread_mutex_lock;
|
||||
__pthread_mutex_trylock;
|
||||
__read;
|
||||
__readv;
|
||||
__select;
|
||||
__sigsuspend;
|
||||
__wait4;
|
||||
__write;
|
||||
__writev;
|
||||
_aio_suspend;
|
||||
_fork;
|
||||
_nanosleep;
|
||||
_pause;
|
||||
_pselect;
|
||||
_pthread_attr_default;
|
||||
_pthread_attr_destroy;
|
||||
_pthread_attr_get_np;
|
||||
_pthread_attr_getdetachstate;
|
||||
_pthread_attr_getguardsize;
|
||||
_pthread_attr_getinheritsched;
|
||||
_pthread_attr_getschedparam;
|
||||
_pthread_attr_getschedpolicy;
|
||||
_pthread_attr_getscope;
|
||||
_pthread_attr_getstack;
|
||||
_pthread_attr_getstackaddr;
|
||||
_pthread_attr_getstacksize;
|
||||
_pthread_attr_init;
|
||||
_pthread_attr_setcreatesuspend_np;
|
||||
_pthread_attr_setdetachstate;
|
||||
_pthread_attr_setguardsize;
|
||||
_pthread_attr_setinheritsched;
|
||||
_pthread_attr_setschedparam;
|
||||
_pthread_attr_setschedpolicy;
|
||||
_pthread_attr_setscope;
|
||||
_pthread_attr_setstack;
|
||||
_pthread_attr_setstackaddr;
|
||||
_pthread_attr_setstacksize;
|
||||
_pthread_cancel;
|
||||
_pthread_cleanup_pop;
|
||||
_pthread_cleanup_push;
|
||||
_pthread_cond_broadcast;
|
||||
_pthread_cond_destroy;
|
||||
_pthread_cond_init;
|
||||
_pthread_cond_signal;
|
||||
_pthread_cond_timedwait;
|
||||
_pthread_cond_wait;
|
||||
_pthread_condattr_default;
|
||||
_pthread_condattr_destroy;
|
||||
_pthread_condattr_init;
|
||||
_pthread_create;
|
||||
_pthread_detach;
|
||||
_pthread_equal;
|
||||
_pthread_exit;
|
||||
_pthread_getconcurrency;
|
||||
_pthread_getprio;
|
||||
_pthread_getschedparam;
|
||||
_pthread_getspecific;
|
||||
_pthread_join;
|
||||
_pthread_key_create;
|
||||
_pthread_key_delete;
|
||||
_pthread_kill;
|
||||
_pthread_main_np;
|
||||
_pthread_multi_np;
|
||||
_pthread_mutex_destroy;
|
||||
_pthread_mutex_getprioceiling;
|
||||
_pthread_mutex_init;
|
||||
_pthread_mutex_lock;
|
||||
_pthread_mutex_setprioceiling;
|
||||
_pthread_mutex_trylock;
|
||||
_pthread_mutex_unlock;
|
||||
_pthread_mutexattr_default;
|
||||
_pthread_mutexattr_destroy;
|
||||
_pthread_mutexattr_getkind_np;
|
||||
_pthread_mutexattr_getprioceiling;
|
||||
_pthread_mutexattr_getprotocol;
|
||||
_pthread_mutexattr_gettype;
|
||||
_pthread_mutexattr_init;
|
||||
_pthread_mutexattr_setkind_np;
|
||||
_pthread_mutexattr_setprioceiling;
|
||||
_pthread_mutexattr_setprotocol;
|
||||
_pthread_mutexattr_settype;
|
||||
_pthread_once;
|
||||
_pthread_resume_all_np;
|
||||
_pthread_resume_np;
|
||||
_pthread_rwlock_destroy;
|
||||
_pthread_rwlock_init;
|
||||
_pthread_rwlock_rdlock;
|
||||
_pthread_rwlock_tryrdlock;
|
||||
_pthread_rwlock_trywrlock;
|
||||
_pthread_rwlock_unlock;
|
||||
_pthread_rwlock_wrlock;
|
||||
_pthread_rwlockattr_destroy;
|
||||
_pthread_rwlockattr_getpshared;
|
||||
_pthread_rwlockattr_init;
|
||||
_pthread_rwlockattr_setpshared;
|
||||
_pthread_self;
|
||||
_pthread_set_name_np;
|
||||
_pthread_setcancelstate;
|
||||
_pthread_setcanceltype;
|
||||
_pthread_setconcurrency;
|
||||
_pthread_setprio;
|
||||
_pthread_setschedparam;
|
||||
_pthread_setspecific;
|
||||
_pthread_sigmask;
|
||||
_pthread_single_np;
|
||||
_pthread_suspend_all_np;
|
||||
_pthread_suspend_np;
|
||||
_pthread_switch_add_np;
|
||||
_pthread_switch_delete_np;
|
||||
_pthread_testcancel;
|
||||
_pthread_yield;
|
||||
_sched_yield;
|
||||
_sem_close;
|
||||
_sem_destroy;
|
||||
_sem_getvalue;
|
||||
_sem_init;
|
||||
_sem_open;
|
||||
_sem_post;
|
||||
_sem_trywait;
|
||||
_sem_unlink;
|
||||
_sem_wait;
|
||||
_sigaction;
|
||||
_sigpending;
|
||||
_sigprocmask;
|
||||
_sigsuspend;
|
||||
_sigwait;
|
||||
_sleep;
|
||||
_spinlock;
|
||||
_spinlock_debug;
|
||||
_spinunlock;
|
||||
_system;
|
||||
_tcdrain;
|
||||
_vfork;
|
||||
_wait;
|
||||
_waitpid;
|
||||
aio_suspend;
|
||||
close;
|
||||
creat;
|
||||
fcntl;
|
||||
fork;
|
||||
fsync;
|
||||
msync;
|
||||
nanosleep;
|
||||
open;
|
||||
pause;
|
||||
poll;
|
||||
pselect;
|
||||
pthread_attr_destroy;
|
||||
pthread_attr_get_np;
|
||||
pthread_attr_getdetachstate;
|
||||
pthread_attr_getguardsize;
|
||||
pthread_attr_getinheritsched;
|
||||
pthread_attr_getschedparam;
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr;
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setcreatesuspend_np;
|
||||
pthread_attr_setdetachstate;
|
||||
pthread_attr_setguardsize;
|
||||
pthread_attr_setinheritsched;
|
||||
pthread_attr_setschedparam;
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr;
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cancel;
|
||||
pthread_cleanup_pop;
|
||||
pthread_cleanup_push;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
pthread_cond_init;
|
||||
pthread_cond_signal;
|
||||
pthread_cond_timedwait;
|
||||
pthread_cond_wait;
|
||||
pthread_condattr_destroy;
|
||||
pthread_condattr_init;
|
||||
pthread_create;
|
||||
pthread_detach;
|
||||
pthread_equal;
|
||||
pthread_exit;
|
||||
pthread_getconcurrency;
|
||||
pthread_getprio;
|
||||
pthread_getschedparam;
|
||||
pthread_getspecific;
|
||||
pthread_join;
|
||||
pthread_key_create;
|
||||
pthread_key_delete;
|
||||
pthread_kill;
|
||||
pthread_main_np;
|
||||
pthread_multi_np;
|
||||
pthread_mutex_destroy;
|
||||
pthread_mutex_getprioceiling;
|
||||
pthread_mutex_init;
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_setprioceiling;
|
||||
pthread_mutex_trylock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_mutexattr_destroy;
|
||||
pthread_mutexattr_getkind_np;
|
||||
pthread_mutexattr_getprioceiling;
|
||||
pthread_mutexattr_getprotocol;
|
||||
pthread_mutexattr_gettype;
|
||||
pthread_mutexattr_init;
|
||||
pthread_mutexattr_setkind_np;
|
||||
pthread_mutexattr_setprioceiling;
|
||||
pthread_mutexattr_setprotocol;
|
||||
pthread_mutexattr_settype;
|
||||
pthread_once;
|
||||
pthread_resume_all_np;
|
||||
pthread_resume_np;
|
||||
pthread_rwlock_destroy;
|
||||
pthread_rwlock_init;
|
||||
pthread_rwlock_rdlock;
|
||||
pthread_rwlock_tryrdlock;
|
||||
pthread_rwlock_trywrlock;
|
||||
pthread_rwlock_unlock;
|
||||
pthread_rwlock_wrlock;
|
||||
pthread_rwlockattr_destroy;
|
||||
pthread_rwlockattr_getpshared;
|
||||
pthread_rwlockattr_init;
|
||||
pthread_rwlockattr_setpshared;
|
||||
pthread_self;
|
||||
pthread_set_name_np;
|
||||
pthread_setcancelstate;
|
||||
pthread_setcanceltype;
|
||||
pthread_setconcurrency;
|
||||
pthread_setprio;
|
||||
pthread_setschedparam;
|
||||
pthread_setspecific;
|
||||
pthread_sigmask;
|
||||
pthread_single_np;
|
||||
pthread_suspend_all_np;
|
||||
pthread_suspend_np;
|
||||
pthread_switch_add_np;
|
||||
pthread_switch_delete_np;
|
||||
pthread_testcancel;
|
||||
pthread_yield;
|
||||
read;
|
||||
readv;
|
||||
sched_yield;
|
||||
select;
|
||||
sem_close;
|
||||
sem_destroy;
|
||||
sem_getvalue;
|
||||
sem_init;
|
||||
sem_open;
|
||||
sem_post;
|
||||
sem_trywait;
|
||||
sem_unlink;
|
||||
sem_wait;
|
||||
sigaction;
|
||||
sigpending;
|
||||
sigprocmask;
|
||||
sigsuspend;
|
||||
sigwait;
|
||||
sleep;
|
||||
system;
|
||||
tcdrain;
|
||||
vfork;
|
||||
wait;
|
||||
wait4;
|
||||
waitpid;
|
||||
write;
|
||||
writev;
|
||||
|
||||
# Debugger needs these.
|
||||
_thread_list;
|
||||
_thread_next_offset;
|
||||
_thread_uniqueid_offset;
|
||||
_thread_state_offset;
|
||||
_thread_name_offset;
|
||||
_thread_ctx_offset;
|
||||
_thread_PS_RUNNING_value;
|
||||
_thread_PS_DEAD_value;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
10
lib/libpthread/support/Makefile.inc
Normal file
10
lib/libpthread/support/Makefile.inc
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/support
|
||||
|
||||
SRCS += thr_support.c
|
||||
SOBJS+= thr_libc.So
|
||||
|
||||
thr_libc.So: thr_support.So
|
||||
${CC} -nostdlib -L/usr/lib -o ${.TARGET} -Wl,-x,-r ${.ALLSRC} -lc_pic
|
||||
|
55
lib/libpthread/support/thr_support.c
Normal file
55
lib/libpthread/support/thr_support.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*-
|
||||
* Copyright 2003 Alexander Kabaev.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kse.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
__strong_reference(clock_gettime, _thr_clock_gettime);
|
||||
__strong_reference(kse_exit, _thr_kse_exit);
|
||||
__strong_reference(kse_wakeup, _thr_kse_wakeup);
|
||||
__strong_reference(kse_create, _thr_kse_create);
|
||||
__strong_reference(kse_thr_interrupt, _thr_kse_thr_interrupt);
|
||||
__strong_reference(kse_release, _thr_kse_release);
|
||||
|
||||
__strong_reference(sigaction, _thr_sigaction);
|
||||
__strong_reference(sigprocmask, _thr_sigprocmask);
|
||||
__strong_reference(sigemptyset, _thr_sigemptyset);
|
||||
__strong_reference(sigaddset, _thr_sigaddset);
|
||||
__strong_reference(sigfillset, _thr_sigfillset);
|
||||
__strong_reference(sigismember, _thr_sigismember);
|
||||
__strong_reference(sigdelset, _thr_sigdelset);
|
||||
|
||||
__strong_reference(memset, _thr_memset);
|
||||
__strong_reference(memcpy, _thr_memcpy);
|
||||
__strong_reference(strcpy, _thr_strcpy);
|
||||
__strong_reference(strlen, _thr_strlen);
|
||||
__strong_reference(bzero, _thr_bzero);
|
||||
|
@ -4,3 +4,4 @@
|
||||
|
||||
SRCS+= thr_error.c _atomic_lock.S ksd.c thr_enter_uts.S thr_getcontext.S \
|
||||
thr_switch.S lock.c
|
||||
|
||||
|
@ -71,6 +71,7 @@ SRCS+= \
|
||||
thr_read.c \
|
||||
thr_readv.c \
|
||||
thr_resume_np.c \
|
||||
thr_rtld.c \
|
||||
thr_rwlock.c \
|
||||
thr_rwlockattr.c \
|
||||
thr_select.c \
|
||||
|
@ -355,6 +355,8 @@ _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_cond_wait, _thr_cond_wait);
|
||||
|
||||
int
|
||||
__pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
@ -632,6 +634,8 @@ _pthread_cond_signal(pthread_cond_t * cond)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_cond_signal, _thr_cond_signal);
|
||||
|
||||
int
|
||||
_pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
{
|
||||
@ -673,7 +677,7 @@ _pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
/* There are no more waiting threads: */
|
||||
(*cond)->c_mutex = NULL;
|
||||
break;
|
||||
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
@ -689,6 +693,8 @@ _pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_cond_broadcast, _thr_cond_broadcast);
|
||||
|
||||
void
|
||||
_cond_wait_backout(struct pthread *curthread)
|
||||
{
|
||||
|
@ -47,16 +47,12 @@ __weak_reference(_pthread_exit, pthread_exit);
|
||||
void
|
||||
_thr_exit(char *fname, int lineno, char *msg)
|
||||
{
|
||||
char s[256];
|
||||
|
||||
/* Prepare an error message string: */
|
||||
snprintf(s, sizeof(s),
|
||||
/* Write an error message to the standard error file descriptor: */
|
||||
_thread_printf(2,
|
||||
"Fatal error '%s' at line %d in file %s (errno = %d)\n",
|
||||
msg, lineno, fname, errno);
|
||||
|
||||
/* Write the string to the standard error file descriptor: */
|
||||
__sys_write(2, s, strlen(s));
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -304,6 +304,8 @@ _libpthread_init(struct pthread *curthread)
|
||||
_thr_initial->kse->k_curthread = _thr_initial;
|
||||
_thr_initial->kse->k_flags |= KF_INITIALIZED;
|
||||
_kse_initial->k_curthread = _thr_initial;
|
||||
|
||||
_thr_rtld_init();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -718,6 +718,8 @@ __pthread_mutex_lock(pthread_mutex_t *m)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(__pthread_mutex_lock, _thr_mutex_lock);
|
||||
|
||||
int
|
||||
_pthread_mutex_lock(pthread_mutex_t *m)
|
||||
{
|
||||
@ -748,6 +750,8 @@ _pthread_mutex_unlock(pthread_mutex_t *m)
|
||||
return (mutex_unlock_common(m, /* add reference */ 0));
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_mutex_unlock, _thr_mutex_unlock);
|
||||
|
||||
int
|
||||
_mutex_cv_unlock(pthread_mutex_t *m)
|
||||
{
|
||||
|
@ -794,6 +794,11 @@ struct pthread {
|
||||
struct pthread_specific_elem *specific;
|
||||
int specific_data_count;
|
||||
|
||||
/*
|
||||
* Current locks bitmap for rtld.
|
||||
*/
|
||||
int rtld_bits;
|
||||
|
||||
/* Cleanup handlers Link List */
|
||||
struct pthread_cleanup *cleanup;
|
||||
char *fname; /* Ptr to source file name */
|
||||
@ -1084,6 +1089,8 @@ int _pthread_mutexattr_init(pthread_mutexattr_t *);
|
||||
int _pthread_mutexattr_destroy(pthread_mutexattr_t *);
|
||||
int _pthread_mutexattr_settype(pthread_mutexattr_t *, int);
|
||||
int _pthread_once(pthread_once_t *, void (*) (void));
|
||||
int _pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
||||
int _pthread_rwlock_destroy (pthread_rwlock_t *);
|
||||
struct pthread *_pthread_self(void);
|
||||
int _pthread_setspecific(pthread_key_t, const void *);
|
||||
struct pthread *_thr_alloc(struct pthread *);
|
||||
@ -1128,6 +1135,19 @@ void _thr_leave_cancellation_point(struct pthread *);
|
||||
int _thr_setconcurrency(int new_level);
|
||||
int _thr_setmaxconcurrency(void);
|
||||
|
||||
/*
|
||||
* Aliases for _pthread functions. Should be called instead of
|
||||
* originals if PLT replocation is unwanted at runtme.
|
||||
*/
|
||||
int _thr_cond_broadcast(pthread_cond_t *);
|
||||
int _thr_cond_signal(pthread_cond_t *);
|
||||
int _thr_cond_wait(pthread_cond_t *, pthread_mutex_t *);
|
||||
int _thr_mutex_lock(pthread_mutex_t *);
|
||||
int _thr_mutex_unlock(pthread_mutex_t *);
|
||||
int _thr_rwlock_rdlock (pthread_rwlock_t *);
|
||||
int _thr_rwlock_wrlock (pthread_rwlock_t *);
|
||||
int _thr_rwlock_unlock (pthread_rwlock_t *);
|
||||
|
||||
/* XXX - Stuff that goes away when my sources get more up to date. */
|
||||
/* #include <sys/kse.h> */
|
||||
#ifdef SYS_KSE_H
|
||||
|
137
lib/libpthread/thread/thr_rtld.c
Normal file
137
lib/libpthread/thread/thr_rtld.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Alexander Kabaev
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
#include <rtld_lock.h>
|
||||
#include "thr_private.h"
|
||||
|
||||
static void *_thr_rtld_lock_create();
|
||||
static void _thr_rtld_lock_destroy(void *);
|
||||
static void _thr_rtld_rlock_acquire(void *);
|
||||
static void _thr_rtld_wlock_acquire(void *);
|
||||
static void _thr_rtld_lock_release(void *);
|
||||
static int _thr_rtld_set_flag(int);
|
||||
static int _thr_rtld_clr_flag(int);
|
||||
|
||||
static void *
|
||||
_thr_rtld_lock_create()
|
||||
{
|
||||
pthread_rwlock_t prwlock;
|
||||
if (_pthread_rwlock_init(&prwlock, NULL))
|
||||
return (NULL);
|
||||
return (prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_lock_destroy(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
if (prwlock != NULL)
|
||||
_pthread_rwlock_destroy(&prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_rlock_acquire(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
_thr_rwlock_rdlock(&prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_wlock_acquire(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
_thr_rwlock_wrlock(&prwlock);
|
||||
}
|
||||
|
||||
static void
|
||||
_thr_rtld_lock_release(void *lock)
|
||||
{
|
||||
pthread_rwlock_t prwlock = (pthread_rwlock_t)lock;
|
||||
_thr_rwlock_unlock(&prwlock);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_thr_rtld_set_flag(int mask)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
int bits;
|
||||
|
||||
curthread = _get_curthread();
|
||||
|
||||
if (curthread != NULL) {
|
||||
bits = curthread->rtld_bits;
|
||||
curthread->rtld_bits |= mask;
|
||||
} else {
|
||||
bits = 0;
|
||||
PANIC("No current thread in rtld call");
|
||||
}
|
||||
|
||||
return (bits);
|
||||
}
|
||||
|
||||
static int
|
||||
_thr_rtld_clr_flag(int mask)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
int bits;
|
||||
|
||||
curthread = _get_curthread();
|
||||
|
||||
if (curthread != NULL) {
|
||||
bits = curthread->rtld_bits;
|
||||
curthread->rtld_bits &= ~mask;
|
||||
} else {
|
||||
bits = 0;
|
||||
PANIC("No current thread in rtld call");
|
||||
}
|
||||
return (bits);
|
||||
}
|
||||
|
||||
void
|
||||
_thr_rtld_init()
|
||||
{
|
||||
struct RtldLockInfo li;
|
||||
li.lock_create = _thr_rtld_lock_create;
|
||||
li.lock_destroy = _thr_rtld_lock_destroy;
|
||||
li.rlock_acquire = _thr_rtld_rlock_acquire;
|
||||
li.wlock_acquire = _thr_rtld_wlock_acquire;
|
||||
li.lock_release = _thr_rtld_lock_release;
|
||||
li.thread_set_flag = _thr_rtld_set_flag;
|
||||
li.thread_clr_flag = _thr_rtld_clr_flag;
|
||||
li.at_fork = NULL;
|
||||
_rtld_thread_init(&li);
|
||||
}
|
||||
|
||||
void
|
||||
_thr_rtld_fini()
|
||||
{
|
||||
_rtld_thread_init(NULL);
|
||||
}
|
@ -46,7 +46,6 @@ __weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
|
||||
__weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock);
|
||||
__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock);
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
@ -158,16 +157,16 @@ _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
}
|
||||
|
||||
/* grab the monitor lock */
|
||||
if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
|
||||
if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0)
|
||||
return (ret);
|
||||
|
||||
/* give writers priority over readers */
|
||||
while (prwlock->blocked_writers || prwlock->state < 0) {
|
||||
ret = _pthread_cond_wait(&prwlock->read_signal, &prwlock->lock);
|
||||
ret = _thr_cond_wait(&prwlock->read_signal, &prwlock->lock);
|
||||
|
||||
if (ret != 0) {
|
||||
/* can't do a whole lot if this fails */
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
@ -184,11 +183,13 @@ _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
* lock. Decrementing 'state' is no good because we probably
|
||||
* don't have the monitor lock.
|
||||
*/
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_rwlock_rdlock, _thr_rwlock_rdlock);
|
||||
|
||||
int
|
||||
_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
@ -276,28 +277,30 @@ _pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
||||
return (EINVAL);
|
||||
|
||||
/* grab the monitor lock */
|
||||
if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
|
||||
if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (prwlock->state > 0) {
|
||||
if (--prwlock->state == 0 && prwlock->blocked_writers)
|
||||
ret = _pthread_cond_signal(&prwlock->write_signal);
|
||||
ret = _thr_cond_signal(&prwlock->write_signal);
|
||||
} else if (prwlock->state < 0) {
|
||||
prwlock->state = 0;
|
||||
|
||||
if (prwlock->blocked_writers)
|
||||
ret = _pthread_cond_signal(&prwlock->write_signal);
|
||||
ret = _thr_cond_signal(&prwlock->write_signal);
|
||||
else
|
||||
ret = _pthread_cond_broadcast(&prwlock->read_signal);
|
||||
ret = _thr_cond_broadcast(&prwlock->read_signal);
|
||||
} else
|
||||
ret = EINVAL;
|
||||
|
||||
/* see the comment on this in pthread_rwlock_rdlock */
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_rwlock_unlock, _thr_rwlock_unlock);
|
||||
|
||||
int
|
||||
_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
@ -318,17 +321,17 @@ _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
}
|
||||
|
||||
/* grab the monitor lock */
|
||||
if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0)
|
||||
if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0)
|
||||
return (ret);
|
||||
|
||||
while (prwlock->state != 0) {
|
||||
++prwlock->blocked_writers;
|
||||
|
||||
ret = _pthread_cond_wait(&prwlock->write_signal, &prwlock->lock);
|
||||
ret = _thr_cond_wait(&prwlock->write_signal, &prwlock->lock);
|
||||
|
||||
if (ret != 0) {
|
||||
--prwlock->blocked_writers;
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@ -339,7 +342,9 @@ _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
prwlock->state = -1;
|
||||
|
||||
/* see the comment on this in pthread_rwlock_rdlock */
|
||||
_pthread_mutex_unlock(&prwlock->lock);
|
||||
_thr_mutex_unlock(&prwlock->lock);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
__strong_reference(_pthread_rwlock_wrlock, _thr_rwlock_wrlock);
|
||||
|
Loading…
Reference in New Issue
Block a user