From c1f295aa8666eb1c08a1edf944ac5617659a066c Mon Sep 17 00:00:00 2001 From: d <> Date: Fri, 20 Nov 1998 11:18:51 +0000 Subject: Add thread-safety to libc, so that libc_r will build (on i386 at least). All POSIX libc api now there (to P1003.1c/D10) (more md stuff is needed for other libc/arch/*) (setlogin is no longer a special syscall) Add -pthread option to gcc (that makes it use -lc_r and -D_POSIX_THREADS). Doc some re-entrant routines Add libc_r to intro(3) dig() uses some libc srcs and an extra -I was needed there. Add more md stuff to libc_r. Update includes for the pthreads api Update libc_r TODO --- src/lib/libc/crypt/Makefile.inc | 4 +- src/lib/libc/include/spinlock.h | 73 ++++++++++++++ src/lib/libc/include/thread_private.h | 175 ++++++++++++++++++++++++++++++++++ src/lib/libc/net/Makefile.inc | 6 +- src/lib/libc/net/gethostnamadr.c | 84 ++++++++++++++-- src/lib/libc/net/getservbyname.c | 26 ++++- src/lib/libc/stdlib/Makefile.inc | 2 +- src/lib/libc/stdlib/abort.c | 11 ++- src/lib/libc/stdlib/exit.c | 11 ++- src/lib/libc/stdlib/malloc.c | 30 ++++-- src/lib/libc/stdlib/rand.3 | 19 +++- src/lib/libc/stdlib/rand.c | 12 ++- src/lib/libc/string/Makefile.inc | 14 +-- 13 files changed, 430 insertions(+), 37 deletions(-) create mode 100644 src/lib/libc/include/spinlock.h create mode 100644 src/lib/libc/include/thread_private.h (limited to 'src') diff --git a/src/lib/libc/crypt/Makefile.inc b/src/lib/libc/crypt/Makefile.inc index 9d96d657db..8364da1e6e 100644 --- a/src/lib/libc/crypt/Makefile.inc +++ b/src/lib/libc/crypt/Makefile.inc @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile.inc,v 1.10 1998/07/21 22:23:20 provos Exp $ +# $OpenBSD: Makefile.inc,v 1.11 1998/11/20 11:18:33 d Exp $ -.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/crypt ${.CURDIR}/crypt +.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/crypt ${LIBCSRCDIR}/crypt SRCS+= cast.c crypt.c morecrypt.c md5crypt.c arc4random.c blowfish.c SRCS+= bcrypt.c diff --git a/src/lib/libc/include/spinlock.h b/src/lib/libc/include/spinlock.h new file mode 100644 index 0000000000..e4871f9aed --- /dev/null +++ b/src/lib/libc/include/spinlock.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1998 John Birrell . + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * $Id: spinlock.h,v 1.1 1998/11/20 11:18:41 d Exp $ + * $OpenBSD: spinlock.h,v 1.1 1998/11/20 11:18:41 d Exp $ + * + * Lock definitions used in both libc and libpthread. + * + */ + +#ifndef _SPINLOCK_H_ +#define _SPINLOCK_H_ +#include +#include + +/* + * Lock structure with room for debugging information. + */ +typedef struct { + volatile register_t access_lock; + volatile long lock_owner; + volatile const char * fname; + volatile int lineno; +} spinlock_t; + +#define _SPINLOCK_INITIALIZER { 0, 0, 0, 0 } + +#define _SPINUNLOCK(_lck) (_lck)->access_lock = 0 +#ifdef _LOCK_DEBUG +#define _SPINLOCK(_lck) _spinlock_debug(_lck, __FILE__, __LINE__) +#else +#define _SPINLOCK(_lck) _spinlock(_lck) +#endif + +/* + * Thread function prototype definitions: + */ +__BEGIN_DECLS +register_t _atomic_lock __P((volatile register_t *)); +register_t _thread_slow_atomic_lock __P((volatile register_t *)); +void _spinlock __P((spinlock_t *)); +void _spinlock_debug __P((spinlock_t *, const char *, int)); +__END_DECLS + +#endif /* _SPINLOCK_H_ */ diff --git a/src/lib/libc/include/thread_private.h b/src/lib/libc/include/thread_private.h new file mode 100644 index 0000000000..a7f7749078 --- /dev/null +++ b/src/lib/libc/include/thread_private.h @@ -0,0 +1,175 @@ +/* + * + * Support for thread-safety in libc and libc_r common code using macros + * to declare thread-safe data structures. + * + * $OpenBSD: thread_private.h,v 1.1 1998/11/20 11:18:41 d Exp $ + */ + +#ifndef _THREAD_PRIVATE_H_ +#define _THREAD_PRIVATE_H_ + +/* + * Parts of this file are + * Copyright (c) 1998 John Birrell . + * All rights reserved. + * + * $Id: thread_private.h,v 1.1 1998/11/20 11:18:41 d Exp $ + * $OpenBSD: thread_private.h,v 1.1 1998/11/20 11:18:41 d Exp $ + */ + +/* + * This global flag is non-zero when a process has created one + * or more threads. It is used to avoid calling locking functions + * when they are not required. In libc, this is always assumed + * to be zero. + */ + +extern volatile int __isthreaded; + +#ifdef _THREAD_SAFE + +#include +#include "pthread_private.h" + +#ifdef __STDC__ +#define __THREAD_MUTEXP_NAME(name) _thread_mutexp_inst__ ## name +#define __THREAD_MUTEX_NAME(name) _thread_mutex_inst__ ## name +#define __THREAD_KEY_NAME(name) _thread_key_inst__ ## name +#else +#define __THREAD_MUTEXP_NAME(name) _thread_mutexp_inst__/**/name +#define __THREAD_MUTEX_NAME(name) _thread_mutex_inst__/**/name +#define __THREAD_KEY_NAME(name) _thread_key_inst__/**/name +#endif + +/* + * Mutex declare, lock and unlock macros. + */ + +#define _THREAD_PRIVATE_MUTEX(name) \ + static struct pthread_mutex __THREAD_MUTEXP_NAME(name) = \ + PTHREAD_MUTEX_STATIC_INITIALIZER; \ + static pthread_mutex_t __THREAD_MUTEX_NAME(name) = \ + &__THREAD_MUTEXP_NAME(name); + +#define _THREAD_PRIVATE_MUTEX_LOCK(name) \ + pthread_mutex_lock(&__THREAD_MUTEX_NAME(name)) + +#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ + pthread_mutex_unlock(&__THREAD_MUTEX_NAME(name)) + +/* + * These macros help in making persistent storage thread-specific. + * Libc makes extensive use of private static data structures + * that hold state across function invocation, and these macros + * are no-ops when _THREAD_SAFE is not defined. + * In a thread-safe library, the static variables are used only for + * initialising the per-thread instances of the state variables. + */ + +/* + * a mutexed data structure used to hold the persistent state's key + */ +struct _thread_private_key_struct { + struct pthread_mutex lockd; + pthread_mutex_t lock; + int init; + pthread_key_t key; +}; + +/* + * Declaration of a per-thread state key. + */ +#define _THREAD_PRIVATE_KEY(name) \ + static volatile struct _thread_private_key_struct \ + __THREAD_KEY_NAME(name) = { \ + PTHREAD_MUTEX_STATIC_INITIALIZER, \ + &__THREAD_KEY_NAME(name).lockd, \ + 0 \ + }; + +/* + * Initialisation of storage space for a per-thread state variable. + * A pointer to a per-thread *copy* of the _initv parameter is returned. + * It calls malloc the first time and the space is automatically free'd + * when the thread dies. If you need something a bit more complicated + * than free() you will need to roll-your-own. + */ +#define _THREAD_PRIVATE(keyname, _initv, _errv) \ + ({ \ + struct _thread_private_key_struct * __k = \ + &__THREAD_KEY_NAME(keyname); \ + void* __p; \ + extern void free __P((void*)); \ + extern void* malloc __P((size_t)); \ + \ + if (!__isthreaded) { \ + /* non-threaded behaviour */ \ + __p = &(_initv); \ + goto _ok; \ + } \ + \ + /* create key for first thread */ \ + pthread_mutex_lock(&__k->lock); \ + if (__k->init == 0) { \ + if (pthread_key_create(&__k->key, free)) { \ + pthread_mutex_unlock(&__k->lock); \ + goto _err; \ + } \ + __k->init = 1; \ + } \ + pthread_mutex_unlock(&__k->lock); \ + \ + if ((__p = pthread_getspecific(__k->key)) == NULL) { \ + /* alloc space on 1st call in this thread */ \ + if ((__p = malloc(sizeof(_initv))) == NULL) \ + goto _err; \ + if (pthread_setspecific(__k->key, __p) != 0) { \ + free(__p); \ + goto _err; \ + } \ + /* initialise with _initv */ \ + memcpy(__p, &_initv, sizeof(_initv)); \ + } \ + goto _ok; \ + _err: \ + __p = (_errv); \ + _ok: \ + __p; \ + }) + +#else + + +/* + * do-nothing macros for single-threaded case + */ +#define _FD_LOCK(f,o,p) (0) +#define _FD_UNLOCK(f,o) /* nothing */ +#define _THREAD_PRIVATE_KEY(_key) /* nothing */ +#define _THREAD_PRIVATE(keyname, _initv, _errv) (&(_initv)) +#define _THREAD_PRIVATE_MUTEX(_name) /* nothing */ +#define _THREAD_PRIVATE_MUTEX_LOCK(_name) /* nothing */ +#define _THREAD_PRIVATE_MUTEX_UNLOCK(_name) /* nothing */ + +#endif + +/* + * File lock contention is difficult to diagnose without knowing + * where locks were set. Allow a debug library to be built which + * records the source file and line number of each lock call. + */ +#ifdef _FLOCK_DEBUG +#define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__) +#else +#define _FLOCKFILE(x) flockfile(x) +#endif + +/* + * Macros for locking and unlocking FILEs. These test if the + * process is threaded to avoid locking when not required. + */ +#define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp) +#define FUNLOCKFILE(fp) if (__isthreaded) funlockfile(fp) + +#endif _THREAD_PRIVATE_H_ diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc index 935a1904c1..35a9632a94 100644 --- a/src/lib/libc/net/Makefile.inc +++ b/src/lib/libc/net/Makefile.inc @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.16 1998/08/29 21:11:40 deraadt Exp $ +# $OpenBSD: Makefile.inc,v 1.17 1998/11/20 11:18:43 d Exp $ # net sources -.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/net ${.CURDIR}/net +.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net CFLAGS+=-DRESOLVSORT @@ -19,7 +19,7 @@ SRCS+= base64.c gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ # m-d Makefile.inc must include sources for: # htonl() htons() ntohl() ntohs() -.include "${.CURDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc" +.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc" MAN+= byteorder.3 ethers.3 gethostbyname.3 getnetent.3 getprotoent.3 \ getservent.3 inet.3 inet_net.3 iso_addr.3 link_addr.3 ns.3 ipx.3 \ diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c index 7321225863..6ff456fb0c 100644 --- a/src/lib/libc/net/gethostnamadr.c +++ b/src/lib/libc/net/gethostnamadr.c @@ -52,7 +52,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.30 1998/03/16 05:06:55 millert Exp $"; +static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.31 1998/11/20 11:18:44 d Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -67,12 +67,14 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.30 1998/03/16 05:06:55 mill #include #include #include +#include #ifdef YP #include #include #include #include "ypinternal.h" #endif +#include "thread_private.h" #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ @@ -423,6 +425,60 @@ getanswer(answer, anslen, qname, qtype) return (NULL); } +#ifndef notyet +/* + * XXX This is an extremely bogus implementations. + * + * FreeBSD has this interface: + * int gethostbyaddr_r(const char *addr, int len, int type, + * struct hostent *result, struct hostent_data *buffer) + */ + +struct hostent * +gethostbyname_r(name, hp, buf, buflen, errorp) + const char * name; + struct hostent * hp; + char * buf; + int buflen; + int * errorp; +{ + struct hostent *res; + + res = gethostbyname(name); + *errorp = h_errno; + if (res == NULL) + return NULL; + memcpy(hp, res, sizeof *hp); /* XXX not sufficient */ + return hp; +} + +/* + * XXX This is an extremely bogus implementations. + */ +struct hostent * +gethostbyaddr_r(addr, len, af, he, buf, buflen, errorp) + const char *addr; /* XXX should have been def'd as u_char! */ + int len, af; + struct hostent * he; + char * buf; + int buflen; + int * errorp; +{ + struct hostent * res; + + res = gethostbyaddr(addr, len, af); + *errorp = h_errno; + if (res == NULL) + return NULL; + memcpy(he, res, sizeof *he); /* XXX not sufficient */ + return he; +} + +/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */ +#endif + +_THREAD_PRIVATE_MUTEX(gethostnamadr) + struct hostent * gethostbyname(name) const char *name; @@ -430,15 +486,19 @@ gethostbyname(name) struct hostent *hp; extern struct hostent *_gethtbyname2(); + _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr); if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (_gethtbyname2(name, AF_INET)); + hp = _gethtbyname2(name, AF_INET); - if (_res.options & RES_USE_INET6) { + else if (_res.options & RES_USE_INET6) { hp = gethostbyname2(name, AF_INET6); - if (hp) - return (hp); + if (hp == NULL) + hp = gethostbyname2(name, AF_INET); } - return (gethostbyname2(name, AF_INET)); + else + hp = gethostbyname2(name, AF_INET); + _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr); + return hp; } struct hostent * @@ -599,9 +659,14 @@ gethostbyaddr(addr, len, af) char qbuf[MAXDNAME+1], *qp; extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); char lookups[MAXDNSLUS]; + struct hostent *res; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (_gethtbyaddr(addr, len, af)); + _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr); + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + res = _gethtbyaddr(addr, len, af); + _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr); + return (res); + } if (af == AF_INET6 && len == IN6ADDRSZ && (!bcmp(uaddr, mapped, sizeof mapped) || @@ -622,11 +687,13 @@ gethostbyaddr(addr, len, af) default: errno = EAFNOSUPPORT; h_errno = NETDB_INTERNAL; + _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr); return (NULL); } if (size != len) { errno = EINVAL; h_errno = NETDB_INTERNAL; + _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr); return (NULL); } switch (af) { @@ -692,6 +759,7 @@ gethostbyaddr(addr, len, af) break; } } + _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr); /* XXX h_errno not correct in all cases... */ return (hp); } diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c index 25f0e27d06..7375c89404 100644 --- a/src/lib/libc/net/getservbyname.c +++ b/src/lib/libc/net/getservbyname.c @@ -32,21 +32,28 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.3 1997/07/09 01:08:34 millert Exp $"; +static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.4 1998/11/20 11:18:44 d Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include +#include "thread_private.h" extern int _serv_stayopen; +_THREAD_PRIVATE_MUTEX(getservbyname_r) + struct servent * -getservbyname(name, proto) +getservbyname_r(name, proto, se, buf, buflen) const char *name, *proto; + struct servent *se; + char *buf; + int buflen; { register struct servent *p; register char **cp; + _THREAD_PRIVATE_MUTEX_LOCK(getservbyname_r); setservent(_serv_stayopen); while ((p = getservent())) { if (strcmp(name, p->s_name) == 0) @@ -61,5 +68,20 @@ gotname: } if (!_serv_stayopen) endservent(); + _THREAD_PRIVATE_MUTEX_UNLOCK(getservbyname_r); return (p); } + +struct servent *getservbyname(name, proto) + const char *name, *proto; +{ + _THREAD_PRIVATE_KEY(getservbyname) + static char buf[4096]; + char *bufp = (char*)_THREAD_PRIVATE(getservbyname, buf, NULL); + + if (bufp == NULL) + return (NULL); + return getservbyname_r(name, proto, (struct servent*) bufp, + bufp + sizeof(struct servent), + sizeof buf - sizeof(struct servent) ); +} diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc index bdd5280dde..3191f08328 100644 --- a/src/lib/libc/stdlib/Makefile.inc +++ b/src/lib/libc/stdlib/Makefile.inc @@ -1,7 +1,7 @@ # $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $ # stdlib sources -.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib +.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c \ cfree.c exit.c getenv.c getopt.c getsubopt.c heapsort.c l64a.c \ diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c index 4ea8a2ca4b..4cc6257acb 100644 --- a/src/lib/libc/stdlib/abort.c +++ b/src/lib/libc/stdlib/abort.c @@ -32,12 +32,13 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: abort.c,v 1.5 1997/06/22 20:21:25 tholo Exp $"; +static char *rcsid = "$OpenBSD: abort.c,v 1.6 1998/11/20 11:18:49 d Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include +#include "thread_private.h" void (*__cleanup)(); @@ -54,7 +55,11 @@ abort() * any errors -- X311J doesn't allow abort to return anyway. */ sigdelset(&mask, SIGABRT); +#ifdef _THREAD_SAFE + (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); +#else _THREAD_SAFE (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); +#endif _THREAD_SAFE /* * POSIX requires we flush stdio buffers on abort @@ -71,7 +76,11 @@ abort() * it again, only harder. */ (void)signal(SIGABRT, SIG_DFL); +#ifdef _THREAD_SAFE + (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); +#else _THREAD_SAFE (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); +#endif _THREAD_SAFE (void)kill(getpid(), SIGABRT); exit(1); } diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c index e358c94fd6..bc7fd395ca 100644 --- a/src/lib/libc/stdlib/exit.c +++ b/src/lib/libc/stdlib/exit.c @@ -32,7 +32,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: exit.c,v 1.2 1996/08/19 08:33:30 tholo Exp $"; +static char *rcsid = "$OpenBSD: exit.c,v 1.3 1998/11/20 11:18:50 d Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -41,6 +41,15 @@ static char *rcsid = "$OpenBSD: exit.c,v 1.2 1996/08/19 08:33:30 tholo Exp $"; void (*__cleanup)(); +/* + * This variable is zero until a process has created a thread. + * It is used to avoid calling locking functions in libc when they + * are not required. By default, libc is intended to be(come) + * thread-safe, but without a (significant) penalty to non-threaded + * processes. + */ +int __isthreaded = 0; + /* * Exit, flushing stdio buffers if necessary. */ diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index d1d8759791..ecbf93dc48 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c @@ -8,7 +8,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: malloc.c,v 1.32 1998/08/06 16:26:32 millert Exp $"; +static char rcsid[] = "$OpenBSD: malloc.c,v 1.33 1998/11/20 11:18:50 d Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -87,15 +87,27 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.32 1998/08/06 16:26:32 millert Exp #endif /* __OpenBSD__ */ #ifdef _THREAD_SAFE -#include -static pthread_mutex_t malloc_lock; -#define THREAD_LOCK() pthread_mutex_lock(&malloc_lock) -#define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock) -#define THREAD_LOCK_INIT() pthread_mutex_init(&malloc_lock, 0); +# include "thread_private.h" +# if 0 + /* kernel threads */ +# include + static pthread_mutex_t malloc_lock; +# define THREAD_LOCK() pthread_mutex_lock(&malloc_lock) +# define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock) +# define THREAD_LOCK_INIT() pthread_mutex_init(&malloc_lock, 0); +# else + /* user threads */ +# include "spinlock.h" + static spinlock_t malloc_lock = _SPINLOCK_INITIALIZER; +# define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&malloc_lock) +# define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&malloc_lock) +# define THREAD_LOCK_INIT() +# endif #else -#define THREAD_LOCK() -#define THREAD_UNLOCK() -#define THREAD_LOCK_INIT() + /* no threads */ +# define THREAD_LOCK() +# define THREAD_UNLOCK() +# define THREAD_LOCK_INIT() #endif /* diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3 index 32d32761f1..28496ec12a 100644 --- a/src/lib/libc/stdlib/rand.3 +++ b/src/lib/libc/stdlib/rand.3 @@ -33,7 +33,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: rand.3,v 1.4 1998/07/05 19:54:22 millert Exp $ +.\" $OpenBSD: rand.3,v 1.5 1998/11/20 11:18:50 d Exp $ .\" .Dd June 29, 1991 .Dt RAND 3 @@ -48,6 +48,8 @@ .Fn srand "unsigned seed" .Ft int .Fn rand void +.Ft int +.Fn rand_r "unsigned int *seed" .Sh DESCRIPTION .Bf -symbolic These interfaces are obsoleted by @@ -73,6 +75,14 @@ with the same seed value. .Pp If no seed value is provided, the functions are automatically seeded with a value of 1. +.Pp +The +.Fn rand_r +is a thread-safe version of +.Fn rand . +Storage for the seed must be provided through the +.Ar seed +argument, and needs to have been initialized by the caller. .Sh SEE ALSO .Xr arc4random 3 , .Xr rand48 3 , @@ -85,3 +95,10 @@ and functions conform to .St -ansiC . +.Pp +The +.Fn rand_r +function +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1c Draft 10. diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c index f270ffd986..61fb66e5ec 100644 --- a/src/lib/libc/stdlib/rand.c +++ b/src/lib/libc/stdlib/rand.c @@ -32,7 +32,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: rand.c,v 1.2 1996/08/19 08:33:44 tholo Exp $"; +static char *rcsid = "$OpenBSD: rand.c,v 1.3 1998/11/20 11:18:50 d Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -40,10 +40,18 @@ static char *rcsid = "$OpenBSD: rand.c,v 1.2 1996/08/19 08:33:44 tholo Exp $"; static u_long next = 1; +int +rand_r(seed) +u_int *seed; +{ + *seed = *seed * 1103515245 + 12345; + return (u_int)(*seed / 65536) % ((u_int)RAND_MAX + 1); +} + int rand() { - return ((next = next * 1103515245 + 12345) % ((u_int)RAND_MAX + 1)); + return rand_r(&next); } void diff --git a/src/lib/libc/string/Makefile.inc b/src/lib/libc/string/Makefile.inc index 076db78945..78eee7efa5 100644 --- a/src/lib/libc/string/Makefile.inc +++ b/src/lib/libc/string/Makefile.inc @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.5 1998/07/01 01:29:44 millert Exp $ +# $OpenBSD: Makefile.inc,v 1.6 1998/11/20 11:18:51 d Exp $ # string sources -.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/string ${.CURDIR}/string +.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string ${LIBCSRCDIR}/string SRCS+= bm.c memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \ strlcat.c strlcpy.c strmode.c strsignal.c strtok.c strxfrm.c \ @@ -16,7 +16,7 @@ SRCS+= bm.c memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \ # m-d Makefile.inc may include sources for: # memcpy() memmove() strchr() strrchr() -.include "${.CURDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc" +.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc" # if no machine specific memmove(3), build one out of bcopy(3). .if empty(SRCS:Mmemmove.S) @@ -100,19 +100,19 @@ LOBJS+= memmove.ln memcpy.ln strchr.ln strrchr.ln memmove.ln: bcopy.c lint ${LINTFLAGS} -DMEMMOVE ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ - ${.CURDIR}/string/bcopy.c + ${LIBCSRCDIR}/string/bcopy.c memcpy.ln: bcopy.c lint ${LINTFLAGS} -DMEMCOPY ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ - ${.CURDIR}/string/bcopy.c + ${LIBCSRCDIR}/string/bcopy.c strchr.ln: index.c lint ${LINTFLAGS} -DSTRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ - ${.CURDIR}/string/index.c + ${LIBCSRCDIR}/string/index.c strrchr.ln: rindex.c lint ${LINTFLAGS} -DSTRRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ - ${.CURDIR}/string/rindex.c + ${LIBCSRCDIR}/string/rindex.c MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \ memcmp.3 memcpy.3 memmove.3 memset.3 rindex.3 strcasecmp.3 strcat.3 \ -- cgit v1.2.3-55-g6feb