summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authord <>1998-11-20 11:18:51 +0000
committerd <>1998-11-20 11:18:51 +0000
commitc1f295aa8666eb1c08a1edf944ac5617659a066c (patch)
treeefe0a5dfb4f9767f96ab03ce9c00dc5bcc98074c /src
parent5a11336d3f08469f2747ebcf26ae777dba46fd22 (diff)
downloadopenbsd-c1f295aa8666eb1c08a1edf944ac5617659a066c.tar.gz
openbsd-c1f295aa8666eb1c08a1edf944ac5617659a066c.tar.bz2
openbsd-c1f295aa8666eb1c08a1edf944ac5617659a066c.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/crypt/Makefile.inc4
-rw-r--r--src/lib/libc/include/spinlock.h73
-rw-r--r--src/lib/libc/include/thread_private.h175
-rw-r--r--src/lib/libc/net/Makefile.inc6
-rw-r--r--src/lib/libc/net/gethostnamadr.c84
-rw-r--r--src/lib/libc/net/getservbyname.c26
-rw-r--r--src/lib/libc/stdlib/Makefile.inc2
-rw-r--r--src/lib/libc/stdlib/abort.c11
-rw-r--r--src/lib/libc/stdlib/exit.c11
-rw-r--r--src/lib/libc/stdlib/malloc.c30
-rw-r--r--src/lib/libc/stdlib/rand.319
-rw-r--r--src/lib/libc/stdlib/rand.c12
-rw-r--r--src/lib/libc/string/Makefile.inc14
13 files changed, 430 insertions, 37 deletions
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 @@
1# $OpenBSD: Makefile.inc,v 1.10 1998/07/21 22:23:20 provos Exp $ 1# $OpenBSD: Makefile.inc,v 1.11 1998/11/20 11:18:33 d Exp $
2 2
3.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/crypt ${.CURDIR}/crypt 3.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/crypt ${LIBCSRCDIR}/crypt
4 4
5SRCS+= cast.c crypt.c morecrypt.c md5crypt.c arc4random.c blowfish.c 5SRCS+= cast.c crypt.c morecrypt.c md5crypt.c arc4random.c blowfish.c
6SRCS+= bcrypt.c 6SRCS+= 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 @@
1/*
2 * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: spinlock.h,v 1.1 1998/11/20 11:18:41 d Exp $
33 * $OpenBSD: spinlock.h,v 1.1 1998/11/20 11:18:41 d Exp $
34 *
35 * Lock definitions used in both libc and libpthread.
36 *
37 */
38
39#ifndef _SPINLOCK_H_
40#define _SPINLOCK_H_
41#include <sys/cdefs.h>
42#include <sys/types.h>
43
44/*
45 * Lock structure with room for debugging information.
46 */
47typedef struct {
48 volatile register_t access_lock;
49 volatile long lock_owner;
50 volatile const char * fname;
51 volatile int lineno;
52} spinlock_t;
53
54#define _SPINLOCK_INITIALIZER { 0, 0, 0, 0 }
55
56#define _SPINUNLOCK(_lck) (_lck)->access_lock = 0
57#ifdef _LOCK_DEBUG
58#define _SPINLOCK(_lck) _spinlock_debug(_lck, __FILE__, __LINE__)
59#else
60#define _SPINLOCK(_lck) _spinlock(_lck)
61#endif
62
63/*
64 * Thread function prototype definitions:
65 */
66__BEGIN_DECLS
67register_t _atomic_lock __P((volatile register_t *));
68register_t _thread_slow_atomic_lock __P((volatile register_t *));
69void _spinlock __P((spinlock_t *));
70void _spinlock_debug __P((spinlock_t *, const char *, int));
71__END_DECLS
72
73#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 @@
1/*
2 *
3 * Support for thread-safety in libc and libc_r common code using macros
4 * to declare thread-safe data structures.
5 *
6 * $OpenBSD: thread_private.h,v 1.1 1998/11/20 11:18:41 d Exp $
7 */
8
9#ifndef _THREAD_PRIVATE_H_
10#define _THREAD_PRIVATE_H_
11
12/*
13 * Parts of this file are
14 * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
15 * All rights reserved.
16 *
17 * $Id: thread_private.h,v 1.1 1998/11/20 11:18:41 d Exp $
18 * $OpenBSD: thread_private.h,v 1.1 1998/11/20 11:18:41 d Exp $
19 */
20
21/*
22 * This global flag is non-zero when a process has created one
23 * or more threads. It is used to avoid calling locking functions
24 * when they are not required. In libc, this is always assumed
25 * to be zero.
26 */
27
28extern volatile int __isthreaded;
29
30#ifdef _THREAD_SAFE
31
32#include <pthread.h>
33#include "pthread_private.h"
34
35#ifdef __STDC__
36#define __THREAD_MUTEXP_NAME(name) _thread_mutexp_inst__ ## name
37#define __THREAD_MUTEX_NAME(name) _thread_mutex_inst__ ## name
38#define __THREAD_KEY_NAME(name) _thread_key_inst__ ## name
39#else
40#define __THREAD_MUTEXP_NAME(name) _thread_mutexp_inst__/**/name
41#define __THREAD_MUTEX_NAME(name) _thread_mutex_inst__/**/name
42#define __THREAD_KEY_NAME(name) _thread_key_inst__/**/name
43#endif
44
45/*
46 * Mutex declare, lock and unlock macros.
47 */
48
49#define _THREAD_PRIVATE_MUTEX(name) \
50 static struct pthread_mutex __THREAD_MUTEXP_NAME(name) = \
51 PTHREAD_MUTEX_STATIC_INITIALIZER; \
52 static pthread_mutex_t __THREAD_MUTEX_NAME(name) = \
53 &__THREAD_MUTEXP_NAME(name);
54
55#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
56 pthread_mutex_lock(&__THREAD_MUTEX_NAME(name))
57
58#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
59 pthread_mutex_unlock(&__THREAD_MUTEX_NAME(name))
60
61/*
62 * These macros help in making persistent storage thread-specific.
63 * Libc makes extensive use of private static data structures
64 * that hold state across function invocation, and these macros
65 * are no-ops when _THREAD_SAFE is not defined.
66 * In a thread-safe library, the static variables are used only for
67 * initialising the per-thread instances of the state variables.
68 */
69
70/*
71 * a mutexed data structure used to hold the persistent state's key
72 */
73struct _thread_private_key_struct {
74 struct pthread_mutex lockd;
75 pthread_mutex_t lock;
76 int init;
77 pthread_key_t key;
78};
79
80/*
81 * Declaration of a per-thread state key.
82 */
83#define _THREAD_PRIVATE_KEY(name) \
84 static volatile struct _thread_private_key_struct \
85 __THREAD_KEY_NAME(name) = { \
86 PTHREAD_MUTEX_STATIC_INITIALIZER, \
87 &__THREAD_KEY_NAME(name).lockd, \
88 0 \
89 };
90
91/*
92 * Initialisation of storage space for a per-thread state variable.
93 * A pointer to a per-thread *copy* of the _initv parameter is returned.
94 * It calls malloc the first time and the space is automatically free'd
95 * when the thread dies. If you need something a bit more complicated
96 * than free() you will need to roll-your-own.
97 */
98#define _THREAD_PRIVATE(keyname, _initv, _errv) \
99 ({ \
100 struct _thread_private_key_struct * __k = \
101 &__THREAD_KEY_NAME(keyname); \
102 void* __p; \
103 extern void free __P((void*)); \
104 extern void* malloc __P((size_t)); \
105 \
106 if (!__isthreaded) { \
107 /* non-threaded behaviour */ \
108 __p = &(_initv); \
109 goto _ok; \
110 } \
111 \
112 /* create key for first thread */ \
113 pthread_mutex_lock(&__k->lock); \
114 if (__k->init == 0) { \
115 if (pthread_key_create(&__k->key, free)) { \
116 pthread_mutex_unlock(&__k->lock); \
117 goto _err; \
118 } \
119 __k->init = 1; \
120 } \
121 pthread_mutex_unlock(&__k->lock); \
122 \
123 if ((__p = pthread_getspecific(__k->key)) == NULL) { \
124 /* alloc space on 1st call in this thread */ \
125 if ((__p = malloc(sizeof(_initv))) == NULL) \
126 goto _err; \
127 if (pthread_setspecific(__k->key, __p) != 0) { \
128 free(__p); \
129 goto _err; \
130 } \
131 /* initialise with _initv */ \
132 memcpy(__p, &_initv, sizeof(_initv)); \
133 } \
134 goto _ok; \
135 _err: \
136 __p = (_errv); \
137 _ok: \
138 __p; \
139 })
140
141#else
142
143
144/*
145 * do-nothing macros for single-threaded case
146 */
147#define _FD_LOCK(f,o,p) (0)
148#define _FD_UNLOCK(f,o) /* nothing */
149#define _THREAD_PRIVATE_KEY(_key) /* nothing */
150#define _THREAD_PRIVATE(keyname, _initv, _errv) (&(_initv))
151#define _THREAD_PRIVATE_MUTEX(_name) /* nothing */
152#define _THREAD_PRIVATE_MUTEX_LOCK(_name) /* nothing */
153#define _THREAD_PRIVATE_MUTEX_UNLOCK(_name) /* nothing */
154
155#endif
156
157/*
158 * File lock contention is difficult to diagnose without knowing
159 * where locks were set. Allow a debug library to be built which
160 * records the source file and line number of each lock call.
161 */
162#ifdef _FLOCK_DEBUG
163#define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__)
164#else
165#define _FLOCKFILE(x) flockfile(x)
166#endif
167
168/*
169 * Macros for locking and unlocking FILEs. These test if the
170 * process is threaded to avoid locking when not required.
171 */
172#define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp)
173#define FUNLOCKFILE(fp) if (__isthreaded) funlockfile(fp)
174
175#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 @@
1# $OpenBSD: Makefile.inc,v 1.16 1998/08/29 21:11:40 deraadt Exp $ 1# $OpenBSD: Makefile.inc,v 1.17 1998/11/20 11:18:43 d Exp $
2 2
3# net sources 3# net sources
4.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/net ${.CURDIR}/net 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
5 5
6CFLAGS+=-DRESOLVSORT 6CFLAGS+=-DRESOLVSORT
7 7
@@ -19,7 +19,7 @@ SRCS+= base64.c gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \
19# m-d Makefile.inc must include sources for: 19# m-d Makefile.inc must include sources for:
20# htonl() htons() ntohl() ntohs() 20# htonl() htons() ntohl() ntohs()
21 21
22.include "${.CURDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc" 22.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc"
23 23
24MAN+= byteorder.3 ethers.3 gethostbyname.3 getnetent.3 getprotoent.3 \ 24MAN+= byteorder.3 ethers.3 gethostbyname.3 getnetent.3 getprotoent.3 \
25 getservent.3 inet.3 inet_net.3 iso_addr.3 link_addr.3 ns.3 ipx.3 \ 25 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 @@
52 */ 52 */
53 53
54#if defined(LIBC_SCCS) && !defined(lint) 54#if defined(LIBC_SCCS) && !defined(lint)
55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.30 1998/03/16 05:06:55 millert Exp $"; 55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.31 1998/11/20 11:18:44 d Exp $";
56#endif /* LIBC_SCCS and not lint */ 56#endif /* LIBC_SCCS and not lint */
57 57
58#include <sys/param.h> 58#include <sys/param.h>
@@ -67,12 +67,14 @@ static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.30 1998/03/16 05:06:55 mill
67#include <errno.h> 67#include <errno.h>
68#include <string.h> 68#include <string.h>
69#include <syslog.h> 69#include <syslog.h>
70#include <stdlib.h>
70#ifdef YP 71#ifdef YP
71#include <rpc/rpc.h> 72#include <rpc/rpc.h>
72#include <rpcsvc/yp.h> 73#include <rpcsvc/yp.h>
73#include <rpcsvc/ypclnt.h> 74#include <rpcsvc/ypclnt.h>
74#include "ypinternal.h" 75#include "ypinternal.h"
75#endif 76#endif
77#include "thread_private.h"
76 78
77#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ 79#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
78 80
@@ -423,6 +425,60 @@ getanswer(answer, anslen, qname, qtype)
423 return (NULL); 425 return (NULL);
424} 426}
425 427
428#ifndef notyet
429/*
430 * XXX This is an extremely bogus implementations.
431 *
432 * FreeBSD has this interface:
433 * int gethostbyaddr_r(const char *addr, int len, int type,
434 * struct hostent *result, struct hostent_data *buffer)
435 */
436
437struct hostent *
438gethostbyname_r(name, hp, buf, buflen, errorp)
439 const char * name;
440 struct hostent * hp;
441 char * buf;
442 int buflen;
443 int * errorp;
444{
445 struct hostent *res;
446
447 res = gethostbyname(name);
448 *errorp = h_errno;
449 if (res == NULL)
450 return NULL;
451 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
452 return hp;
453}
454
455/*
456 * XXX This is an extremely bogus implementations.
457 */
458struct hostent *
459gethostbyaddr_r(addr, len, af, he, buf, buflen, errorp)
460 const char *addr; /* XXX should have been def'd as u_char! */
461 int len, af;
462 struct hostent * he;
463 char * buf;
464 int buflen;
465 int * errorp;
466{
467 struct hostent * res;
468
469 res = gethostbyaddr(addr, len, af);
470 *errorp = h_errno;
471 if (res == NULL)
472 return NULL;
473 memcpy(he, res, sizeof *he); /* XXX not sufficient */
474 return he;
475}
476
477/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
478#endif
479
480_THREAD_PRIVATE_MUTEX(gethostnamadr)
481
426struct hostent * 482struct hostent *
427gethostbyname(name) 483gethostbyname(name)
428 const char *name; 484 const char *name;
@@ -430,15 +486,19 @@ gethostbyname(name)
430 struct hostent *hp; 486 struct hostent *hp;
431 extern struct hostent *_gethtbyname2(); 487 extern struct hostent *_gethtbyname2();
432 488
489 _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr);
433 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 490 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
434 return (_gethtbyname2(name, AF_INET)); 491 hp = _gethtbyname2(name, AF_INET);
435 492
436 if (_res.options & RES_USE_INET6) { 493 else if (_res.options & RES_USE_INET6) {
437 hp = gethostbyname2(name, AF_INET6); 494 hp = gethostbyname2(name, AF_INET6);
438 if (hp) 495 if (hp == NULL)
439 return (hp); 496 hp = gethostbyname2(name, AF_INET);
440 } 497 }
441 return (gethostbyname2(name, AF_INET)); 498 else
499 hp = gethostbyname2(name, AF_INET);
500 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
501 return hp;
442} 502}
443 503
444struct hostent * 504struct hostent *
@@ -599,9 +659,14 @@ gethostbyaddr(addr, len, af)
599 char qbuf[MAXDNAME+1], *qp; 659 char qbuf[MAXDNAME+1], *qp;
600 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); 660 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
601 char lookups[MAXDNSLUS]; 661 char lookups[MAXDNSLUS];
662 struct hostent *res;
602 663
603 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 664 _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr);
604 return (_gethtbyaddr(addr, len, af)); 665 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
666 res = _gethtbyaddr(addr, len, af);
667 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
668 return (res);
669 }
605 670
606 if (af == AF_INET6 && len == IN6ADDRSZ && 671 if (af == AF_INET6 && len == IN6ADDRSZ &&
607 (!bcmp(uaddr, mapped, sizeof mapped) || 672 (!bcmp(uaddr, mapped, sizeof mapped) ||
@@ -622,11 +687,13 @@ gethostbyaddr(addr, len, af)
622 default: 687 default:
623 errno = EAFNOSUPPORT; 688 errno = EAFNOSUPPORT;
624 h_errno = NETDB_INTERNAL; 689 h_errno = NETDB_INTERNAL;
690 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
625 return (NULL); 691 return (NULL);
626 } 692 }
627 if (size != len) { 693 if (size != len) {
628 errno = EINVAL; 694 errno = EINVAL;
629 h_errno = NETDB_INTERNAL; 695 h_errno = NETDB_INTERNAL;
696 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
630 return (NULL); 697 return (NULL);
631 } 698 }
632 switch (af) { 699 switch (af) {
@@ -692,6 +759,7 @@ gethostbyaddr(addr, len, af)
692 break; 759 break;
693 } 760 }
694 } 761 }
762 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
695 /* XXX h_errno not correct in all cases... */ 763 /* XXX h_errno not correct in all cases... */
696 return (hp); 764 return (hp);
697} 765}
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 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.3 1997/07/09 01:08:34 millert Exp $"; 35static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.4 1998/11/20 11:18:44 d Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <netdb.h> 38#include <netdb.h>
39#include <string.h> 39#include <string.h>
40#include "thread_private.h"
40 41
41extern int _serv_stayopen; 42extern int _serv_stayopen;
42 43
44_THREAD_PRIVATE_MUTEX(getservbyname_r)
45
43struct servent * 46struct servent *
44getservbyname(name, proto) 47getservbyname_r(name, proto, se, buf, buflen)
45 const char *name, *proto; 48 const char *name, *proto;
49 struct servent *se;
50 char *buf;
51 int buflen;
46{ 52{
47 register struct servent *p; 53 register struct servent *p;
48 register char **cp; 54 register char **cp;
49 55
56 _THREAD_PRIVATE_MUTEX_LOCK(getservbyname_r);
50 setservent(_serv_stayopen); 57 setservent(_serv_stayopen);
51 while ((p = getservent())) { 58 while ((p = getservent())) {
52 if (strcmp(name, p->s_name) == 0) 59 if (strcmp(name, p->s_name) == 0)
@@ -61,5 +68,20 @@ gotname:
61 } 68 }
62 if (!_serv_stayopen) 69 if (!_serv_stayopen)
63 endservent(); 70 endservent();
71 _THREAD_PRIVATE_MUTEX_UNLOCK(getservbyname_r);
64 return (p); 72 return (p);
65} 73}
74
75struct servent *getservbyname(name, proto)
76 const char *name, *proto;
77{
78 _THREAD_PRIVATE_KEY(getservbyname)
79 static char buf[4096];
80 char *bufp = (char*)_THREAD_PRIVATE(getservbyname, buf, NULL);
81
82 if (bufp == NULL)
83 return (NULL);
84 return getservbyname_r(name, proto, (struct servent*) bufp,
85 bufp + sizeof(struct servent),
86 sizeof buf - sizeof(struct servent) );
87}
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 @@
1# $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $ 1# $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $
2 2
3# stdlib sources 3# stdlib sources
4.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
5 5
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c \ 6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c \
7 cfree.c exit.c getenv.c getopt.c getsubopt.c heapsort.c l64a.c \ 7 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 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: abort.c,v 1.5 1997/06/22 20:21:25 tholo Exp $"; 35static char *rcsid = "$OpenBSD: abort.c,v 1.6 1998/11/20 11:18:49 d Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <signal.h> 38#include <signal.h>
39#include <stdlib.h> 39#include <stdlib.h>
40#include <unistd.h> 40#include <unistd.h>
41#include "thread_private.h"
41 42
42void (*__cleanup)(); 43void (*__cleanup)();
43 44
@@ -54,7 +55,11 @@ abort()
54 * any errors -- X311J doesn't allow abort to return anyway. 55 * any errors -- X311J doesn't allow abort to return anyway.
55 */ 56 */
56 sigdelset(&mask, SIGABRT); 57 sigdelset(&mask, SIGABRT);
58#ifdef _THREAD_SAFE
59 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
60#else _THREAD_SAFE
57 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 61 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
62#endif _THREAD_SAFE
58 63
59 /* 64 /*
60 * POSIX requires we flush stdio buffers on abort 65 * POSIX requires we flush stdio buffers on abort
@@ -71,7 +76,11 @@ abort()
71 * it again, only harder. 76 * it again, only harder.
72 */ 77 */
73 (void)signal(SIGABRT, SIG_DFL); 78 (void)signal(SIGABRT, SIG_DFL);
79#ifdef _THREAD_SAFE
80 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
81#else _THREAD_SAFE
74 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 82 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
83#endif _THREAD_SAFE
75 (void)kill(getpid(), SIGABRT); 84 (void)kill(getpid(), SIGABRT);
76 exit(1); 85 exit(1);
77} 86}
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 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: exit.c,v 1.2 1996/08/19 08:33:30 tholo Exp $"; 35static char *rcsid = "$OpenBSD: exit.c,v 1.3 1998/11/20 11:18:50 d Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <stdlib.h> 38#include <stdlib.h>
@@ -42,6 +42,15 @@ static char *rcsid = "$OpenBSD: exit.c,v 1.2 1996/08/19 08:33:30 tholo Exp $";
42void (*__cleanup)(); 42void (*__cleanup)();
43 43
44/* 44/*
45 * This variable is zero until a process has created a thread.
46 * It is used to avoid calling locking functions in libc when they
47 * are not required. By default, libc is intended to be(come)
48 * thread-safe, but without a (significant) penalty to non-threaded
49 * processes.
50 */
51int __isthreaded = 0;
52
53/*
45 * Exit, flushing stdio buffers if necessary. 54 * Exit, flushing stdio buffers if necessary.
46 */ 55 */
47void 56void
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 @@
8 */ 8 */
9 9
10#if defined(LIBC_SCCS) && !defined(lint) 10#if defined(LIBC_SCCS) && !defined(lint)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.32 1998/08/06 16:26:32 millert Exp $"; 11static char rcsid[] = "$OpenBSD: malloc.c,v 1.33 1998/11/20 11:18:50 d Exp $";
12#endif /* LIBC_SCCS and not lint */ 12#endif /* LIBC_SCCS and not lint */
13 13
14/* 14/*
@@ -87,15 +87,27 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.32 1998/08/06 16:26:32 millert Exp
87#endif /* __OpenBSD__ */ 87#endif /* __OpenBSD__ */
88 88
89#ifdef _THREAD_SAFE 89#ifdef _THREAD_SAFE
90#include <pthread.h> 90# include "thread_private.h"
91static pthread_mutex_t malloc_lock; 91# if 0
92#define THREAD_LOCK() pthread_mutex_lock(&malloc_lock) 92 /* kernel threads */
93#define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock) 93# include <pthread.h>
94#define THREAD_LOCK_INIT() pthread_mutex_init(&malloc_lock, 0); 94 static pthread_mutex_t malloc_lock;
95# define THREAD_LOCK() pthread_mutex_lock(&malloc_lock)
96# define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock)
97# define THREAD_LOCK_INIT() pthread_mutex_init(&malloc_lock, 0);
98# else
99 /* user threads */
100# include "spinlock.h"
101 static spinlock_t malloc_lock = _SPINLOCK_INITIALIZER;
102# define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&malloc_lock)
103# define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&malloc_lock)
104# define THREAD_LOCK_INIT()
105# endif
95#else 106#else
96#define THREAD_LOCK() 107 /* no threads */
97#define THREAD_UNLOCK() 108# define THREAD_LOCK()
98#define THREAD_LOCK_INIT() 109# define THREAD_UNLOCK()
110# define THREAD_LOCK_INIT()
99#endif 111#endif
100 112
101/* 113/*
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 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: rand.3,v 1.4 1998/07/05 19:54:22 millert Exp $ 36.\" $OpenBSD: rand.3,v 1.5 1998/11/20 11:18:50 d Exp $
37.\" 37.\"
38.Dd June 29, 1991 38.Dd June 29, 1991
39.Dt RAND 3 39.Dt RAND 3
@@ -48,6 +48,8 @@
48.Fn srand "unsigned seed" 48.Fn srand "unsigned seed"
49.Ft int 49.Ft int
50.Fn rand void 50.Fn rand void
51.Ft int
52.Fn rand_r "unsigned int *seed"
51.Sh DESCRIPTION 53.Sh DESCRIPTION
52.Bf -symbolic 54.Bf -symbolic
53These interfaces are obsoleted by 55These interfaces are obsoleted by
@@ -73,6 +75,14 @@ with the same seed value.
73.Pp 75.Pp
74If no seed value is provided, the functions are automatically 76If no seed value is provided, the functions are automatically
75seeded with a value of 1. 77seeded with a value of 1.
78.Pp
79The
80.Fn rand_r
81is a thread-safe version of
82.Fn rand .
83Storage for the seed must be provided through the
84.Ar seed
85argument, and needs to have been initialized by the caller.
76.Sh SEE ALSO 86.Sh SEE ALSO
77.Xr arc4random 3 , 87.Xr arc4random 3 ,
78.Xr rand48 3 , 88.Xr rand48 3 ,
@@ -85,3 +95,10 @@ and
85functions 95functions
86conform to 96conform to
87.St -ansiC . 97.St -ansiC .
98.Pp
99The
100.Fn rand_r
101function
102conforms to ISO/IEC 9945-1 ANSI/IEEE
103.Pq Dq Tn POSIX
104Std 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 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: rand.c,v 1.2 1996/08/19 08:33:44 tholo Exp $"; 35static char *rcsid = "$OpenBSD: rand.c,v 1.3 1998/11/20 11:18:50 d Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <sys/types.h> 38#include <sys/types.h>
@@ -41,9 +41,17 @@ static char *rcsid = "$OpenBSD: rand.c,v 1.2 1996/08/19 08:33:44 tholo Exp $";
41static u_long next = 1; 41static u_long next = 1;
42 42
43int 43int
44rand_r(seed)
45u_int *seed;
46{
47 *seed = *seed * 1103515245 + 12345;
48 return (u_int)(*seed / 65536) % ((u_int)RAND_MAX + 1);
49}
50
51int
44rand() 52rand()
45{ 53{
46 return ((next = next * 1103515245 + 12345) % ((u_int)RAND_MAX + 1)); 54 return rand_r(&next);
47} 55}
48 56
49void 57void
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 @@
1# $OpenBSD: Makefile.inc,v 1.5 1998/07/01 01:29:44 millert Exp $ 1# $OpenBSD: Makefile.inc,v 1.6 1998/11/20 11:18:51 d Exp $
2 2
3# string sources 3# string sources
4.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/string ${.CURDIR}/string 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string ${LIBCSRCDIR}/string
5 5
6SRCS+= bm.c memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \ 6SRCS+= bm.c memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \
7 strlcat.c strlcpy.c strmode.c strsignal.c strtok.c strxfrm.c \ 7 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 \
16# m-d Makefile.inc may include sources for: 16# m-d Makefile.inc may include sources for:
17# memcpy() memmove() strchr() strrchr() 17# memcpy() memmove() strchr() strrchr()
18 18
19.include "${.CURDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc" 19.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc"
20 20
21# if no machine specific memmove(3), build one out of bcopy(3). 21# if no machine specific memmove(3), build one out of bcopy(3).
22.if empty(SRCS:Mmemmove.S) 22.if empty(SRCS:Mmemmove.S)
@@ -100,19 +100,19 @@ LOBJS+= memmove.ln memcpy.ln strchr.ln strrchr.ln
100 100
101memmove.ln: bcopy.c 101memmove.ln: bcopy.c
102 lint ${LINTFLAGS} -DMEMMOVE ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ 102 lint ${LINTFLAGS} -DMEMMOVE ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
103 ${.CURDIR}/string/bcopy.c 103 ${LIBCSRCDIR}/string/bcopy.c
104 104
105memcpy.ln: bcopy.c 105memcpy.ln: bcopy.c
106 lint ${LINTFLAGS} -DMEMCOPY ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ 106 lint ${LINTFLAGS} -DMEMCOPY ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
107 ${.CURDIR}/string/bcopy.c 107 ${LIBCSRCDIR}/string/bcopy.c
108 108
109strchr.ln: index.c 109strchr.ln: index.c
110 lint ${LINTFLAGS} -DSTRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ 110 lint ${LINTFLAGS} -DSTRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
111 ${.CURDIR}/string/index.c 111 ${LIBCSRCDIR}/string/index.c
112 112
113strrchr.ln: rindex.c 113strrchr.ln: rindex.c
114 lint ${LINTFLAGS} -DSTRRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \ 114 lint ${LINTFLAGS} -DSTRRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
115 ${.CURDIR}/string/rindex.c 115 ${LIBCSRCDIR}/string/rindex.c
116 116
117MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \ 117MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \
118 memcmp.3 memcpy.3 memmove.3 memset.3 rindex.3 strcasecmp.3 strcat.3 \ 118 memcmp.3 memcpy.3 memmove.3 memset.3 rindex.3 strcasecmp.3 strcat.3 \