diff options
author | Roland McGrath <roland@gnu.org> | 2002-05-27 02:50:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-05-27 02:50:10 +0000 |
commit | 2d3e2366b453da9b4288c30f3f894fccef1e7914 (patch) | |
tree | 2ada3140e12e0ba146954f447b0be0eb51f83fa0 | |
parent | 9403905d538fbb6fd33fa8439978a868aef56d9e (diff) |
2002-05-26 Roland McGrath <roland@frob.com>
Changes merged from CMU MK83a version:
* cthreads.h, options.h: Various cleanups.
* call.c, cthread_data.c, sync.c, mig_support.c: Likewise.
* i386/cthreads.h, i386/thread.c, i386/lock.s: Likewise.
* cthread_internals.h: Add decls for internal functions.
(struct cproc): Use vm_offset_t for stack_base and stack_size members.
Use natural_t for context member.
* cprocs.c: Use prototypes for all defns.
* cthreads.c: Likewise.
(cthread_exit): Cast any_t to integer_t before int.
-rw-r--r-- | libthreads/call.c | 51 | ||||
-rw-r--r-- | libthreads/cprocs.c | 170 | ||||
-rw-r--r-- | libthreads/cthread_data.c | 90 | ||||
-rw-r--r-- | libthreads/cthread_internals.h | 111 | ||||
-rw-r--r-- | libthreads/cthreads.c | 157 | ||||
-rw-r--r-- | libthreads/cthreads.h | 417 | ||||
-rw-r--r-- | libthreads/i386/cthreads.h | 21 | ||||
-rw-r--r-- | libthreads/i386/lock.s | 28 | ||||
-rw-r--r-- | libthreads/i386/thread.c | 63 | ||||
-rw-r--r-- | libthreads/mig_support.c | 106 | ||||
-rw-r--r-- | libthreads/sync.c | 9 |
11 files changed, 616 insertions, 607 deletions
diff --git a/libthreads/call.c b/libthreads/call.c index ec25345c..85bd4f38 100644 --- a/libthreads/call.c +++ b/libthreads/call.c @@ -1,84 +1,79 @@ -/* +/* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* * HISTORY - * $Log: call.c,v $ - * Revision 1.1 1992/10/06 18:31:03 mib - * entered into RCS - * + * $Log: call.c,v $ + * Revision 2.5 93/01/14 18:04:38 danner + * Converted file to ANSI C. + * [92/12/18 pds] + * * Revision 2.4 91/05/14 17:56:00 mrt * Correcting copyright - * + * * Revision 2.3 91/02/14 14:19:20 mrt * Added new Mach copyright * [91/02/13 12:40:44 mrt] - * + * * Revision 2.2 90/01/19 14:36:50 rwd * Created. Routines to replace thread_* and cthread_call_on. * [90/01/03 rwd] - * + * */ #include <cthreads.h> #include "cthread_internals.h" -#ifdef THREAD_CALLS -kern_return_t cthread_get_state(thread) -cthread_t thread; +#if defined(THREAD_CALLS) +kern_return_t cthread_get_state(cthread_t thread) { cproc_t p = thread->ur; } -kern_return_t cthread_set_state(thread) -cthread_t thread; +kern_return_t cthread_set_state(cthread_t thread) { cproc_t p = thread->ur; } -kern_return_t cthread_abort(thread) -cthread_t thread; +kern_return_t cthread_abort(cthread_t thread) { cproc_t p = thread->ur; } -kern_return_t cthread_resume(thread) -cthread_t thread; +kern_return_t cthread_resume(cthread_t thread) { cproc_t p = thread->ur; } -kern_return_t cthread_suspend(thread) -cthread_t thread; +kern_return_t cthread_suspend(cthread_t thread) { cproc_t p = thread->ur; } -kern_return_t cthread_call_on(thread) -cthread_t thread; +kern_return_t cthread_call_on(cthread_t thread) { cproc_t p = thread->ur; } -#endif /* THREAD_CALLS */ +#endif /* defined(THREAD_CALLS) */ diff --git a/libthreads/cprocs.c b/libthreads/cprocs.c index dd8ed95c..91e689f8 100644 --- a/libthreads/cprocs.c +++ b/libthreads/cprocs.c @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1993-1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -25,72 +25,24 @@ */ /* * HISTORY - * $Log: cprocs.c,v $ - * Revision 1.14 2002/05/08 09:32:11 roland - * 2002-05-07 Roland McGrath <roland@frob.com> + * 26-Oct-94 Johannes Helander (jvh) Helsinki University of Technology + * Set the wait_type field. * - * * cprocs.c (cproc_list_lock): Declare type as spin_lock_t. + * $Log: cprocs.c,v $ + * Revision 2.18 93/03/09 10:59:10 danner + * Lint. + * [93/03/06 af] * - * Revision 1.13 2001/03/31 23:01:01 roland - * 2001-03-31 Roland McGrath <roland@frob.com> + * Revision 2.17 93/01/19 08:55:44 danner + * Added missing spin_lock_t type from cproc_list_lock decl. + * [92/12/30 af] * - * * cthreads.h: Fix obsolescent #endif syntax. - * * cthread_internals.h: Likewise. - * * cancel-cond.c: Likewise. - * * stack.c: Likewise. - * * cthreads.c: Likewise. - * * cprocs.c: Likewise. - * * call.c: Likewise. * - * Revision 1.12 2000/01/10 14:42:30 kettenis - * 2000-01-10 Mark Kettenis <kettenis@gnu.org> - * - * * cprocs.c: Include <assert.h> - * - * Revision 1.11 2000/01/09 23:00:18 roland - * 2000-01-09 Roland McGrath <roland@baalperazim.frob.com> - * - * * cprocs.c (cproc_alloc): Initialize P->wired and P->msg here (code - * from cthread_wire). - * (cthread_wire): Reduce to just an assert, cthreads always wired. - * (chtread_unwire): Abort if called. - * - * Revision 1.10 1998/07/20 06:59:14 roland - * 1998-07-20 Roland McGrath <roland@baalperazim.frob.com> - * - * * i386/csw.S (cproc_prepare): Take address of cthread_body as third - * arg, so we don't have to deal with PIC magic to find its address - * without producing a text reloc. - * * cprocs.c (cproc_create): Pass &cthread_body to cproc_prepare. - * - * Revision 1.9 1996/11/18 23:54:51 thomas - * Mon Nov 18 16:36:56 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - * - * * cprocs.c (cproc_create): Cast CHILD in assignment. - * - * Revision 1.8 1995/12/06 19:48:34 mib - * (condition_unimplies): Take address of (*impp)->next in assignment to - * IMPP on loop step instruction. - * - * Revision 1.7 1995/09/22 17:51:10 roland - * Include hurd/threadvar.h. - * - * Revision 1.6 1995/08/30 15:57:47 mib - * Repair typos. - * - * Revision 1.5 1995/08/30 15:50:53 mib - * (cond_signal): If this condition has implications, see if one of them - * needs to be signalled when we have no waiters. - * (cond_broadcast): Signal the implications list too. - * (condition_implies, condition_unimplies): New functions. - * - * Revision 1.4 1995/04/04 21:04:29 roland - * (mutex_lock_solid, mutex_unlock_solid): Renamed to __*. - * (_cthread_mutex_lock_routine, _cthread_mutex_unlock_routine): Variables - * removed. - * - * Revision 1.3 1994/05/19 04:55:30 roland - * entered into RCS + * Revision 2.16 93/01/14 18:04:46 danner + * Convert file to ANSI C. + * [92/12/18 pds] + * 64bit cleanup. + * [92/12/10 21:08:32 af] * * Revision 2.15 92/03/06 14:09:31 rpd * Replaced swtch_pri with yield. @@ -270,15 +222,6 @@ #include <assert.h> /* - * C Threads imports: - */ -extern void alloc_stack(); -extern void cproc_switch(); /* cproc context switch */ -extern void cproc_start_wait(); /* cproc idle thread */ -extern vm_offset_t cproc_stack_base(); /* return start of stack */ -extern vm_offset_t stack_init(); - -/* * Port_entry's are used by cthread_mach_msg to store information * about each port/port_set for which it is managing threads */ @@ -358,8 +301,8 @@ private mach_msg_header_t wakeup_msg; /* prebuilt message used by idle * Return current value for max kernel threads * Note: 0 means no limit */ - -cthread_kernel_limit() +int +cthread_kernel_limit(void) { return cthread_max_kernel_threads; } @@ -370,8 +313,8 @@ cthread_kernel_limit() * over maximum. */ -cthread_set_kernel_limit(n) - int n; +void +cthread_set_kernel_limit(int n) { cthread_max_kernel_threads = n; } @@ -380,7 +323,8 @@ cthread_set_kernel_limit(n) * Wire a cthread to its current kernel thread */ -void cthread_wire() +void +cthread_wire(void) { register cproc_t p = cproc_self(); kern_return_t r; @@ -393,7 +337,8 @@ void cthread_wire() * Unwire a cthread. Deallocate its wait port. */ -void cthread_unwire() +void +cthread_unwire(void) { register cproc_t p = cproc_self(); @@ -416,7 +361,7 @@ void cthread_unwire() } private cproc_t -cproc_alloc() +cproc_alloc(void) { register cproc_t p = (cproc_t) malloc(sizeof(struct cproc)); kern_return_t r; @@ -466,7 +411,7 @@ cproc_alloc() */ vm_offset_t -cproc_init() +cproc_init(void) { kern_return_t r; @@ -503,9 +448,7 @@ cproc_init() * synching on its lock. Just send message to wired cproc. */ -private int cproc_ready(p, preq) - register cproc_t p; - register int preq; +private boolean_t cproc_ready(register cproc_t p, register int preq) { register cproc_t s=cproc_self(); kern_return_t r; @@ -586,8 +529,7 @@ private int cproc_ready(p, preq) */ void -cproc_waiting(p) - register cproc_t p; +cproc_waiting(cproc_t p) { mach_msg_header_t msg; register cproc_t new; @@ -634,8 +576,8 @@ cproc_waiting(p) * */ -cproc_t -cproc_waiter() +private cproc_t +cproc_waiter(void) { register cproc_t waiter; @@ -667,7 +609,8 @@ cproc_waiter() * You must hold cproc_self()->lock when called. */ -cproc_block() +private void +cproc_block(void) { extern unsigned int __hurd_threadvar_max; /* GNU */ register cproc_t waiter, new, p = cproc_self(); @@ -755,7 +698,7 @@ cproc_block() * Implement C threads using MACH threads. */ cproc_t -cproc_create() +cproc_create(void) { register cproc_t child = cproc_alloc(); register kern_return_t r; @@ -805,9 +748,7 @@ cproc_create() } void -condition_wait(c, m) - register condition_t c; - mutex_t m; +condition_wait(condition_t c, mutex_t m) { register cproc_t p = cproc_self(); @@ -877,8 +818,7 @@ condition_unimplies (condition_t implicator, condition_t implicatand) /* Signal one waiter on C. If there were no waiters at all, return 0, else return 1. */ int -cond_signal(c) - register condition_t c; +cond_signal(condition_t c) { register cproc_t p; struct cond_imp *imp; @@ -899,8 +839,7 @@ cond_signal(c) } void -cond_broadcast(c) - register condition_t c; +cond_broadcast(condition_t c) { register cproc_t p; struct cthread_queue blocked_queue; @@ -931,7 +870,7 @@ cond_broadcast(c) } void -cthread_yield() +cthread_yield(void) { register cproc_t new, p = cproc_self(); @@ -1040,8 +979,8 @@ __mutex_unlock_solid(void *ptr) * call to occur as often as is possible. */ -private port_entry_t get_port_entry(port, min, max) - mach_port_t port; +private port_entry_t +get_port_entry(mach_port_t port, int min, int max) { register port_entry_t i; @@ -1064,8 +1003,8 @@ private port_entry_t get_port_entry(port, min, max) return i; } -cthread_msg_busy(port, min, max) - mach_port_t port; +void +cthread_msg_busy(mach_port_t port, int min, int max) { register port_entry_t port_entry; register cproc_t new, p = cproc_self(); @@ -1096,8 +1035,8 @@ cthread_msg_busy(port, min, max) } -cthread_msg_active(port, min, max) -mach_port_t port; +void +cthread_msg_active(mach_port_t port, int min, int max) { register cproc_t p = cproc_self(); register port_entry_t port_entry; @@ -1115,17 +1054,11 @@ mach_port_t port; } mach_msg_return_t -cthread_mach_msg(header, option, - send_size, rcv_size, rcv_name, - timeout, notify, min, max) - register mach_msg_header_t *header; - register mach_msg_option_t option; - mach_msg_size_t send_size; - mach_msg_size_t rcv_size; - register mach_port_t rcv_name; - mach_msg_timeout_t timeout; - mach_port_t notify; - int min, max; +cthread_mach_msg(register mach_msg_header_t *header, + register mach_msg_option_t option, mach_msg_size_t send_size, + mach_msg_size_t rcv_size, register mach_port_t rcv_name, + mach_msg_timeout_t timeout, mach_port_t notify, int min, + int max) { register port_entry_t port_entry; register cproc_t p = cproc_self(); @@ -1184,7 +1117,8 @@ cthread_mach_msg(header, option, return r; } -cproc_fork_prepare() +void +cproc_fork_prepare(void) { register cproc_t p = cproc_self(); @@ -1193,7 +1127,8 @@ cproc_fork_prepare() spin_lock(&cproc_list_lock); } -cproc_fork_parent() +void +cproc_fork_parent(void) { register cproc_t p = cproc_self(); @@ -1202,7 +1137,8 @@ cproc_fork_parent() vm_inherit(mach_task_self(),p->stack_base, p->stack_size, VM_INHERIT_NONE); } -cproc_fork_child() +void +cproc_fork_child(void) { register cproc_t l,p = cproc_self(); cproc_t m; diff --git a/libthreads/cthread_data.c b/libthreads/cthread_data.c index 12d10610..02e6fa82 100644 --- a/libthreads/cthread_data.c +++ b/libthreads/cthread_data.c @@ -1,20 +1,26 @@ -/* +/* * Mach Operating System - * Copyright (c) 1991 Carnegie-Mellon University + * Copyright (c) 1992,1991 Carnegie-Mellon University * All rights reserved. The CMU software License Agreement specifies * the terms and conditions for use and redistribution. */ /* * HISTORY - * $Log: cthread_data.c,v $ - * Revision 1.1 1992/10/06 18:31:04 mib - * entered into RCS - * + * $Log: cthread_data.c,v $ + * Revision 2.4 93/05/10 17:51:20 rvb + * Make cthread_set_data and cthread_data macros. + * [93/05/06 rvb] + * + * Revision 2.3 93/01/14 18:04:52 danner + * Converted file to ANSI C. + * Removed usage of obsolete type any_t. + * [92/12/18 pds] + * * Revision 2.2 92/05/23 11:35:17 jfriedl * Snarfed from multi-server sources at CMU. * No stdio (for use with single-server). - * - * + * + * * Revision 2.2 91/03/25 14:14:45 jjc * For compatibility with cthread_data: * 1) Added routines, cthread_data and cthread_set_data, @@ -27,25 +33,25 @@ * Made simple implementation from POSIX threads specification for * thread specific data. * [91/03/07 jjc] - * + * */ -#include <cthreads.h> +#include <stdio.h> +#include <cthreads.h> -#ifdef CTHREAD_DATA -#define CTHREAD_KEY_FIRST (cthread_key_t)1 /* first free key */ -#else /* CTHREAD_DATA */ -#define CTHREAD_KEY_FIRST CTHREAD_KEY_NULL /* first free key */ -#endif /* CTHREAD_DATA */ #define CTHREAD_KEY_MAX (cthread_key_t)8 /* max. no. of keys */ #define CTHREAD_KEY_NULL (cthread_key_t)0 -#ifdef CTHREAD_DATA +#if defined(CTHREAD_DATA) /* * Key reserved for cthread_data */ #define CTHREAD_KEY_RESERVED CTHREAD_KEY_NULL -#endif /* CTHREAD_DATA */ + +#define CTHREAD_KEY_FIRST (cthread_key_t)1 /* first free key */ +#else /* not defined(CTHREAD_DATA) */ +#define CTHREAD_KEY_FIRST CTHREAD_KEY_NULL /* first free key */ +#endif /* defined(CTHREAD_DATA) */ /* lock protecting key creation */ @@ -61,8 +67,8 @@ cthread_key_t cthread_key = CTHREAD_KEY_FIRST; * maintained on a thread specific basis. * Returns 0 if successful and returns -1 otherwise. */ -cthread_keycreate(key) -cthread_key_t *key; +int +cthread_keycreate(cthread_key_t *key) { if (cthread_key >= CTHREAD_KEY_FIRST && cthread_key < CTHREAD_KEY_MAX) { mutex_lock((mutex_t)&cthread_data_lock); @@ -83,20 +89,19 @@ cthread_key_t *key; * If the calling thread doesn't have a value for the given key, * the value returned is CTHREAD_DATA_VALUE_NULL. */ -cthread_getspecific(key, value) -cthread_key_t key; -any_t *value; +int +cthread_getspecific(cthread_key_t key, void **value) { register cthread_t self; - register any_t *thread_data; + register void **thread_data; *value = CTHREAD_DATA_VALUE_NULL; if (key < CTHREAD_KEY_NULL || key >= cthread_key) return(-1); self = cthread_self(); - thread_data = (any_t *)(self->private_data); - if (thread_data != (any_t *)0) + thread_data = (void **)(self->private_data); + if (thread_data != NULL) *value = thread_data[key]; return(0); @@ -107,20 +112,19 @@ any_t *value; * Set private data associated with given key * Returns 0 if successful and returns -1 otherwise. */ -cthread_setspecific(key, value) -cthread_key_t key; -any_t value; +int +cthread_setspecific(cthread_key_t key, void *value) { register int i; register cthread_t self; - register any_t *thread_data; + register void **thread_data; if (key < CTHREAD_KEY_NULL || key >= cthread_key) return(-1); self = cthread_self(); - thread_data = (any_t *)(self->private_data); - if (thread_data != (any_t *)0) + thread_data = (void **)(self->private_data); + if (thread_data != NULL) thread_data[key] = value; else { /* @@ -128,12 +132,12 @@ any_t value; * point cthread_data at it, and then set the * data for the given key with the given value. */ - thread_data = (any_t *)malloc(CTHREAD_KEY_MAX * sizeof(any_t)); - if (thread_data == (any_t *)0) { + thread_data = malloc(CTHREAD_KEY_MAX * sizeof(void *)); + if (thread_data == NULL) { printf("cthread_setspecific: malloc failed\n"); return(-1); } - self->private_data = (any_t)thread_data; + self->private_data = thread_data; for (i = 0; i < CTHREAD_KEY_MAX; i++) thread_data[i] = CTHREAD_DATA_VALUE_NULL; @@ -144,16 +148,15 @@ any_t value; } -#ifdef CTHREAD_DATA +#if defined(CTHREAD_DATA_XX) /* * Set thread specific "global" variable, * using new POSIX routines. * Crash and burn if the thread given isn't the calling thread. * XXX For compatibility with old cthread_set_data() XXX */ -cthread_set_data(t, x) -cthread_t t; -any_t x; +int +cthread_set_data(cthread_t t, void *x) { register cthread_t self; @@ -162,6 +165,7 @@ any_t x; return(cthread_setspecific(CTHREAD_KEY_RESERVED, x)); else { ASSERT(t == self); + return(-1); } } @@ -172,12 +176,11 @@ any_t x; * Crash and burn if the thread given isn't the calling thread. * XXX For compatibility with old cthread_data() XXX */ -any_t -cthread_data(t) -cthread_t t; +void * +cthread_data(cthread_t t) { register cthread_t self; - any_t value; + void *value; self = cthread_self(); if (t == self) { @@ -186,6 +189,7 @@ cthread_t t; } else { ASSERT(t == self); + return(NULL); } } -#endif /* CTHREAD_DATA */ +#endif /* defined(CTHREAD_DATA_XX) */ diff --git a/libthreads/cthread_internals.h b/libthreads/cthread_internals.h index 69e71180..7c557428 100644 --- a/libthreads/cthread_internals.h +++ b/libthreads/cthread_internals.h @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -25,23 +25,28 @@ */ /* * HISTORY - * $Log: cthread_internals.h,v $ - * Revision 1.4 2001/03/31 23:01:01 roland - * 2001-03-31 Roland McGrath <roland@frob.com> + * 26-Oct-94 Johannes Helander (jvh) Helsinki University of Technology + * Defined WAIT_DEBUG and initialized wait_enum * - * * cthreads.h: Fix obsolescent #endif syntax. - * * cthread_internals.h: Likewise. - * * cancel-cond.c: Likewise. - * * stack.c: Likewise. - * * cthreads.c: Likewise. - * * cprocs.c: Likewise. - * * call.c: Likewise. + * $Log: cthread_internals.h,v $ + * Revision 2.17 93/05/10 21:33:36 rvb + * Context is a natural_t. Assumming, that is, that on + * some future architecture one word might be enough. + * [93/05/06 09:19:35 af] * - * Revision 1.3 1995/08/29 14:49:20 mib - * (cproc_block): Provide decl. + * Revision 2.16 93/05/10 17:51:23 rvb + * Flush stdlib + * [93/05/05 09:12:29 rvb] * - * Revision 1.2 1994/05/05 10:58:01 roland - * entered into RCS + * Revision 2.15 93/01/14 18:04:56 danner + * Added declarations for library-internal routines. + * [92/12/18 pds] + * + * Replaced malloc and mach_error declarations with includes of + * mach_error.h and stdlib.h. + * [92/06/13 pds] + * 64bit cleanup. + * [92/12/01 af] * * Revision 2.14 92/08/03 18:03:56 jfriedl * Made state element of struct cproc volatile. @@ -160,7 +165,7 @@ typedef struct cproc { mach_port_t reply_port; /* for mig_get_reply_port() */ #endif - int context; + natural_t context; spin_lock_t lock; volatile int state; /* current state */ #define CPROC_RUNNING 0 @@ -173,15 +178,13 @@ typedef struct cproc { mach_msg_header_t msg; - unsigned int stack_base; - unsigned int stack_size; + vm_offset_t stack_base; + vm_offset_t stack_size; } *cproc_t; #define NO_CPROC ((cproc_t) 0) #define cproc_self() ((cproc_t) ur_cthread_self()) -int cproc_block (); - #if 0 /* This declaration conflicts with <stdlib.h> in GNU. */ /* @@ -221,3 +224,71 @@ extern void mach_error(); #define yield() \ (void) thread_switch(MACH_PORT_NULL, SWITCH_OPTION_DEPRESS, 10) + +/* + * Functions implemented in malloc.c. + */ + +#if defined(DEBUG) +extern void print_malloc_free_list(void); +#endif /* defined(DEBUG) */ + +extern void malloc_fork_prepare(void); + +extern void malloc_fork_parent(void); + +extern void malloc_fork_child(void); + + +/* + * Functions implemented in stack.c. + */ + +extern vm_offset_t stack_init(cproc_t _cproc); + +extern void alloc_stack(cproc_t _cproc); + +extern vm_offset_t cproc_stack_base(cproc_t _cproc, int _offset); + +extern void stack_fork_child(void); + +/* + * Functions implemented in cprocs.c. + */ + +extern vm_offset_t cproc_init(void); + +extern void cproc_waiting(cproc_t _waiter); + +extern cproc_t cproc_create(void); + +extern void cproc_fork_prepare(void); + +extern void cproc_fork_parent(void); + +extern void cproc_fork_child(void); + +/* + * Function implemented in cthreads.c. + */ + +extern void cthread_body(cproc_t _self); + +/* + * Functions from machine dependent files. + */ + +extern void cproc_switch(natural_t *_cur, const natural_t *_new, + spin_lock_t *_lock); + +extern void cproc_start_wait(natural_t *_parent, cproc_t _child, + vm_offset_t _stackp, + spin_lock_t *_lock); + +extern void cproc_prepare(cproc_t _child, + natural_t *_child_context, + vm_offset_t _stackp, + void (*cthread_body_pc)()); + +extern void cproc_setup(cproc_t _child, thread_t _mach_thread, + void (*_routine)(cproc_t)); diff --git a/libthreads/cthreads.c b/libthreads/cthreads.c index 12126f20..645ac939 100644 --- a/libthreads/cthreads.c +++ b/libthreads/cthreads.c @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -25,52 +25,24 @@ */ /* * HISTORY - * $Log: cthreads.c,v $ - * Revision 1.10 2001/03/31 23:01:01 roland - * 2001-03-31 Roland McGrath <roland@frob.com> + * 20-Oct-93 Tero Kivinen (kivinen) at Helsinki University of Technology + * Renamed cthread_t->catch to to cthread_t->catch_exit, because + * catch is reserved word in c++. * - * * cthreads.h: Fix obsolescent #endif syntax. - * * cthread_internals.h: Likewise. - * * cancel-cond.c: Likewise. - * * stack.c: Likewise. - * * cthreads.c: Likewise. - * * cprocs.c: Likewise. - * * call.c: Likewise. + * $Log: cthreads.c,v $ + * Revision 2.13 93/01/21 12:27:55 danner + * Remove deadlock in cproc_fork_child; must release malloc lock first. + * [93/01/19 16:37:43 bershad] * - * Revision 1.9 1998/11/22 18:18:10 roland - * 1998-11-12 Mark Kettenis <kettenis@phys.uva.nl> + * Revision 2.12 93/01/14 18:05:00 danner + * Converted file to ANSI C. + * Removed use of obsolete type any_t. + * [92/12/18 pds] + * 64bit cleanup. + * [92/12/01 af] * - * * 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> - * - * * cthreads.c (cthread_body): Wire self before calling user work - * function. This way all cthreads will be wired, which the ports - * library (and hurd_thread_cancel, etc.) depend on. - * - * Revision 1.6 1997/06/10 01:22:19 thomas - * Mon Jun 9 21:18:46 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> - * - * * 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 + * Free private_data in cthread_exit, from Mike Kupfer. + * [92/11/30 af] * * Revision 2.11 92/07/20 13:33:37 cmaeda * In cthread_init, do machine dependent initialization if it's defined. @@ -147,33 +119,19 @@ */ #include <cthreads.h> +#include <mach/mig_support.h> #include "cthread_internals.h" /* - * C Threads imports: - */ -extern void cproc_create(); -extern vm_offset_t cproc_init(); -extern void mig_init(); - -/* - * Mach imports: - */ - -/* - * C library imports: - */ - -/* * Thread status bits. */ #define T_MAIN 0x1 #define T_RETURNED 0x2 #define T_DETACHED 0x4 -#ifdef DEBUG +#if defined(DEBUG) int cthread_debug = FALSE; -#endif /* DEBUG */ +#endif /* defined(DEBUG) */ private struct cthread_queue cthreads = QUEUE_INITIALIZER; private struct mutex cthread_lock = MUTEX_INITIALIZER; @@ -189,9 +147,7 @@ private spin_lock_t free_lock = SPIN_LOCK_INITIALIZER; /* unlocked */ private struct cthread initial_cthread = { 0 }; private cthread_t -cthread_alloc(func, arg) - cthread_fn_t func; - any_t arg; +cthread_alloc(cthread_fn_t func, void *arg) { register cthread_t t = NO_CTHREAD; @@ -223,8 +179,7 @@ cthread_alloc(func, arg) } private void -cthread_free(t) - register cthread_t t; +cthread_free(cthread_t t) { spin_lock(&free_lock); t->next = free_cthreads; @@ -232,8 +187,8 @@ cthread_free(t) spin_unlock(&free_lock); } -int -cthread_init() +vm_offset_t +cthread_init(void) { static int cthreads_started = FALSE; register cproc_t p; @@ -242,9 +197,9 @@ cthread_init() if (cthreads_started) return 0; - t = cthread_alloc((cthread_fn_t) 0, (any_t) 0); stack = cproc_init(); cthread_cprocs = 1; + t = cthread_alloc((cthread_fn_t) 0, (void *) 0); #ifdef cthread_md_init cthread_md_init(); @@ -270,16 +225,15 @@ cthread_init() /* * Used for automatic initialization by crt0. - * Cast needed since too many C compilers choke on the type void (*)(). */ -int (*_cthread_init_routine)() = (int (*)()) cthread_init; +vm_offset_t (*_cthread_init_routine)(void) = cthread_init; + /* * Procedure invoked at the base of each cthread. */ void -cthread_body(self) - cproc_t self; +cthread_body(cproc_t self) { register cthread_t t; @@ -297,8 +251,7 @@ cthread_body(self) */ mutex_unlock(&cthread_lock); cthread_assoc(self, t); /* assume thread's identity */ - if (_setjmp(t->catch) == 0) { /* catch for cthread_exit() */ - cthread_wire (); + if (_setjmp(t->catch_exit) == 0) { /* catch for cthread_exit() */ /* * Execute the fork request. */ @@ -333,9 +286,7 @@ cthread_body(self) } cthread_t -cthread_fork(func, arg) - cthread_fn_t func; - any_t arg; +cthread_fork(cthread_fn_t func, void *arg) { register cthread_t t; @@ -367,11 +318,10 @@ cthread_detach(t) } } -any_t -cthread_join(t) - cthread_t t; +void * +cthread_join(cthread_t t) { - any_t result; + void *result; TRACE(printf("[%s] join(%s)\n", cthread_name(cthread_self()), cthread_name(t))); mutex_lock(&t->lock); @@ -385,21 +335,24 @@ cthread_join(t) } void -cthread_exit(result) - any_t result; +cthread_exit(void *result) { register cthread_t t = cthread_self(); TRACE(printf("[%s] exit()\n", cthread_name(t))); t->result = result; + if (t->private_data != 0) { + free((char *)t->private_data); + t->private_data = 0; + } if (t->state & T_MAIN) { mutex_lock(&cthread_lock); while (cthread_cthreads > 1) condition_wait(&cthread_idle, &cthread_lock); mutex_unlock(&cthread_lock); - exit((int)(long)result); + exit((int) (integer_t) result); } else { - _longjmp(t->catch, TRUE); + _longjmp(t->catch_exit, TRUE); } } @@ -410,60 +363,60 @@ cthread_exit(result) int (*_cthread_exit_routine)() = (int (*)()) cthread_exit; void -cthread_set_name(t, name) - cthread_t t; - char *name; +cthread_set_name(cthread_t t, const char *name) { t->name = name; } -char * -cthread_name(t) - cthread_t t; +const char * +cthread_name(cthread_t t) { - return (t == NO_CTHREAD - ? "idle" - : (t->name == 0 ? "?" : t->name)); + return (t == NO_CTHREAD ? "idle" : (t->name == 0 ? "?" : t->name)); } int -cthread_limit() +cthread_limit(void) { return cthread_max_cprocs; } void -cthread_set_limit(n) - int n; +cthread_set_limit(int n) { cthread_max_cprocs = n; } int -cthread_count() +cthread_count(void) { return cthread_cthreads; } -cthread_fork_prepare() +void +cthread_fork_prepare(void) { spin_lock(&free_lock); mutex_lock(&cthread_lock); + malloc_fork_prepare(); cproc_fork_prepare(); } -cthread_fork_parent() +void +cthread_fork_parent(void) { cproc_fork_parent(); + malloc_fork_parent(); mutex_unlock(&cthread_lock); spin_unlock(&free_lock); } -cthread_fork_child() +void +cthread_fork_child(void) { cthread_t t; cproc_t p; + malloc_fork_child(); cproc_fork_child(); mutex_unlock(&cthread_lock); spin_unlock(&free_lock); diff --git a/libthreads/cthreads.h b/libthreads/cthreads.h index c1dfd44c..26abfd6a 100644 --- a/libthreads/cthreads.h +++ b/libthreads/cthreads.h @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1993,1992,1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -25,67 +25,58 @@ */ /* * HISTORY - * $Log: cthreads.h,v $ - * Revision 1.16 2001/03/31 23:01:01 roland - * 2001-03-31 Roland McGrath <roland@frob.com> - * - * * cthreads.h: Fix obsolescent #endif syntax. - * * cthread_internals.h: Likewise. - * * cancel-cond.c: Likewise. - * * stack.c: Likewise. - * * cthreads.c: Likewise. - * * cprocs.c: Likewise. - * * 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. - * - * Revision 1.11 1996/01/24 18:37:59 roland - * Use prototypes for functions of zero args. - * - * Revision 1.10 1995/09/13 19:50:07 mib - * (CONDITION_INITIALIZER): Provide initial zero for IMPLICATIONS member. - * (condition_init): Bother initializing NAME and IMPLICATIONS members. - * - * Revision 1.9 1995/08/30 15:51:41 mib - * (condition_implies, condition_unimplies): New functions. - * (struct condition): New member `implications'. - * (cond_imp): New structure. - * (cond_signal): Return int now. - * (condition_broadcast): Always call cond_broadcast if this condition - * has implications. - * (condition_signal): Always call cond_signal if this condition has - * implications. - * - * Revision 1.8 1995/08/30 15:10:23 mib - * (hurd_condition_wait): Provide declaration. - * - * Revision 1.7 1995/07/18 17:15:51 mib - * Reverse previous change. - * - * Revision 1.5 1995/04/04 21:06:16 roland - * (mutex_lock, mutex_unlock): Use __ names for *_solid. - * - * Revision 1.4 1994/05/05 10:52:06 roland - * entered into RCS + * 20-Oct-93 Tero Kivinen (kivinen) at Helsinki University of Technology + * Renamed cthread_t->catch to to cthread_t->catch_exit, because + * catch is reserved word in c++. + * + * 12-Oct-93 Johannes Helander (jvh) at Helsinki University of Technology + * Added CONDITION_NAMED_INITIALIZER and MUTEX_NAMED_INITIALIZER1 + * macros. They take one argument: a name string. + * + * $Log: cthreads.h,v $ + * Revision 2.17 93/05/10 19:43:11 rvb + * Removed include of stdlib.h and just define malloc + * [93/04/27 mrt] + * + * Revision 2.16 93/05/10 17:51:26 rvb + * Just imagine how much more useful TWO special/fast lookup + * variables could be. (Actually, I am planning on using this + * for bsdss -- for multiple threads per task. If I don't, I'll + * remove the feature.) + * [93/05/10 rvb] + * Big mistake here! CTHREAD_DATA must always be set TRUE. + * cthreads.h is included by import_mach.h by lots of files + * that are not compiled with -DCTHREAD_DATA. This means + * they see a different structure for cthread_t than the + * cthread library -- which is compiled with CTHREAD_DATA. + * Also, make cthread_set_data and cthread_data macros. + * [93/05/06 rvb] + * Flush stdlib + * [93/05/05 rvb] + * + * Revision 2.15 93/01/27 09:03:32 danner + * Updated include of mach/mach.h to mach.h + * + * + * Revision 2.14 93/01/24 13:24:50 danner + * Get MACRO_BEGIN, MACRO_END, NEVER, ... from sys/macro_help.h + * why define it here. + * [92/10/20 rvb] + * + * Revision 2.13 93/01/14 18:05:04 danner + * Added MACRO_BEGIN and MACRO_END to definition of spin_lock. + * Fixed return value of cthread_set_data. + * Added prototypes for other miscellaneous functions. + * [92/12/18 pds] + * Converted file to ANSI C. + * Added declarations of cthread_fork_{prepare,parent,child}. + * Added include of <sys/macro_help.h>. + * [92/12/13 pds] + * + * Replaced calloc declaration with an include of stdlib.h. + * [92/06/15 pds] + * 64bit cleanup. + * [92/12/02 af] * * Revision 2.12 92/05/22 18:38:36 jfriedl * From Mike Kupfer <kupfer@sprite.Berkeley.EDU>: @@ -225,62 +216,46 @@ #ifndef _CTHREADS_ #define _CTHREADS_ 1 -/* MIB XXX */ -#define CTHREAD_DATA +#define WAIT_DEBUG /* XXX should be defined somewhere else */ #if 0 /* This is CMU's machine-dependent file. In GNU all of the machine dependencies are dealt with in libc. */ #include <machine/cthreads.h> +#include <mach.h> +#include <sys/macro_help.h> +#include <mach/machine/vm_param.h> + +#ifdef __STDC__ +extern void *malloc(); #else -#include <machine-sp.h> -#define cthread_sp() ((vm_address_t) __thread_stack_pointer ()) +extern char *malloc(); #endif -#if c_plusplus || __STDC__ - -#ifndef C_ARG_DECLS -#define C_ARG_DECLS(arglist) arglist -#endif /* not C_ARG_DECLS */ - -typedef void *any_t; - -#else /* not (c_plusplus || __STDC__) */ - -#ifndef C_ARG_DECLS -#define C_ARG_DECLS(arglist) () -#endif /* not C_ARG_DECLS */ - -typedef char *any_t; +#else /* GNU */ +# include <stdlib.h> +# include <mach.h> +# include <mach/machine/vm_param.h> +# include <machine-sp.h> +# define cthread_sp() ((vm_address_t) __thread_stack_pointer ()) +# define MACRO_BEGIN __extension__ ({ +# define MACRO_END 0; }) +#endif -#endif /* not (c_plusplus || __STDC__) */ +typedef void *any_t; /* XXX - obsolete, should be deleted. */ -#include <mach/mach.h> -#include <mach/machine/vm_param.h> - -#ifndef TRUE +#if defined(TRUE) +#else /* not defined(TRUE) */ #define TRUE 1 #define FALSE 0 -#endif /* TRUE */ - - -#undef MACRO_BEGIN -#undef MACRO_END -#define MACRO_BEGIN __extension__ ({ -#define MACRO_END 0; }) - +#endif /* * C Threads package initialization. */ -extern int cthread_init C_ARG_DECLS((void)); -#if 0 -/* This prototype is broken for GNU. */ -extern any_t calloc C_ARG_DECLS((unsigned n, unsigned size)); -#else -#include <stdlib.h> -#endif +extern vm_offset_t cthread_init(void); + /* * Queues. @@ -300,7 +275,7 @@ typedef struct cthread_queue_item { #define cthread_queue_alloc() ((cthread_queue_t) calloc(1, sizeof(struct cthread_queue))) #define cthread_queue_init(q) ((q)->head = (q)->tail = 0) -#define cthread_queue_free(q) free((any_t) (q)) +#define cthread_queue_free(q) free((q)) #define cthread_queue_enq(q, x) \ MACRO_BEGIN \ @@ -332,7 +307,7 @@ typedef struct cthread_queue_item { #define cthread_queue_map(q, t, f) \ MACRO_BEGIN \ register cthread_queue_item_t x, next; \ - for (x = (cthread_queue_item_t) ((q)->head); x != 0; x = next) { \ + for (x = (cthread_queue_item_t) ((q)->head); x != 0; x = next){\ next = x->next; \ (*(f))((t) x); \ } \ @@ -349,20 +324,24 @@ typedef struct cthread_queue_item { /* * Spin locks. */ -extern void -spin_lock_solid C_ARG_DECLS((spin_lock_t *p)); +extern void spin_lock_solid(spin_lock_t *_lock); -#ifndef spin_unlock -extern void -spin_unlock C_ARG_DECLS((spin_lock_t *p)); +#if defined(spin_unlock) +#else /* not defined(spin_unlock) */ +extern void spin_unlock(spin_lock_t *_lock); #endif -#ifndef spin_try_lock -extern int -spin_try_lock C_ARG_DECLS((spin_lock_t *p)); +#if defined(spin_try_lock) +#else /* not defined(spin_try_lock) */ +extern boolean_t spin_try_lock(spin_lock_t *_lock); #endif -#define spin_lock(p) ({if (!spin_try_lock(p)) spin_lock_solid(p);}) +#define spin_lock(p) \ + MACRO_BEGIN \ + if (!spin_try_lock(p)) { \ + spin_lock_solid(p); \ + } \ + MACRO_END #endif /* End unused CMU code. */ @@ -376,12 +355,15 @@ typedef struct mutex { see if it gets the mutex. */ spin_lock_t held; spin_lock_t lock; - char *name; + const char *name; struct cthread_queue queue; + /* holder is for WAIT_DEBUG. Not ifdeffed to keep size constant. */ + struct cthread *holder; } *mutex_t; /* Rearranged accordingly for GNU: */ -#define MUTEX_INITIALIZER { SPIN_LOCK_INITIALIZER, SPIN_LOCK_INITIALIZER, 0, QUEUE_INITIALIZER } +#define MUTEX_INITIALIZER { SPIN_LOCK_INITIALIZER, SPIN_LOCK_INITIALIZER, 0, QUEUE_INITIALIZER, } +#define MUTEX_NAMED_INITIALIZER(Name) { SPIN_LOCK_INITIALIZER, SPIN_LOCK_INITIALIZER, Name, QUEUE_INITIALIZER, } #define mutex_alloc() ((mutex_t) calloc(1, sizeof(struct mutex))) #define mutex_init(m) \ @@ -389,37 +371,52 @@ typedef struct mutex { spin_lock_init(&(m)->lock); \ cthread_queue_init(&(m)->queue); \ spin_lock_init(&(m)->held); \ + (m)->holder = 0; \ MACRO_END #define mutex_set_name(m, x) ((m)->name = (x)) #define mutex_name(m) ((m)->name != 0 ? (m)->name : "?") -#define mutex_clear(m) mutex_init(m) -#define mutex_free(m) free((any_t) (m)) - -extern void __mutex_lock_solid (void *mutex); /* blocking -- roland@gnu */ -extern void __mutex_unlock_solid (void *mutex); /* roland@gnu */ +#define mutex_clear(m) /* nop */??? +#define mutex_free(m) free((m)) #define mutex_try_lock(m) spin_try_lock(&(m)->held) +#if defined(WAIT_DEBUG) #define mutex_lock(m) \ MACRO_BEGIN \ if (!spin_try_lock(&(m)->held)) { \ __mutex_lock_solid(m); \ } \ + (m)->holder = cthread_self(); \ MACRO_END #define mutex_unlock(m) \ MACRO_BEGIN \ if (spin_unlock(&(m)->held), \ - cthread_queue_head(&(m)->queue, void *) != 0) { \ + cthread_queue_head(&(m)->queue, vm_offset_t) != 0) { \ __mutex_unlock_solid(m); \ } \ + (m)->holder = 0; \ MACRO_END - +#else /* defined(WAIT_DEBUG */ +#define mutex_lock(m) \ + MACRO_BEGIN \ + if (!spin_try_lock(&(m)->held)) { \ + __mutex_lock_solid(m); \ + } \ + MACRO_END +#define mutex_unlock(m) \ + MACRO_BEGIN \ + if (spin_unlock(&(m)->held), \ + cthread_queue_head(&(m)->queue, vm_offset_t) != 0) { \ + __mutex_unlock_solid(m); \ + } \ + MACRO_END +#endif /* defined(WAIT_DEBUG) */ /* * Condition variables. */ typedef struct condition { spin_lock_t lock; struct cthread_queue queue; - char *name; + const char *name; struct cond_imp *implications; } *condition_t; @@ -430,8 +427,10 @@ struct cond_imp }; #define CONDITION_INITIALIZER { SPIN_LOCK_INITIALIZER, QUEUE_INITIALIZER, 0, 0 } +#define CONDITION_NAMED_INITIALIZER(Name) { SPIN_LOCK_INITIALIZER, QUEUE_INITIALIZER, Name, 0 } -#define condition_alloc() ((condition_t) calloc(1, sizeof(struct condition))) +#define condition_alloc() \ + ((condition_t) calloc(1, sizeof(struct condition))) #define condition_init(c) \ MACRO_BEGIN \ spin_lock_init(&(c)->lock); \ @@ -449,7 +448,7 @@ struct cond_imp #define condition_free(c) \ MACRO_BEGIN \ condition_clear(c); \ - free((any_t) (c)); \ + free((c)); \ MACRO_END #define condition_signal(c) \ @@ -466,29 +465,17 @@ struct cond_imp } \ MACRO_END -extern int -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)); +extern int cond_signal(condition_t _cond); -extern int -hurd_condition_wait C_ARG_DECLS((condition_t c, mutex_t m)); +extern void cond_broadcast(condition_t _cond); -extern void -condition_implies C_ARG_DECLS((condition_t implicator, condition_t implicatand)); - -extern void -condition_unimplies C_ARG_DECLS((condition_t implicator, condition_t implicatand)); +extern void condition_wait(condition_t _cond, mutex_t _mutex); /* * Threads. */ -typedef any_t (*cthread_fn_t) C_ARG_DECLS((any_t arg)); +typedef void * (*cthread_fn_t)(void *arg); #include <setjmp.h> @@ -497,34 +484,28 @@ typedef struct cthread { struct mutex lock; struct condition done; int state; - jmp_buf catch; + jmp_buf catch_exit; cthread_fn_t func; - any_t arg; - any_t result; - char *name; -#ifdef CTHREAD_DATA - any_t data; -#endif /* CTHREAD_DATA */ - any_t private_data; + void *arg; + void *result; + const char *name; + void *data; + void *ldata; + void *private_data; struct ur_cthread *ur; } *cthread_t; #define NO_CTHREAD ((cthread_t) 0) -extern cthread_t -cthread_fork C_ARG_DECLS((cthread_fn_t func, any_t arg)); +extern cthread_t cthread_fork(cthread_fn_t _func, void *_arg); -extern void -cthread_detach C_ARG_DECLS((cthread_t t)); +extern void cthread_detach(cthread_t _thread); -extern any_t -cthread_join C_ARG_DECLS((cthread_t t)); +extern any_t cthread_join(cthread_t _thread); -extern void -cthread_yield C_ARG_DECLS((void)); +extern void cthread_yield(void); -extern void -cthread_exit C_ARG_DECLS((any_t result)); +extern void cthread_exit(void *_result); /* * This structure must agree with struct cproc in cthread_internals.h @@ -535,20 +516,20 @@ typedef struct ur_cthread { } *ur_cthread_t; #ifndef cthread_sp -extern int -cthread_sp C_ARG_DECLS((void)); +extern vm_offset_t +cthread_sp(void); #endif -extern int cthread_stack_mask; +extern vm_offset_t cthread_stack_mask; -#ifdef STACK_GROWTH_UP +#if defined(STACK_GROWTH_UP) #define ur_cthread_ptr(sp) \ (* (ur_cthread_t *) ((sp) & cthread_stack_mask)) -#else /* STACK_GROWTH_UP */ +#else /* not defined(STACK_GROWTH_UP) */ #define ur_cthread_ptr(sp) \ (* (ur_cthread_t *) ( ((sp) | cthread_stack_mask) + 1 \ - sizeof(ur_cthread_t *)) ) -#endif /* STACK_GROWTH_UP */ +#endif /* defined(STACK_GROWTH_UP) */ #define ur_cthread_self() (ur_cthread_ptr(cthread_sp())) @@ -556,37 +537,80 @@ extern int cthread_stack_mask; ((t) ? ((t)->ur = (ur_cthread_t)(id)) : 0)) #define cthread_self() (ur_cthread_self()->incarnation) -extern void -cthread_set_name C_ARG_DECLS((cthread_t t, char *name)); +extern void cthread_set_name(cthread_t _thread, const char *_name); + +extern const char * cthread_name(cthread_t _thread); + +extern int cthread_count(void); + +extern void cthread_set_limit(int _limit); -extern char * -cthread_name C_ARG_DECLS((cthread_t t)); +extern int cthread_limit(void); -extern int -cthread_count C_ARG_DECLS((void)); +extern void cthread_set_kernel_limit(int _n); -extern void -cthread_set_limit C_ARG_DECLS((int n)); +extern int cthread_kernel_limit(void); -extern int -cthread_limit C_ARG_DECLS((void)); +extern void cthread_wire(void); -extern void -cthread_wire C_ARG_DECLS((void)); +extern void cthread_unwire(void); -#ifdef CTHREAD_DATA +extern void cthread_msg_busy(mach_port_t _port, int _min, int _max); + +extern void cthread_msg_active(mach_port_t _prt, int _min, int _max); + +extern mach_msg_return_t cthread_mach_msg(mach_msg_header_t *_header, + mach_msg_option_t _option, + mach_msg_size_t _send_size, + mach_msg_size_t _rcv_size, + mach_port_t _rcv_name, + mach_msg_timeout_t _timeout, + mach_port_t _notify, + int _min, int _max); + +extern void cthread_fork_prepare(void); + +extern void cthread_fork_parent(void); + +extern void cthread_fork_child(void); + +#if defined(THREAD_CALLS) +/* + * Routines to replace thread_*. + */ +extern kern_return_t cthread_get_state(cthread_t _thread); + +extern kern_return_t cthread_set_state(cthread_t _thread); + +extern kern_return_t cthread_abort(cthread_t _thread); + +extern kern_return_t cthread_resume(cthread_t _thread); + +extern kern_return_t cthread_suspend(cthread_t _thread); + +extern kern_return_t cthread_call_on(cthread_t _thread); +#endif /* defined(THREAD_CALLS) */ + +#if defined(CTHREAD_DATA_XX) /* * Set or get thread specific "global" variable * * The thread given must be the calling thread (ie. thread_self). * XXX This is for compatibility with the old cthread_data. XXX */ -extern int -cthread_set_data C_ARG_DECLS((cthread_t t, any_t x)); +extern int cthread_set_data(cthread_t _thread, void *_val); + +extern void * cthread_data(cthread_t _thread); +#else /* defined(CTHREAD_DATA_XX) */ + +#define cthread_set_data(_thread, _val) ((_thread)->data) = (void *)(_val); +#define cthread_data(_thread) ((_thread)->data) + +#define cthread_set_ldata(_thread, _val) ((_thread)->ldata) = (void *)(_val); +#define cthread_ldata(_thread) ((_thread)->ldata) + +#endif /* defined(CTHREAD_DATA_XX) */ -extern any_t -cthread_data C_ARG_DECLS((cthread_t t)); -#endif /* CTHREAD_DATA */ /* * Support for POSIX thread specific data @@ -594,7 +618,7 @@ cthread_data C_ARG_DECLS((cthread_t t)); * Multiplexes a thread specific "global" variable * into many thread specific "global" variables. */ -#define CTHREAD_DATA_VALUE_NULL (any_t)0 +#define CTHREAD_DATA_VALUE_NULL (void *)0 #define CTHREAD_KEY_INVALID (cthread_key_t)-1 typedef int cthread_key_t; @@ -604,27 +628,25 @@ typedef int cthread_key_t; * Different threads may use same key, but the values bound to the key are * maintained on a thread specific basis. */ -extern int -cthread_keycreate C_ARG_DECLS((cthread_key_t *key)); +extern int cthread_keycreate(cthread_key_t *_key); /* * Get value currently bound to key for calling thread */ -extern int -cthread_getspecific C_ARG_DECLS((cthread_key_t key, any_t *value)); +extern int cthread_getspecific(cthread_key_t _key, void **_value); /* * Bind value to given key for calling thread */ -extern int -cthread_setspecific C_ARG_DECLS((cthread_key_t key, any_t value)); +extern int cthread_setspecific(cthread_key_t _key, void *_value); /* * Debugging support. */ -#ifdef DEBUG +#if defined(DEBUG) -#ifndef ASSERT +#if defined(ASSERT) +#else /* not defined(ASSERT) */ /* * Assertion macro, similar to <assert.h> */ @@ -639,18 +661,19 @@ cthread_setspecific C_ARG_DECLS((cthread_key_t key, any_t value)); } \ MACRO_END -#endif /* ASSERT */ +#endif /* defined(ASSERT) */ #define SHOULDNT_HAPPEN 0 extern int cthread_debug; -#else /* DEBUG */ +#else /* not defined(DEBUG) */ -#ifndef ASSERT +#if defined(ASSERT) +#else /* not defined(ASSERT) */ #define ASSERT(p) -#endif /* ASSERT */ +#endif /* defined(ASSERT) */ -#endif /* DEBUG */ +#endif /* defined(DEBUG) */ -#endif /* _CTHREADS_ */ +#endif /* not defined(_CTHREADS_) */ diff --git a/libthreads/i386/cthreads.h b/libthreads/i386/cthreads.h index 8ffe4b72..643e7350 100644 --- a/libthreads/i386/cthreads.h +++ b/libthreads/i386/cthreads.h @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University + * Copyright (c) 1993,1991,1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -26,6 +26,15 @@ /* * HISTORY * $Log: cthreads.h,v $ + * Revision 2.9 93/01/24 13:24:58 danner + * Move ! in spin_try_lock to give the compiler + * a fighting chance. + * [92/11/19 rvb] + * + * Revision 2.8 93/01/14 18:05:09 danner + * asm -> __asm__ + * [93/01/10 danner] + * * Revision 2.7 92/01/03 20:36:59 dbg * Add volatile to spin_lock_t. Change spin_unlock and * spin_try_lock definitions back to memory operands, but rely on @@ -66,21 +75,21 @@ typedef volatile int spin_lock_t; #define spin_unlock(p) \ ({ register int _u__ ; \ - asm volatile("xorl %0, %0; \n\ + __asm__ volatile("xorl %0, %0; \n\ xchgl %0, %1" \ : "=&r" (_u__), "=m" (*(p)) ); \ 0; }) #define spin_try_lock(p)\ - ({ boolean_t _r__; \ - asm volatile("movl $1, %0; \n\ + (!({ boolean_t _r__; \ + __asm__ volatile("movl $1, %0; \n\ xchgl %0, %1" \ : "=&r" (_r__), "=m" (*(p)) ); \ - !_r__; }) + _r__; })) #define cthread_sp() \ ({ int _sp__; \ - asm("movl %%esp, %0" \ + __asm__("movl %%esp, %0" \ : "=g" (_sp__) ); \ _sp__; }) diff --git a/libthreads/i386/lock.s b/libthreads/i386/lock.s index e27fa7ff..f064e5bb 100644 --- a/libthreads/i386/lock.s +++ b/libthreads/i386/lock.s @@ -26,6 +26,10 @@ /* * HISTORY * $Log: lock.s,v $ + * Revision 2.6 93/05/10 17:51:38 rvb + * Use C Comment + * [93/05/04 18:14:05 rvb] + * * Revision 2.5 91/05/14 17:57:20 mrt * Correcting copyright * @@ -49,22 +53,22 @@ * boolean_t spin_try_lock(int *m) */ ENTRY(spin_try_lock) - movl 4(%esp),%ecx / point at mutex - movl $1,%eax / set locked value in acc - xchg %eax,(%ecx) / swap with mutex - / xchg with memory is automatically - / locked - xorl $1,%eax / 1 (locked) => FALSE - / 0 (locked) => TRUE + movl 4(%esp),%ecx /* point at mutex */ + movl $1,%eax /* set locked value in acc */ + xchg %eax,(%ecx) /* swap with mutex */ + /* xchg with memory is automatically */ + /* locked */ + xorl $1,%eax /* 1 (locked) => FALSE */ + /* 0 (locked) => TRUE */ ret /* * void spin_unlock(int *m) */ ENTRY(spin_unlock) - movl 4(%esp),%ecx / point at mutex - xorl %eax,%eax / set unlocked value in acc - xchg %eax,(%ecx) / swap with mutex - / xchg with memory is automatically - / locked + movl 4(%esp),%ecx /* point at mutex */ + xorl %eax,%eax /* set unlocked value in acc */ + xchg %eax,(%ecx) /* swap with mutex */ + /* xchg with memory is automatically */ + /* locked */ ret diff --git a/libthreads/i386/thread.c b/libthreads/i386/thread.c index c6781b9d..c0195a8b 100644 --- a/libthreads/i386/thread.c +++ b/libthreads/i386/thread.c @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990 Carnegie Mellon University + * Copyright (c) 1992,1991,1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -25,44 +25,20 @@ */ /* * HISTORY - * $Log: thread.c,v $ - * Revision 1.5 2001/03/31 23:03:03 roland - * 2001-03-31 Roland McGrath <roland@frob.com> + * $Log: thread.c,v $ + * Revision 2.8 93/02/02 21:54:58 mrt + * Changed include of mach/mach.h to mach.h. + * [93/02/02 mrt] * - * * cthreads.h: Fix obsolescent #endif syntax. - * * cthread_internals.h: Likewise. - * * cancel-cond.c: Likewise. - * * stack.c: Likewise. - * * cthreads.c: Likewise. - * * cprocs.c: Likewise. - * * call.c: Likewise. - * * i386/thread.c: Likewise. - * - * Revision 1.4 2001/02/26 04:15:27 roland - * 2001-02-25 Roland McGrath <roland@frob.com> - * - * * i386/thread.c: Remove superfluous bzero decl, - * just include <strings.h> instead. - * - * Revision 1.3 1997/02/18 22:53:31 miles - * (cproc_setup): - * Correctly leave space at top of stack for account for GNU per-thread - * variables. - * - * Revision 1.2 1994/05/04 19:05:26 mib - * entered into RCS + * Revision 2.7 93/01/14 18:05:15 danner + * Converted file to ANSI C. + * Fixed argument types. + * [92/12/18 pds] * * Revision 2.6 91/07/31 18:37:07 dbg * Undefine cthread_sp macro around function definition. * [91/07/30 17:36:23 dbg] * - * Revision 2.5 91/05/14 17:57:27 mrt - * Correcting copyright - * - * Revision 2.4 91/02/14 14:20:21 mrt - * Changed to new Mach copyright - * [91/02/13 12:20:10 mrt] - * * Revision 2.3 90/06/02 15:13:53 rpd * Added definition of cthread_sp. * [90/06/02 rpd] @@ -78,15 +54,13 @@ */ #ifndef lint -static char rcs_id[] = "$Header: cvs-sans-libpthread/hurd/libthreads/i386/thread.c,v 1.6 2001/12/22 21:02:31 roland Exp $"; +char rcs_id[] = "$Header: cvs-sans-libpthread/hurd/libthreads/i386/thread.c,v 1.7 2002/05/27 02:50:10 roland Exp $"; #endif /* not lint */ -#include "../cthreads.h" -#include "../cthread_internals.h" -#include <strings.h> -#include <mach/mach.h> - +#include <cthreads.h> +#include "cthread_internals.h" +#include <mach.h> /* * Set up the initial state of a MACH thread @@ -94,10 +68,7 @@ static char rcs_id[] = "$Header: cvs-sans-libpthread/hurd/libthreads/i386/thread * when it is resumed. */ void -cproc_setup(child, thread, routine) - register cproc_t child; - int thread; - int routine; +cproc_setup(register cproc_t child, thread_t thread, void (*routine)(cproc_t)) { extern unsigned int __hurd_threadvar_max; /* GNU */ register int *top = (int *) @@ -118,7 +89,7 @@ cproc_setup(child, thread, routine) count = i386_THREAD_STATE_COUNT; MACH_CALL(thread_get_state(thread,i386_THREAD_STATE,(thread_state_t) &state,&count),r); - ts->eip = routine; + ts->eip = (int) routine; *--top = (int) child; /* argument to function */ *--top = 0; /* fake return address */ ts->uesp = (int) top; /* set stack pointer */ @@ -127,12 +98,12 @@ cproc_setup(child, thread, routine) MACH_CALL(thread_set_state(thread,i386_THREAD_STATE,(thread_state_t) &state,i386_THREAD_STATE_COUNT),r); } -#ifdef cthread_sp +#if defined(cthread_sp) #undef cthread_sp #endif int -cthread_sp() +cthread_sp(void) { return (int) __thread_stack_pointer (); } diff --git a/libthreads/mig_support.c b/libthreads/mig_support.c index bb9e6a5e..01e5deb0 100644 --- a/libthreads/mig_support.c +++ b/libthreads/mig_support.c @@ -1,54 +1,68 @@ -/* +/* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1993-1989 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* * HISTORY + * 26-Feb-94 Johannes Helander (jvh) at Helsinki University of Technology + * Added mach_put_reply_port. mig_dealloc_reply_port now takes the + * port as an argument. + * * $Log: mig_support.c,v $ + * Revision 2.8 93/01/24 13:27:14 danner + * Corrrected include of mach/mach.h to mach.h + * [93/01/16 mrt] + * + * Revision 2.7 93/01/14 18:05:37 danner + * Converted file to ANSI C. + * Made argument to mig_init a void * for compatibility with + * mig_init in libmach. + * [92/12/18 pds] + * * Revision 2.6 91/05/14 17:57:41 mrt * Correcting copyright - * + * * Revision 2.5 91/02/14 14:20:30 mrt * Added new Mach copyright * [91/02/13 12:41:26 mrt] - * + * * Revision 2.4 90/08/07 14:31:41 rpd * Removed RCS keyword nonsense. - * + * * Revision 2.3 90/08/07 14:27:48 rpd * When we recycle the global reply port by giving it to the first * cthread, clear the global reply port. This will take care of * someone accidently calling this twice. * [90/08/07 rwd] - * + * * Revision 2.2 90/06/02 15:14:04 rpd * Converted to new IPC. * [90/03/20 20:56:50 rpd] - * + * * Revision 2.1 89/08/03 17:09:50 rwd * Created. - * + * * 18-Jan-89 David Golub (dbg) at Carnegie-Mellon University * Replaced task_data() by thread_reply(). * @@ -75,7 +89,9 @@ */ -#include <mach/mach.h> +#include <mach.h> +#include <mach/mig_support.h> +#include <mach/mach_traps.h> #include <cthreads.h> #include "cthread_internals.h" @@ -88,8 +104,7 @@ private mach_port_t mig_reply_port = MACH_PORT_NULL; * called and again with initial cproc at end of cthread_init. */ void -mig_init(initial) - register cproc_t initial; +mig_init(register void *initial) { if (initial == NO_CPROC) { /* called from mach_init before cthread_init, @@ -101,23 +116,16 @@ mig_init(initial) /* recycle global reply port as this cthread's reply port */ multithreaded = TRUE; - initial->reply_port = mig_reply_port; + ((cproc_t) initial)->reply_port = mig_reply_port; mig_reply_port = MACH_PORT_NULL; } } -void -__mig_init (initial) - register cproc_t initial; -{ - mig_init (initial); -} - /* * Called by mig interface code whenever a reply port is needed. */ mach_port_t -mig_get_reply_port() +mig_get_reply_port(void) { register mach_port_t reply_port; @@ -137,18 +145,13 @@ mig_get_reply_port() return reply_port; } -mach_port_t -__mig_get_reply_port() -{ - return mig_get_reply_port(); -} - /* * Called by mig interface code after a timeout on the reply port. * May also be called by user. */ +/*ARGSUSED*/ void -mig_dealloc_reply_port() +mig_dealloc_reply_port(mach_port_t p) { register mach_port_t reply_port; @@ -169,8 +172,45 @@ mig_dealloc_reply_port() MACH_PORT_RIGHT_RECEIVE, -1); } +/* + * Called by mig interfaces when done with a port. + * Used to provide the same interface as needed when a custom + * allocator is used. + */ + +/*ARGSUSED*/ +void +mig_put_reply_port(mach_port_t port) +{ + /* Do nothing */ +} + +void +__mig_init(register void *initial) +{ + mig_init (initial); +} + +mach_port_t +__mig_get_reply_port(void) +{ + return mig_get_reply_port(); +} + +void +__mig_dealloc_reply_port(mach_port_t p) +{ + mig_dealloc_reply_port(p); +} + +void +__mig_put_reply_port(mach_port_t port) +{ + mig_put_reply_port(port); +} + void -__mig_dealloc_reply_port () +__mig_dealloc_reply_port (void) { mig_dealloc_reply_port (); } diff --git a/libthreads/sync.c b/libthreads/sync.c index e17280aa..d65eb654 100644 --- a/libthreads/sync.c +++ b/libthreads/sync.c @@ -1,6 +1,6 @@ /* * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * Copyright (c) 1992,1991,1990,1989 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its @@ -26,6 +26,10 @@ /* * HISTORY * $Log: sync.c,v $ + * Revision 2.8 93/01/14 18:06:23 danner + * Converted file to ANSI C. + * [92/12/18 pds] + * * Revision 2.7 92/03/06 14:09:59 rpd * Replaced swtch_pri with yield. * [92/03/06 rpd] @@ -69,8 +73,7 @@ int cthread_spin_count=0; void -spin_lock_solid(p) - register spin_lock_t *p; +spin_lock_solid(register spin_lock_t *p) { while (spin_lock_locked(p) || !spin_try_lock(p)) { #ifdef STATISTICS |