1 |
/* |
/* |
2 |
* Mach Operating System |
* Mach Operating System |
3 |
* Copyright (c) 1991,1990,1989 Carnegie Mellon University |
* Copyright (c) 1993,1992,1991,1990,1989 Carnegie Mellon University |
4 |
* All Rights Reserved. |
* All Rights Reserved. |
5 |
* |
* |
6 |
* Permission to use, copy, modify and distribute this software and its |
* Permission to use, copy, modify and distribute this software and its |
25 |
*/ |
*/ |
26 |
/* |
/* |
27 |
* HISTORY |
* HISTORY |
28 |
* $Log$ |
* 20-Oct-93 Tero Kivinen (kivinen) at Helsinki University of Technology |
29 |
* Revision 1.17 2002/05/08 09:32:14 roland |
* Renamed cthread_t->catch to to cthread_t->catch_exit, because |
30 |
* 2002-05-07 Roland McGrath <roland@frob.com> |
* catch is reserved word in c++. |
31 |
* |
* |
32 |
* * cthreads.h (cthread_sp): Cast to vm_address_t instead of int. |
* 12-Oct-93 Johannes Helander (jvh) at Helsinki University of Technology |
33 |
* (mutex_unlock): Cast to void * instead of int. |
* Added CONDITION_NAMED_INITIALIZER and MUTEX_NAMED_INITIALIZER1 |
34 |
|
* macros. They take one argument: a name string. |
35 |
* |
* |
36 |
* Revision 1.16 2001/03/31 23:01:01 roland |
* $Log$ |
37 |
* 2001-03-31 Roland McGrath <roland@frob.com> |
* Revision 1.18 2002/05/27 02:50:10 roland |
38 |
|
* 2002-05-26 Roland McGrath <roland@frob.com> |
39 |
* |
* |
40 |
* * cthreads.h: Fix obsolescent #endif syntax. |
* Changes merged from CMU MK83a version: |
41 |
* * cthread_internals.h: Likewise. |
* * cthreads.h, options.h: Various cleanups. |
42 |
* * cancel-cond.c: Likewise. |
* * call.c, cthread_data.c, sync.c, mig_support.c: Likewise. |
43 |
* * stack.c: Likewise. |
* * i386/cthreads.h, i386/thread.c, i386/lock.s: Likewise. |
44 |
|
* * cthread_internals.h: Add decls for internal functions. |
45 |
|
* (struct cproc): Use vm_offset_t for stack_base and stack_size members. |
46 |
|
* Use natural_t for context member. |
47 |
|
* * cprocs.c: Use prototypes for all defns. |
48 |
* * cthreads.c: Likewise. |
* * cthreads.c: Likewise. |
49 |
* * cprocs.c: Likewise. |
* (cthread_exit): Cast any_t to integer_t before int. |
|
* * call.c: Likewise. |
|
|
* |
|
|
* Revision 1.15 1999/06/13 18:54:42 roland |
|
|
* 1999-06-13 Roland McGrath <roland@baalperazim.frob.com> |
|
|
* |
|
|
* * cthreads.h (MACRO_BEGIN, MACRO_END): #undef before unconditionally |
|
|
* redefining. Use GCC extension for statement expression with value 0. |
|
|
* |
|
|
* Revision 1.14 1999/05/30 01:39:48 roland |
|
|
* 1999-05-29 Roland McGrath <roland@baalperazim.frob.com> |
|
|
* |
|
|
* * cthreads.h (mutex_clear): Change again, to call mutex_init. |
|
|
* |
|
|
* Revision 1.13 1999/05/29 18:59:10 roland |
|
|
* 1999-05-29 Roland McGrath <roland@baalperazim.frob.com> |
|
|
* |
|
|
* * cthreads.h (mutex_clear): Change from syntax error to no-op (with |
|
|
* warning avoidance). |
|
|
* |
|
|
* Revision 1.12 1996/05/04 10:06:31 roland |
|
|
* [lint] (NEVER): Spurious global variable removed. |
|
|
* [!lint] (NEVER): Useless macro removed. |
|
50 |
* |
* |
51 |
* Revision 1.11 1996/01/24 18:37:59 roland |
* Revision 2.17 93/05/10 19:43:11 rvb |
52 |
* Use prototypes for functions of zero args. |
* Removed include of stdlib.h and just define malloc |
53 |
* |
* [93/04/27 mrt] |
54 |
* Revision 1.10 1995/09/13 19:50:07 mib |
* |
55 |
* (CONDITION_INITIALIZER): Provide initial zero for IMPLICATIONS member. |
* Revision 2.16 93/05/10 17:51:26 rvb |
56 |
* (condition_init): Bother initializing NAME and IMPLICATIONS members. |
* Just imagine how much more useful TWO special/fast lookup |
57 |
* |
* variables could be. (Actually, I am planning on using this |
58 |
* Revision 1.9 1995/08/30 15:51:41 mib |
* for bsdss -- for multiple threads per task. If I don't, I'll |
59 |
* (condition_implies, condition_unimplies): New functions. |
* remove the feature.) |
60 |
* (struct condition): New member `implications'. |
* [93/05/10 rvb] |
61 |
* (cond_imp): New structure. |
* Big mistake here! CTHREAD_DATA must always be set TRUE. |
62 |
* (cond_signal): Return int now. |
* cthreads.h is included by import_mach.h by lots of files |
63 |
* (condition_broadcast): Always call cond_broadcast if this condition |
* that are not compiled with -DCTHREAD_DATA. This means |
64 |
* has implications. |
* they see a different structure for cthread_t than the |
65 |
* (condition_signal): Always call cond_signal if this condition has |
* cthread library -- which is compiled with CTHREAD_DATA. |
66 |
* implications. |
* Also, make cthread_set_data and cthread_data macros. |
67 |
* |
* [93/05/06 rvb] |
68 |
* Revision 1.8 1995/08/30 15:10:23 mib |
* Flush stdlib |
69 |
* (hurd_condition_wait): Provide declaration. |
* [93/05/05 rvb] |
70 |
* |
* |
71 |
* Revision 1.7 1995/07/18 17:15:51 mib |
* Revision 2.15 93/01/27 09:03:32 danner |
72 |
* Reverse previous change. |
* Updated include of mach/mach.h to mach.h |
73 |
* |
* |
74 |
* Revision 1.5 1995/04/04 21:06:16 roland |
* |
75 |
* (mutex_lock, mutex_unlock): Use __ names for *_solid. |
* Revision 2.14 93/01/24 13:24:50 danner |
76 |
* |
* Get MACRO_BEGIN, MACRO_END, NEVER, ... from sys/macro_help.h |
77 |
* Revision 1.4 1994/05/05 10:52:06 roland |
* why define it here. |
78 |
* entered into RCS |
* [92/10/20 rvb] |
79 |
|
* |
80 |
|
* Revision 2.13 93/01/14 18:05:04 danner |
81 |
|
* Added MACRO_BEGIN and MACRO_END to definition of spin_lock. |
82 |
|
* Fixed return value of cthread_set_data. |
83 |
|
* Added prototypes for other miscellaneous functions. |
84 |
|
* [92/12/18 pds] |
85 |
|
* Converted file to ANSI C. |
86 |
|
* Added declarations of cthread_fork_{prepare,parent,child}. |
87 |
|
* Added include of <sys/macro_help.h>. |
88 |
|
* [92/12/13 pds] |
89 |
|
* |
90 |
|
* Replaced calloc declaration with an include of stdlib.h. |
91 |
|
* [92/06/15 pds] |
92 |
|
* 64bit cleanup. |
93 |
|
* [92/12/02 af] |
94 |
* |
* |
95 |
* Revision 2.12 92/05/22 18:38:36 jfriedl |
* Revision 2.12 92/05/22 18:38:36 jfriedl |
96 |
* From Mike Kupfer <kupfer@sprite.Berkeley.EDU>: |
* From Mike Kupfer <kupfer@sprite.Berkeley.EDU>: |
230 |
#ifndef _CTHREADS_ |
#ifndef _CTHREADS_ |
231 |
#define _CTHREADS_ 1 |
#define _CTHREADS_ 1 |
232 |
|
|
233 |
/* MIB XXX */ |
#define WAIT_DEBUG /* XXX should be defined somewhere else */ |
|
#define CTHREAD_DATA |
|
234 |
|
|
235 |
#if 0 |
#if 0 |
236 |
/* This is CMU's machine-dependent file. In GNU all of the machine |
/* This is CMU's machine-dependent file. In GNU all of the machine |
237 |
dependencies are dealt with in libc. */ |
dependencies are dealt with in libc. */ |
238 |
#include <machine/cthreads.h> |
#include <machine/cthreads.h> |
239 |
|
#include <mach.h> |
240 |
|
#include <sys/macro_help.h> |
241 |
|
#include <mach/machine/vm_param.h> |
242 |
|
|
243 |
|
#ifdef __STDC__ |
244 |
|
extern void *malloc(); |
245 |
#else |
#else |
246 |
#include <machine-sp.h> |
extern char *malloc(); |
|
#define cthread_sp() ((vm_address_t) __thread_stack_pointer ()) |
|
247 |
#endif |
#endif |
248 |
|
|
249 |
#if c_plusplus || __STDC__ |
#else /* GNU */ |
250 |
|
# include <stdlib.h> |
251 |
#ifndef C_ARG_DECLS |
# include <mach.h> |
252 |
#define C_ARG_DECLS(arglist) arglist |
# include <mach/machine/vm_param.h> |
253 |
#endif /* not C_ARG_DECLS */ |
# include <machine-sp.h> |
254 |
|
# define cthread_sp() ((vm_address_t) __thread_stack_pointer ()) |
255 |
typedef void *any_t; |
# define MACRO_BEGIN __extension__ ({ |
256 |
|
# define MACRO_END 0; }) |
257 |
#else /* not (c_plusplus || __STDC__) */ |
#endif |
|
|
|
|
#ifndef C_ARG_DECLS |
|
|
#define C_ARG_DECLS(arglist) () |
|
|
#endif /* not C_ARG_DECLS */ |
|
|
|
|
|
typedef char *any_t; |
|
|
|
|
|
#endif /* not (c_plusplus || __STDC__) */ |
|
258 |
|
|
259 |
#include <mach/mach.h> |
typedef void *any_t; /* XXX - obsolete, should be deleted. */ |
|
#include <mach/machine/vm_param.h> |
|
260 |
|
|
261 |
#ifndef TRUE |
#if defined(TRUE) |
262 |
|
#else /* not defined(TRUE) */ |
263 |
#define TRUE 1 |
#define TRUE 1 |
264 |
#define FALSE 0 |
#define FALSE 0 |
265 |
#endif /* TRUE */ |
#endif |
|
|
|
|
|
|
|
#undef MACRO_BEGIN |
|
|
#undef MACRO_END |
|
|
#define MACRO_BEGIN __extension__ ({ |
|
|
#define MACRO_END 0; }) |
|
|
|
|
266 |
|
|
267 |
/* |
/* |
268 |
* C Threads package initialization. |
* C Threads package initialization. |
269 |
*/ |
*/ |
270 |
|
|
271 |
extern int cthread_init C_ARG_DECLS((void)); |
extern vm_offset_t cthread_init(void); |
272 |
#if 0 |
|
|
/* This prototype is broken for GNU. */ |
|
|
extern any_t calloc C_ARG_DECLS((unsigned n, unsigned size)); |
|
|
#else |
|
|
#include <stdlib.h> |
|
|
#endif |
|
273 |
|
|
274 |
/* |
/* |
275 |
* Queues. |
* Queues. |
289 |
|
|
290 |
#define cthread_queue_alloc() ((cthread_queue_t) calloc(1, sizeof(struct cthread_queue))) |
#define cthread_queue_alloc() ((cthread_queue_t) calloc(1, sizeof(struct cthread_queue))) |
291 |
#define cthread_queue_init(q) ((q)->head = (q)->tail = 0) |
#define cthread_queue_init(q) ((q)->head = (q)->tail = 0) |
292 |
#define cthread_queue_free(q) free((any_t) (q)) |
#define cthread_queue_free(q) free((q)) |
293 |
|
|
294 |
#define cthread_queue_enq(q, x) \ |
#define cthread_queue_enq(q, x) \ |
295 |
MACRO_BEGIN \ |
MACRO_BEGIN \ |
321 |
#define cthread_queue_map(q, t, f) \ |
#define cthread_queue_map(q, t, f) \ |
322 |
MACRO_BEGIN \ |
MACRO_BEGIN \ |
323 |
register cthread_queue_item_t x, next; \ |
register cthread_queue_item_t x, next; \ |
324 |
for (x = (cthread_queue_item_t) ((q)->head); x != 0; x = next) { \ |
for (x = (cthread_queue_item_t) ((q)->head); x != 0; x = next){\ |
325 |
next = x->next; \ |
next = x->next; \ |
326 |
(*(f))((t) x); \ |
(*(f))((t) x); \ |
327 |
} \ |
} \ |
338 |
/* |
/* |
339 |
* Spin locks. |
* Spin locks. |
340 |
*/ |
*/ |
341 |
extern void |
extern void spin_lock_solid(spin_lock_t *_lock); |
|
spin_lock_solid C_ARG_DECLS((spin_lock_t *p)); |
|
342 |
|
|
343 |
#ifndef spin_unlock |
#if defined(spin_unlock) |
344 |
extern void |
#else /* not defined(spin_unlock) */ |
345 |
spin_unlock C_ARG_DECLS((spin_lock_t *p)); |
extern void spin_unlock(spin_lock_t *_lock); |
346 |
#endif |
#endif |
347 |
|
|
348 |
#ifndef spin_try_lock |
#if defined(spin_try_lock) |
349 |
extern int |
#else /* not defined(spin_try_lock) */ |
350 |
spin_try_lock C_ARG_DECLS((spin_lock_t *p)); |
extern boolean_t spin_try_lock(spin_lock_t *_lock); |
351 |
#endif |
#endif |
352 |
|
|
353 |
#define spin_lock(p) ({if (!spin_try_lock(p)) spin_lock_solid(p);}) |
#define spin_lock(p) \ |
354 |
|
MACRO_BEGIN \ |
355 |
|
if (!spin_try_lock(p)) { \ |
356 |
|
spin_lock_solid(p); \ |
357 |
|
} \ |
358 |
|
MACRO_END |
359 |
|
|
360 |
#endif /* End unused CMU code. */ |
#endif /* End unused CMU code. */ |
361 |
|
|
369 |
see if it gets the mutex. */ |
see if it gets the mutex. */ |
370 |
spin_lock_t held; |
spin_lock_t held; |
371 |
spin_lock_t lock; |
spin_lock_t lock; |
372 |
char *name; |
const char *name; |
373 |
struct cthread_queue queue; |
struct cthread_queue queue; |
374 |
|
/* holder is for WAIT_DEBUG. Not ifdeffed to keep size constant. */ |
375 |
|
struct cthread *holder; |
376 |
} *mutex_t; |
} *mutex_t; |
377 |
|
|
378 |
/* Rearranged accordingly for GNU: */ |
/* Rearranged accordingly for GNU: */ |
379 |
#define MUTEX_INITIALIZER { SPIN_LOCK_INITIALIZER, SPIN_LOCK_INITIALIZER, 0, QUEUE_INITIALIZER } |
#define MUTEX_INITIALIZER { SPIN_LOCK_INITIALIZER, SPIN_LOCK_INITIALIZER, 0, QUEUE_INITIALIZER, } |
380 |
|
#define MUTEX_NAMED_INITIALIZER(Name) { SPIN_LOCK_INITIALIZER, SPIN_LOCK_INITIALIZER, Name, QUEUE_INITIALIZER, } |
381 |
|
|
382 |
#define mutex_alloc() ((mutex_t) calloc(1, sizeof(struct mutex))) |
#define mutex_alloc() ((mutex_t) calloc(1, sizeof(struct mutex))) |
383 |
#define mutex_init(m) \ |
#define mutex_init(m) \ |
385 |
spin_lock_init(&(m)->lock); \ |
spin_lock_init(&(m)->lock); \ |
386 |
cthread_queue_init(&(m)->queue); \ |
cthread_queue_init(&(m)->queue); \ |
387 |
spin_lock_init(&(m)->held); \ |
spin_lock_init(&(m)->held); \ |
388 |
|
(m)->holder = 0; \ |
389 |
MACRO_END |
MACRO_END |
390 |
#define mutex_set_name(m, x) ((m)->name = (x)) |
#define mutex_set_name(m, x) ((m)->name = (x)) |
391 |
#define mutex_name(m) ((m)->name != 0 ? (m)->name : "?") |
#define mutex_name(m) ((m)->name != 0 ? (m)->name : "?") |
392 |
#define mutex_clear(m) mutex_init(m) |
#define mutex_clear(m) /* nop */??? |
393 |
#define mutex_free(m) free((any_t) (m)) |
#define mutex_free(m) free((m)) |
|
|
|
|
extern void __mutex_lock_solid (void *mutex); /* blocking -- roland@gnu */ |
|
|
extern void __mutex_unlock_solid (void *mutex); /* roland@gnu */ |
|
394 |
|
|
395 |
#define mutex_try_lock(m) spin_try_lock(&(m)->held) |
#define mutex_try_lock(m) spin_try_lock(&(m)->held) |
396 |
|
#if defined(WAIT_DEBUG) |
397 |
#define mutex_lock(m) \ |
#define mutex_lock(m) \ |
398 |
MACRO_BEGIN \ |
MACRO_BEGIN \ |
399 |
if (!spin_try_lock(&(m)->held)) { \ |
if (!spin_try_lock(&(m)->held)) { \ |
400 |
__mutex_lock_solid(m); \ |
__mutex_lock_solid(m); \ |
401 |
} \ |
} \ |
402 |
|
(m)->holder = cthread_self(); \ |
403 |
MACRO_END |
MACRO_END |
404 |
#define mutex_unlock(m) \ |
#define mutex_unlock(m) \ |
405 |
MACRO_BEGIN \ |
MACRO_BEGIN \ |
406 |
if (spin_unlock(&(m)->held), \ |
if (spin_unlock(&(m)->held), \ |
407 |
cthread_queue_head(&(m)->queue, void *) != 0) { \ |
cthread_queue_head(&(m)->queue, vm_offset_t) != 0) { \ |
408 |
__mutex_unlock_solid(m); \ |
__mutex_unlock_solid(m); \ |
409 |
} \ |
} \ |
410 |
|
(m)->holder = 0; \ |
411 |
MACRO_END |
MACRO_END |
412 |
|
#else /* defined(WAIT_DEBUG */ |
413 |
|
#define mutex_lock(m) \ |
414 |
|
MACRO_BEGIN \ |
415 |
|
if (!spin_try_lock(&(m)->held)) { \ |
416 |
|
__mutex_lock_solid(m); \ |
417 |
|
} \ |
418 |
|
MACRO_END |
419 |
|
#define mutex_unlock(m) \ |
420 |
|
MACRO_BEGIN \ |
421 |
|
if (spin_unlock(&(m)->held), \ |
422 |
|
cthread_queue_head(&(m)->queue, vm_offset_t) != 0) { \ |
423 |
|
__mutex_unlock_solid(m); \ |
424 |
|
} \ |
425 |
|
MACRO_END |
426 |
|
#endif /* defined(WAIT_DEBUG) */ |
427 |
/* |
/* |
428 |
* Condition variables. |
* Condition variables. |
429 |
*/ |
*/ |
430 |
typedef struct condition { |
typedef struct condition { |
431 |
spin_lock_t lock; |
spin_lock_t lock; |
432 |
struct cthread_queue queue; |
struct cthread_queue queue; |
433 |
char *name; |
const char *name; |
434 |
struct cond_imp *implications; |
struct cond_imp *implications; |
435 |
} *condition_t; |
} *condition_t; |
436 |
|
|
441 |
}; |
}; |
442 |
|
|
443 |
#define CONDITION_INITIALIZER { SPIN_LOCK_INITIALIZER, QUEUE_INITIALIZER, 0, 0 } |
#define CONDITION_INITIALIZER { SPIN_LOCK_INITIALIZER, QUEUE_INITIALIZER, 0, 0 } |
444 |
|
#define CONDITION_NAMED_INITIALIZER(Name) { SPIN_LOCK_INITIALIZER, QUEUE_INITIALIZER, Name, 0 } |
445 |
|
|
446 |
#define condition_alloc() ((condition_t) calloc(1, sizeof(struct condition))) |
#define condition_alloc() \ |
447 |
|
((condition_t) calloc(1, sizeof(struct condition))) |
448 |
#define condition_init(c) \ |
#define condition_init(c) \ |
449 |
MACRO_BEGIN \ |
MACRO_BEGIN \ |
450 |
spin_lock_init(&(c)->lock); \ |
spin_lock_init(&(c)->lock); \ |
462 |
#define condition_free(c) \ |
#define condition_free(c) \ |
463 |
MACRO_BEGIN \ |
MACRO_BEGIN \ |
464 |
condition_clear(c); \ |
condition_clear(c); \ |
465 |
free((any_t) (c)); \ |
free((c)); \ |
466 |
MACRO_END |
MACRO_END |
467 |
|
|
468 |
#define condition_signal(c) \ |
#define condition_signal(c) \ |
479 |
} \ |
} \ |
480 |
MACRO_END |
MACRO_END |
481 |
|
|
482 |
extern int |
extern int cond_signal(condition_t _cond); |
|
cond_signal C_ARG_DECLS((condition_t c)); |
|
|
|
|
|
extern void |
|
|
cond_broadcast C_ARG_DECLS((condition_t c)); |
|
|
|
|
|
extern void |
|
|
condition_wait C_ARG_DECLS((condition_t c, mutex_t m)); |
|
483 |
|
|
484 |
extern int |
extern void cond_broadcast(condition_t _cond); |
|
hurd_condition_wait C_ARG_DECLS((condition_t c, mutex_t m)); |
|
485 |
|
|
486 |
extern void |
extern void condition_wait(condition_t _cond, mutex_t _mutex); |
|
condition_implies C_ARG_DECLS((condition_t implicator, condition_t implicatand)); |
|
|
|
|
|
extern void |
|
|
condition_unimplies C_ARG_DECLS((condition_t implicator, condition_t implicatand)); |
|
487 |
|
|
488 |
/* |
/* |
489 |
* Threads. |
* Threads. |
490 |
*/ |
*/ |
491 |
|
|
492 |
typedef any_t (*cthread_fn_t) C_ARG_DECLS((any_t arg)); |
typedef void * (*cthread_fn_t)(void *arg); |
493 |
|
|
494 |
#include <setjmp.h> |
#include <setjmp.h> |
495 |
|
|
498 |
struct mutex lock; |
struct mutex lock; |
499 |
struct condition done; |
struct condition done; |
500 |
int state; |
int state; |
501 |
jmp_buf catch; |
jmp_buf catch_exit; |
502 |
cthread_fn_t func; |
cthread_fn_t func; |
503 |
any_t arg; |
void *arg; |
504 |
any_t result; |
void *result; |
505 |
char *name; |
const char *name; |
506 |
#ifdef CTHREAD_DATA |
void *data; |
507 |
any_t data; |
void *ldata; |
508 |
#endif /* CTHREAD_DATA */ |
void *private_data; |
|
any_t private_data; |
|
509 |
struct ur_cthread *ur; |
struct ur_cthread *ur; |
510 |
} *cthread_t; |
} *cthread_t; |
511 |
|
|
512 |
#define NO_CTHREAD ((cthread_t) 0) |
#define NO_CTHREAD ((cthread_t) 0) |
513 |
|
|
514 |
extern cthread_t |
extern cthread_t cthread_fork(cthread_fn_t _func, void *_arg); |
|
cthread_fork C_ARG_DECLS((cthread_fn_t func, any_t arg)); |
|
515 |
|
|
516 |
extern void |
extern void cthread_detach(cthread_t _thread); |
|
cthread_detach C_ARG_DECLS((cthread_t t)); |
|
517 |
|
|
518 |
extern any_t |
extern any_t cthread_join(cthread_t _thread); |
|
cthread_join C_ARG_DECLS((cthread_t t)); |
|
519 |
|
|
520 |
extern void |
extern void cthread_yield(void); |
|
cthread_yield C_ARG_DECLS((void)); |
|
521 |
|
|
522 |
extern void |
extern void cthread_exit(void *_result); |
|
cthread_exit C_ARG_DECLS((any_t result)); |
|
523 |
|
|
524 |
/* |
/* |
525 |
* This structure must agree with struct cproc in cthread_internals.h |
* This structure must agree with struct cproc in cthread_internals.h |
530 |
} *ur_cthread_t; |
} *ur_cthread_t; |
531 |
|
|
532 |
#ifndef cthread_sp |
#ifndef cthread_sp |
533 |
extern int |
extern vm_offset_t |
534 |
cthread_sp C_ARG_DECLS((void)); |
cthread_sp(void); |
535 |
#endif |
#endif |
536 |
|
|
537 |
extern int cthread_stack_mask; |
extern vm_offset_t cthread_stack_mask; |
538 |
|
|
539 |
#ifdef STACK_GROWTH_UP |
#if defined(STACK_GROWTH_UP) |
540 |
#define ur_cthread_ptr(sp) \ |
#define ur_cthread_ptr(sp) \ |
541 |
(* (ur_cthread_t *) ((sp) & cthread_stack_mask)) |
(* (ur_cthread_t *) ((sp) & cthread_stack_mask)) |
542 |
#else /* STACK_GROWTH_UP */ |
#else /* not defined(STACK_GROWTH_UP) */ |
543 |
#define ur_cthread_ptr(sp) \ |
#define ur_cthread_ptr(sp) \ |
544 |
(* (ur_cthread_t *) ( ((sp) | cthread_stack_mask) + 1 \ |
(* (ur_cthread_t *) ( ((sp) | cthread_stack_mask) + 1 \ |
545 |
- sizeof(ur_cthread_t *)) ) |
- sizeof(ur_cthread_t *)) ) |
546 |
#endif /* STACK_GROWTH_UP */ |
#endif /* defined(STACK_GROWTH_UP) */ |
547 |
|
|
548 |
#define ur_cthread_self() (ur_cthread_ptr(cthread_sp())) |
#define ur_cthread_self() (ur_cthread_ptr(cthread_sp())) |
549 |
|
|
551 |
((t) ? ((t)->ur = (ur_cthread_t)(id)) : 0)) |
((t) ? ((t)->ur = (ur_cthread_t)(id)) : 0)) |
552 |
#define cthread_self() (ur_cthread_self()->incarnation) |
#define cthread_self() (ur_cthread_self()->incarnation) |
553 |
|
|
554 |
extern void |
extern void cthread_set_name(cthread_t _thread, const char *_name); |
555 |
cthread_set_name C_ARG_DECLS((cthread_t t, char *name)); |
|
556 |
|
extern const char * cthread_name(cthread_t _thread); |
557 |
|
|
558 |
|
extern int cthread_count(void); |
559 |
|
|
560 |
|
extern void cthread_set_limit(int _limit); |
561 |
|
|
562 |
extern char * |
extern int cthread_limit(void); |
|
cthread_name C_ARG_DECLS((cthread_t t)); |
|
563 |
|
|
564 |
extern int |
extern void cthread_set_kernel_limit(int _n); |
|
cthread_count C_ARG_DECLS((void)); |
|
565 |
|
|
566 |
extern void |
extern int cthread_kernel_limit(void); |
|
cthread_set_limit C_ARG_DECLS((int n)); |
|
567 |
|
|
568 |
extern int |
extern void cthread_wire(void); |
|
cthread_limit C_ARG_DECLS((void)); |
|
569 |
|
|
570 |
extern void |
extern void cthread_unwire(void); |
|
cthread_wire C_ARG_DECLS((void)); |
|
571 |
|
|
572 |
#ifdef CTHREAD_DATA |
extern void cthread_msg_busy(mach_port_t _port, int _min, int _max); |
573 |
|
|
574 |
|
extern void cthread_msg_active(mach_port_t _prt, int _min, int _max); |
575 |
|
|
576 |
|
extern mach_msg_return_t cthread_mach_msg(mach_msg_header_t *_header, |
577 |
|
mach_msg_option_t _option, |
578 |
|
mach_msg_size_t _send_size, |
579 |
|
mach_msg_size_t _rcv_size, |
580 |
|
mach_port_t _rcv_name, |
581 |
|
mach_msg_timeout_t _timeout, |
582 |
|
mach_port_t _notify, |
583 |
|
int _min, int _max); |
584 |
|
|
585 |
|
extern void cthread_fork_prepare(void); |
586 |
|
|
587 |
|
extern void cthread_fork_parent(void); |
588 |
|
|
589 |
|
extern void cthread_fork_child(void); |
590 |
|
|
591 |
|
#if defined(THREAD_CALLS) |
592 |
|
/* |
593 |
|
* Routines to replace thread_*. |
594 |
|
*/ |
595 |
|
extern kern_return_t cthread_get_state(cthread_t _thread); |
596 |
|
|
597 |
|
extern kern_return_t cthread_set_state(cthread_t _thread); |
598 |
|
|
599 |
|
extern kern_return_t cthread_abort(cthread_t _thread); |
600 |
|
|
601 |
|
extern kern_return_t cthread_resume(cthread_t _thread); |
602 |
|
|
603 |
|
extern kern_return_t cthread_suspend(cthread_t _thread); |
604 |
|
|
605 |
|
extern kern_return_t cthread_call_on(cthread_t _thread); |
606 |
|
#endif /* defined(THREAD_CALLS) */ |
607 |
|
|
608 |
|
#if defined(CTHREAD_DATA_XX) |
609 |
/* |
/* |
610 |
* Set or get thread specific "global" variable |
* Set or get thread specific "global" variable |
611 |
* |
* |
612 |
* The thread given must be the calling thread (ie. thread_self). |
* The thread given must be the calling thread (ie. thread_self). |
613 |
* XXX This is for compatibility with the old cthread_data. XXX |
* XXX This is for compatibility with the old cthread_data. XXX |
614 |
*/ |
*/ |
615 |
extern int |
extern int cthread_set_data(cthread_t _thread, void *_val); |
616 |
cthread_set_data C_ARG_DECLS((cthread_t t, any_t x)); |
|
617 |
|
extern void * cthread_data(cthread_t _thread); |
618 |
|
#else /* defined(CTHREAD_DATA_XX) */ |
619 |
|
|
620 |
|
#define cthread_set_data(_thread, _val) ((_thread)->data) = (void *)(_val); |
621 |
|
#define cthread_data(_thread) ((_thread)->data) |
622 |
|
|
623 |
|
#define cthread_set_ldata(_thread, _val) ((_thread)->ldata) = (void *)(_val); |
624 |
|
#define cthread_ldata(_thread) ((_thread)->ldata) |
625 |
|
|
626 |
|
#endif /* defined(CTHREAD_DATA_XX) */ |
627 |
|
|
|
extern any_t |
|
|
cthread_data C_ARG_DECLS((cthread_t t)); |
|
|
#endif /* CTHREAD_DATA */ |
|
628 |
|
|
629 |
/* |
/* |
630 |
* Support for POSIX thread specific data |
* Support for POSIX thread specific data |
632 |
* Multiplexes a thread specific "global" variable |
* Multiplexes a thread specific "global" variable |
633 |
* into many thread specific "global" variables. |
* into many thread specific "global" variables. |
634 |
*/ |
*/ |
635 |
#define CTHREAD_DATA_VALUE_NULL (any_t)0 |
#define CTHREAD_DATA_VALUE_NULL (void *)0 |
636 |
#define CTHREAD_KEY_INVALID (cthread_key_t)-1 |
#define CTHREAD_KEY_INVALID (cthread_key_t)-1 |
637 |
|
|
638 |
typedef int cthread_key_t; |
typedef int cthread_key_t; |
642 |
* Different threads may use same key, but the values bound to the key are |
* Different threads may use same key, but the values bound to the key are |
643 |
* maintained on a thread specific basis. |
* maintained on a thread specific basis. |
644 |
*/ |
*/ |
645 |
extern int |
extern int cthread_keycreate(cthread_key_t *_key); |
|
cthread_keycreate C_ARG_DECLS((cthread_key_t *key)); |
|
646 |
|
|
647 |
/* |
/* |
648 |
* Get value currently bound to key for calling thread |
* Get value currently bound to key for calling thread |
649 |
*/ |
*/ |
650 |
extern int |
extern int cthread_getspecific(cthread_key_t _key, void **_value); |
|
cthread_getspecific C_ARG_DECLS((cthread_key_t key, any_t *value)); |
|
651 |
|
|
652 |
/* |
/* |
653 |
* Bind value to given key for calling thread |
* Bind value to given key for calling thread |
654 |
*/ |
*/ |
655 |
extern int |
extern int cthread_setspecific(cthread_key_t _key, void *_value); |
|
cthread_setspecific C_ARG_DECLS((cthread_key_t key, any_t value)); |
|
656 |
|
|
657 |
/* |
/* |
658 |
* Debugging support. |
* Debugging support. |
659 |
*/ |
*/ |
660 |
#ifdef DEBUG |
#if defined(DEBUG) |
661 |
|
|
662 |
#ifndef ASSERT |
#if defined(ASSERT) |
663 |
|
#else /* not defined(ASSERT) */ |
664 |
/* |
/* |
665 |
* Assertion macro, similar to <assert.h> |
* Assertion macro, similar to <assert.h> |
666 |
*/ |
*/ |
675 |
} \ |
} \ |
676 |
MACRO_END |
MACRO_END |
677 |
|
|
678 |
#endif /* ASSERT */ |
#endif /* defined(ASSERT) */ |
679 |
|
|
680 |
#define SHOULDNT_HAPPEN 0 |
#define SHOULDNT_HAPPEN 0 |
681 |
|
|
682 |
extern int cthread_debug; |
extern int cthread_debug; |
683 |
|
|
684 |
#else /* DEBUG */ |
#else /* not defined(DEBUG) */ |
685 |
|
|
686 |
#ifndef ASSERT |
#if defined(ASSERT) |
687 |
|
#else /* not defined(ASSERT) */ |
688 |
#define ASSERT(p) |
#define ASSERT(p) |
689 |
#endif /* ASSERT */ |
#endif /* defined(ASSERT) */ |
690 |
|
|
691 |
#endif /* DEBUG */ |
#endif /* defined(DEBUG) */ |
692 |
|
|
693 |
#endif /* _CTHREADS_ */ |
#endif /* not defined(_CTHREADS_) */ |