summaryrefslogtreecommitdiff
path: root/src/lib/libc/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/include')
-rw-r--r--src/lib/libc/include/spinlock.h73
-rw-r--r--src/lib/libc/include/thread_private.h175
2 files changed, 248 insertions, 0 deletions
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_