1 |
/* |
/* |
2 |
* Mach Operating System |
* Mach Operating System |
3 |
* Copyright (c) 1991,1990,1989 Carnegie Mellon University |
* Copyright (c) 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.11 2002/05/08 09:37:07 roland |
* Renamed cthread_t->catch to to cthread_t->catch_exit, because |
30 |
* 2002-05-08 Roland McGrath <roland@frob.com> |
* catch is reserved word in c++. |
|
* |
|
|
* * cthreads.c (cthread_exit): Cast any_t to long before int. |
|
31 |
* |
* |
32 |
* Revision 1.10 2001/03/31 23:01:01 roland |
* $Log$ |
33 |
* 2001-03-31 Roland McGrath <roland@frob.com> |
* Revision 1.12 2002/05/27 02:50:10 roland |
34 |
|
* 2002-05-26 Roland McGrath <roland@frob.com> |
35 |
* |
* |
36 |
* * cthreads.h: Fix obsolescent #endif syntax. |
* Changes merged from CMU MK83a version: |
37 |
* * cthread_internals.h: Likewise. |
* * cthreads.h, options.h: Various cleanups. |
38 |
* * cancel-cond.c: Likewise. |
* * call.c, cthread_data.c, sync.c, mig_support.c: Likewise. |
39 |
* * stack.c: Likewise. |
* * i386/cthreads.h, i386/thread.c, i386/lock.s: Likewise. |
40 |
|
* * cthread_internals.h: Add decls for internal functions. |
41 |
|
* (struct cproc): Use vm_offset_t for stack_base and stack_size members. |
42 |
|
* Use natural_t for context member. |
43 |
|
* * cprocs.c: Use prototypes for all defns. |
44 |
* * cthreads.c: Likewise. |
* * cthreads.c: Likewise. |
45 |
* * cprocs.c: Likewise. |
* (cthread_exit): Cast any_t to integer_t before int. |
|
* * call.c: Likewise. |
|
|
* |
|
|
* Revision 1.9 1998/11/22 18:18:10 roland |
|
|
* 1998-11-12 Mark Kettenis <kettenis@phys.uva.nl> |
|
|
* |
|
|
* * cthreads.c (cthread_init): Move cthread_alloc call before |
|
|
* cproc_init call, since cthread_alloc uses malloc, and malloc won't |
|
|
* work between initializing the new stack and switching over to it. |
|
|
* |
|
|
* Revision 1.8 1998/06/10 19:38:01 tb |
|
|
* Tue Jun 9 13:50:09 1998 Thomas Bushnell, n/BSG <tb@mit.edu> |
|
|
* |
|
|
* * cthreads.c (cthread_fork_prepare): Don't call |
|
|
* malloc_fork_prepare since we are no longer providing our own |
|
|
* malloc in this library. |
|
|
* (cthread_fork_parent): Likewise, for malloc_fork_parent. |
|
|
* (cthread_fork_child): Likewize, for malloc_fork_child. |
|
|
* |
|
|
* Revision 1.7 1997/08/20 19:41:20 thomas |
|
|
* Wed Aug 20 15:39:44 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> |
|
46 |
* |
* |
47 |
* * cthreads.c (cthread_body): Wire self before calling user work |
* Revision 2.13 93/01/21 12:27:55 danner |
48 |
* function. This way all cthreads will be wired, which the ports |
* Remove deadlock in cproc_fork_child; must release malloc lock first. |
49 |
* library (and hurd_thread_cancel, etc.) depend on. |
* [93/01/19 16:37:43 bershad] |
50 |
|
* |
51 |
|
* Revision 2.12 93/01/14 18:05:00 danner |
52 |
|
* Converted file to ANSI C. |
53 |
|
* Removed use of obsolete type any_t. |
54 |
|
* [92/12/18 pds] |
55 |
|
* 64bit cleanup. |
56 |
|
* [92/12/01 af] |
57 |
* |
* |
58 |
* Revision 1.6 1997/06/10 01:22:19 thomas |
* Free private_data in cthread_exit, from Mike Kupfer. |
59 |
* Mon Jun 9 21:18:46 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> |
* [92/11/30 af] |
|
* |
|
|
* * cthreads.c (cthread_fork): Delete debugging oddity that crept |
|
|
* into source. |
|
|
* |
|
|
* Revision 1.5 1997/04/04 01:30:35 thomas |
|
|
* *** empty log message *** |
|
|
* |
|
|
* Revision 1.4 1994/05/05 18:13:57 roland |
|
|
* entered into RCS |
|
60 |
* |
* |
61 |
* Revision 2.11 92/07/20 13:33:37 cmaeda |
* Revision 2.11 92/07/20 13:33:37 cmaeda |
62 |
* In cthread_init, do machine dependent initialization if it's defined. |
* In cthread_init, do machine dependent initialization if it's defined. |
133 |
*/ |
*/ |
134 |
|
|
135 |
#include <cthreads.h> |
#include <cthreads.h> |
136 |
|
#include <mach/mig_support.h> |
137 |
#include "cthread_internals.h" |
#include "cthread_internals.h" |
138 |
|
|
139 |
/* |
/* |
|
* C Threads imports: |
|
|
*/ |
|
|
extern void cproc_create(); |
|
|
extern vm_offset_t cproc_init(); |
|
|
extern void mig_init(); |
|
|
|
|
|
/* |
|
|
* Mach imports: |
|
|
*/ |
|
|
|
|
|
/* |
|
|
* C library imports: |
|
|
*/ |
|
|
|
|
|
/* |
|
140 |
* Thread status bits. |
* Thread status bits. |
141 |
*/ |
*/ |
142 |
#define T_MAIN 0x1 |
#define T_MAIN 0x1 |
143 |
#define T_RETURNED 0x2 |
#define T_RETURNED 0x2 |
144 |
#define T_DETACHED 0x4 |
#define T_DETACHED 0x4 |
145 |
|
|
146 |
#ifdef DEBUG |
#if defined(DEBUG) |
147 |
int cthread_debug = FALSE; |
int cthread_debug = FALSE; |
148 |
#endif /* DEBUG */ |
#endif /* defined(DEBUG) */ |
149 |
|
|
150 |
private struct cthread_queue cthreads = QUEUE_INITIALIZER; |
private struct cthread_queue cthreads = QUEUE_INITIALIZER; |
151 |
private struct mutex cthread_lock = MUTEX_INITIALIZER; |
private struct mutex cthread_lock = MUTEX_INITIALIZER; |
161 |
private struct cthread initial_cthread = { 0 }; |
private struct cthread initial_cthread = { 0 }; |
162 |
|
|
163 |
private cthread_t |
private cthread_t |
164 |
cthread_alloc(func, arg) |
cthread_alloc(cthread_fn_t func, void *arg) |
|
cthread_fn_t func; |
|
|
any_t arg; |
|
165 |
{ |
{ |
166 |
register cthread_t t = NO_CTHREAD; |
register cthread_t t = NO_CTHREAD; |
167 |
|
|
193 |
} |
} |
194 |
|
|
195 |
private void |
private void |
196 |
cthread_free(t) |
cthread_free(cthread_t t) |
|
register cthread_t t; |
|
197 |
{ |
{ |
198 |
spin_lock(&free_lock); |
spin_lock(&free_lock); |
199 |
t->next = free_cthreads; |
t->next = free_cthreads; |
201 |
spin_unlock(&free_lock); |
spin_unlock(&free_lock); |
202 |
} |
} |
203 |
|
|
204 |
int |
vm_offset_t |
205 |
cthread_init() |
cthread_init(void) |
206 |
{ |
{ |
207 |
static int cthreads_started = FALSE; |
static int cthreads_started = FALSE; |
208 |
register cproc_t p; |
register cproc_t p; |
211 |
|
|
212 |
if (cthreads_started) |
if (cthreads_started) |
213 |
return 0; |
return 0; |
|
t = cthread_alloc((cthread_fn_t) 0, (any_t) 0); |
|
214 |
stack = cproc_init(); |
stack = cproc_init(); |
215 |
cthread_cprocs = 1; |
cthread_cprocs = 1; |
216 |
|
t = cthread_alloc((cthread_fn_t) 0, (void *) 0); |
217 |
|
|
218 |
#ifdef cthread_md_init |
#ifdef cthread_md_init |
219 |
cthread_md_init(); |
cthread_md_init(); |
239 |
|
|
240 |
/* |
/* |
241 |
* Used for automatic initialization by crt0. |
* Used for automatic initialization by crt0. |
|
* Cast needed since too many C compilers choke on the type void (*)(). |
|
242 |
*/ |
*/ |
243 |
int (*_cthread_init_routine)() = (int (*)()) cthread_init; |
vm_offset_t (*_cthread_init_routine)(void) = cthread_init; |
244 |
|
|
245 |
|
|
246 |
/* |
/* |
247 |
* Procedure invoked at the base of each cthread. |
* Procedure invoked at the base of each cthread. |
248 |
*/ |
*/ |
249 |
void |
void |
250 |
cthread_body(self) |
cthread_body(cproc_t self) |
|
cproc_t self; |
|
251 |
{ |
{ |
252 |
register cthread_t t; |
register cthread_t t; |
253 |
|
|
265 |
*/ |
*/ |
266 |
mutex_unlock(&cthread_lock); |
mutex_unlock(&cthread_lock); |
267 |
cthread_assoc(self, t); /* assume thread's identity */ |
cthread_assoc(self, t); /* assume thread's identity */ |
268 |
if (_setjmp(t->catch) == 0) { /* catch for cthread_exit() */ |
if (_setjmp(t->catch_exit) == 0) { /* catch for cthread_exit() */ |
|
cthread_wire (); |
|
269 |
/* |
/* |
270 |
* Execute the fork request. |
* Execute the fork request. |
271 |
*/ |
*/ |
300 |
} |
} |
301 |
|
|
302 |
cthread_t |
cthread_t |
303 |
cthread_fork(func, arg) |
cthread_fork(cthread_fn_t func, void *arg) |
|
cthread_fn_t func; |
|
|
any_t arg; |
|
304 |
{ |
{ |
305 |
register cthread_t t; |
register cthread_t t; |
306 |
|
|
332 |
} |
} |
333 |
} |
} |
334 |
|
|
335 |
any_t |
void * |
336 |
cthread_join(t) |
cthread_join(cthread_t t) |
|
cthread_t t; |
|
337 |
{ |
{ |
338 |
any_t result; |
void *result; |
339 |
|
|
340 |
TRACE(printf("[%s] join(%s)\n", cthread_name(cthread_self()), cthread_name(t))); |
TRACE(printf("[%s] join(%s)\n", cthread_name(cthread_self()), cthread_name(t))); |
341 |
mutex_lock(&t->lock); |
mutex_lock(&t->lock); |
349 |
} |
} |
350 |
|
|
351 |
void |
void |
352 |
cthread_exit(result) |
cthread_exit(void *result) |
|
any_t result; |
|
353 |
{ |
{ |
354 |
register cthread_t t = cthread_self(); |
register cthread_t t = cthread_self(); |
355 |
|
|
356 |
TRACE(printf("[%s] exit()\n", cthread_name(t))); |
TRACE(printf("[%s] exit()\n", cthread_name(t))); |
357 |
t->result = result; |
t->result = result; |
358 |
|
if (t->private_data != 0) { |
359 |
|
free((char *)t->private_data); |
360 |
|
t->private_data = 0; |
361 |
|
} |
362 |
if (t->state & T_MAIN) { |
if (t->state & T_MAIN) { |
363 |
mutex_lock(&cthread_lock); |
mutex_lock(&cthread_lock); |
364 |
while (cthread_cthreads > 1) |
while (cthread_cthreads > 1) |
365 |
condition_wait(&cthread_idle, &cthread_lock); |
condition_wait(&cthread_idle, &cthread_lock); |
366 |
mutex_unlock(&cthread_lock); |
mutex_unlock(&cthread_lock); |
367 |
exit((int)(long)result); |
exit((int) (integer_t) result); |
368 |
} else { |
} else { |
369 |
_longjmp(t->catch, TRUE); |
_longjmp(t->catch_exit, TRUE); |
370 |
} |
} |
371 |
} |
} |
372 |
|
|
377 |
int (*_cthread_exit_routine)() = (int (*)()) cthread_exit; |
int (*_cthread_exit_routine)() = (int (*)()) cthread_exit; |
378 |
|
|
379 |
void |
void |
380 |
cthread_set_name(t, name) |
cthread_set_name(cthread_t t, const char *name) |
|
cthread_t t; |
|
|
char *name; |
|
381 |
{ |
{ |
382 |
t->name = name; |
t->name = name; |
383 |
} |
} |
384 |
|
|
385 |
char * |
const char * |
386 |
cthread_name(t) |
cthread_name(cthread_t t) |
|
cthread_t t; |
|
387 |
{ |
{ |
388 |
return (t == NO_CTHREAD |
return (t == NO_CTHREAD ? "idle" : (t->name == 0 ? "?" : t->name)); |
|
? "idle" |
|
|
: (t->name == 0 ? "?" : t->name)); |
|
389 |
} |
} |
390 |
|
|
391 |
int |
int |
392 |
cthread_limit() |
cthread_limit(void) |
393 |
{ |
{ |
394 |
return cthread_max_cprocs; |
return cthread_max_cprocs; |
395 |
} |
} |
396 |
|
|
397 |
void |
void |
398 |
cthread_set_limit(n) |
cthread_set_limit(int n) |
|
int n; |
|
399 |
{ |
{ |
400 |
cthread_max_cprocs = n; |
cthread_max_cprocs = n; |
401 |
} |
} |
402 |
|
|
403 |
int |
int |
404 |
cthread_count() |
cthread_count(void) |
405 |
{ |
{ |
406 |
return cthread_cthreads; |
return cthread_cthreads; |
407 |
} |
} |
408 |
|
|
409 |
cthread_fork_prepare() |
void |
410 |
|
cthread_fork_prepare(void) |
411 |
{ |
{ |
412 |
spin_lock(&free_lock); |
spin_lock(&free_lock); |
413 |
mutex_lock(&cthread_lock); |
mutex_lock(&cthread_lock); |
414 |
|
malloc_fork_prepare(); |
415 |
cproc_fork_prepare(); |
cproc_fork_prepare(); |
416 |
} |
} |
417 |
|
|
418 |
cthread_fork_parent() |
void |
419 |
|
cthread_fork_parent(void) |
420 |
{ |
{ |
421 |
cproc_fork_parent(); |
cproc_fork_parent(); |
422 |
|
malloc_fork_parent(); |
423 |
mutex_unlock(&cthread_lock); |
mutex_unlock(&cthread_lock); |
424 |
spin_unlock(&free_lock); |
spin_unlock(&free_lock); |
425 |
} |
} |
426 |
|
|
427 |
cthread_fork_child() |
void |
428 |
|
cthread_fork_child(void) |
429 |
{ |
{ |
430 |
cthread_t t; |
cthread_t t; |
431 |
cproc_t p; |
cproc_t p; |
432 |
|
|
433 |
|
malloc_fork_child(); |
434 |
cproc_fork_child(); |
cproc_fork_child(); |
435 |
mutex_unlock(&cthread_lock); |
mutex_unlock(&cthread_lock); |
436 |
spin_unlock(&free_lock); |
spin_unlock(&free_lock); |