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