]> git.saurik.com Git - apple/libc.git/blob - threads/cthreads.h
Libc-339.tar.gz
[apple/libc.git] / threads / cthreads.h
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Cthreads.
27 */
28
29 #ifndef _CTHREADS_
30 #define _CTHREADS_ 1
31
32 #if defined(__cplusplus)
33 #define __DECLBEGIN extern "C" {
34 #define __DECLEND }
35 #else
36 #define __DECLBEGIN
37 #define __DECLEND
38 #endif
39
40 typedef void *any_t;
41
42 /*
43 * Spin locks.
44 */
45 __DECLBEGIN
46 extern void spin_unlock(int *p);
47 extern void spin_lock(int *p);
48 __DECLEND
49
50 #include <mach/mach_types.h>
51 #include <mach/boolean.h>
52
53 #ifndef MACRO_BEGIN
54
55 #define NEVER FALSE
56
57 #define MACRO_BEGIN do {
58 #define MACRO_END } while (NEVER)
59
60 #endif /* MACRO_BEGIN */
61
62 /*
63 * C Threads package initialization.
64 */
65 __DECLBEGIN
66 extern void cthread_init();
67 __DECLEND
68
69 #include <stdlib.h>
70
71 /*
72 * Queues.
73 */
74 typedef struct cthread_queue {
75 struct cthread_queue_item *head;
76 struct cthread_queue_item *tail;
77 } *cthread_queue_t;
78
79 typedef struct cthread_queue_item {
80 struct cthread_queue_item *next;
81 } *cthread_queue_item_t;
82
83 #define NO_QUEUE_ITEM ((cthread_queue_item_t) 0)
84
85 #define QUEUE_INITIALIZER { NO_QUEUE_ITEM, NO_QUEUE_ITEM }
86
87 #define cthread_queue_alloc() ((cthread_queue_t) calloc(1, sizeof(struct cthread_queue)))
88 #define cthread_queue_init(q) ((q)->head = (q)->tail = 0)
89 #define cthread_queue_free(q) free((any_t) (q))
90
91 #define cthread_queue_enq(q, x) \
92 MACRO_BEGIN \
93 (x)->next = 0; \
94 if ((q)->tail == 0) \
95 (q)->head = (cthread_queue_item_t) (x); \
96 else \
97 (q)->tail->next = (cthread_queue_item_t) (x); \
98 (q)->tail = (cthread_queue_item_t) (x); \
99 MACRO_END
100
101 #define cthread_queue_preq(q, x) \
102 MACRO_BEGIN \
103 if ((q)->tail == 0) \
104 (q)->tail = (cthread_queue_item_t) (x); \
105 ((cthread_queue_item_t) (x))->next = (q)->head; \
106 (q)->head = (cthread_queue_item_t) (x); \
107 MACRO_END
108
109 #define cthread_queue_head(q, t) ((t) ((q)->head))
110
111 #define cthread_queue_deq(q, t, x) \
112 MACRO_BEGIN \
113 if (((x) = (t) ((q)->head)) != 0 && \
114 ((q)->head = (cthread_queue_item_t) ((x)->next)) == 0) \
115 (q)->tail = 0; \
116 MACRO_END
117
118 #define cthread_queue_map(q, t, f) \
119 MACRO_BEGIN \
120 register cthread_queue_item_t x, next; \
121 for (x = (cthread_queue_item_t) ((q)->head); x != 0; x = next) { \
122 next = x->next; \
123 (*(f))((t) x); \
124 } \
125 MACRO_END
126
127
128 /*
129 * Mutex objects.
130 */
131 typedef struct mutex {
132 int lock;
133 char *name;
134 } *mutex_t;
135
136 #define MUTEX_INITIALIZER { 0, 0 }
137
138 #define mutex_alloc() ((mutex_t) calloc(1, sizeof(struct mutex)))
139 #define mutex_init(m) ((m)->lock = 0)
140 #define mutex_set_name(m, x) ((m)->name = (x))
141 #define mutex_name(m) ((m)->name != 0 ? (m)->name : "?")
142 #define mutex_clear(m) /* nop */
143 #define mutex_free(m) free((any_t) (m))
144
145 #define mutex_lock(m) \
146 MACRO_BEGIN \
147 if (! mutex_try_lock(m)) mutex_wait_lock(m); \
148 MACRO_END
149
150 __DECLBEGIN
151 extern int mutex_try_lock(mutex_t m); /* nonblocking */
152 extern void mutex_wait_lock(mutex_t m); /* blocking */
153 extern void mutex_unlock(mutex_t m);
154 __DECLEND
155
156 /*
157 * Condition variables.
158 */
159 typedef struct condition {
160 int lock;
161 struct cthread_queue queue;
162 char *name;
163 } *condition_t;
164
165 #define CONDITION_INITIALIZER { 0, QUEUE_INITIALIZER, 0 }
166
167 #define condition_alloc() ((condition_t) calloc(1, sizeof(struct condition)))
168 #define condition_init(c) MACRO_BEGIN (c)->lock = 0; cthread_queue_init(&(c)->queue); MACRO_END
169 #define condition_set_name(c, x) ((c)->name = (x))
170 #define condition_name(c) ((c)->name != 0 ? (c)->name : "?")
171 #define condition_clear(c) MACRO_BEGIN condition_broadcast(c); spin_lock(&(c)->lock); MACRO_END
172 #define condition_free(c) MACRO_BEGIN condition_clear(c); free((any_t) (c)); MACRO_END
173
174 #define condition_signal(c) \
175 MACRO_BEGIN \
176 if ((c)->queue.head) cond_signal(c); \
177 MACRO_END
178
179 #define condition_broadcast(c) \
180 MACRO_BEGIN \
181 if ((c)->queue.head) cond_broadcast(c); \
182 MACRO_END
183
184 __DECLBEGIN
185 extern void cond_signal(condition_t c);
186 extern void cond_broadcast(condition_t c);
187 extern void condition_wait(condition_t c, mutex_t m);
188 __DECLEND
189
190 /*
191 * Threads.
192 */
193
194 typedef any_t (*cthread_fn_t)(any_t arg);
195
196 #import <setjmp.h>
197
198 typedef struct cthread {
199 struct cthread *next;
200 thread_port_t real_thread;
201 struct mutex lock;
202 struct condition done;
203 int state;
204 #if defined(__cplusplus)
205 jmp_buf catchBuf;
206 #else
207 jmp_buf catch;
208 #endif
209 cthread_fn_t func;
210 any_t arg;
211 any_t result;
212 const char *name;
213 any_t data;
214 } *cthread_t;
215
216 #define NO_CTHREAD ((cthread_t) 0)
217
218 __DECLBEGIN
219 extern cthread_t cthread_fork(cthread_fn_t func, any_t arg);
220 extern void cthread_detach(cthread_t t);
221 extern any_t cthread_join(cthread_t t);
222 extern void cthread_yield(void);
223 extern void cthread_exit(any_t result);
224 extern kern_return_t cthread_priority(
225 cthread_t t,
226 int priority,
227 boolean_t set_max);
228 extern kern_return_t cthread_max_priority(
229 cthread_t t,
230 mach_port_t pset,
231 int max_priority);
232 extern kern_return_t cthread_abort(cthread_t t);
233 __DECLEND
234
235 /*
236 * This structure must agree with struct cproc in cthread_internals.h
237 */
238 typedef struct ur_cthread {
239 struct ur_cthread *next;
240 cthread_t incarnation;
241 } *ur_cthread_t;
242
243 __DECLBEGIN
244 extern int cthread_sp(void);
245
246 extern int cthread_stack_mask;
247
248 extern ur_cthread_t ur_cthread_self(void);
249 #define cthread_thread(c) (c->real_thread)
250 extern void cthread_set_errno_self(int e);
251 extern int cthread_errno(void);
252 #define cthread_assoc(id, t) (((ur_cthread_t) (id))->incarnation = (t))
253 #define cthread_self() (ur_cthread_self()->incarnation)
254
255 extern void cthread_set_name(cthread_t t, const char *name);
256 extern const char *cthread_name(cthread_t t);
257 extern int cthread_count(void);
258 extern void cthread_set_limit(int n);
259 extern int cthread_limit(void);
260 __DECLEND
261
262 #define cthread_set_data(t, x) ((t)->data = (x))
263 #define cthread_data(t) ((t)->data)
264
265 /*
266 * Spin locks.
267 */
268 #define spin_unlock(p) (*(p) = 0)
269
270 /*
271 * Mutex locks.
272 */
273 #define mutex_unlock(m) ((m)->lock = 0)
274
275
276 /*
277 * Debugging support.
278 */
279 #ifdef CTHREADS_DEBUG
280
281 #ifndef ASSERT
282 /*
283 * Assertion macro, similar to <assert.h>
284 */
285 #import <stdio.h>
286 #define ASSERT(p) \
287 MACRO_BEGIN \
288 if (!(p)) { \
289 fprintf(stderr, \
290 "File %s, line %d: assertion p failed.\n", \
291 __FILE__, __LINE__); \
292 abort(); \
293 } \
294 MACRO_END
295
296 #endif /* ASSERT */
297
298 #define SHOULDNT_HAPPEN 0
299
300 extern int cthread_debug;
301
302 #else /* CTHREADS_DEBUG */
303
304 #ifndef ASSERT
305 #define ASSERT(p)
306 #endif /* ASSERT */
307
308 #endif /* CTHREADS_DEBUG */
309
310 #endif /* _CTHREADS_ */