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