diff options
Diffstat (limited to 'libthreads')
-rw-r--r-- | libthreads/ChangeLog | 269 | ||||
-rw-r--r-- | libthreads/Makefile | 23 | ||||
-rw-r--r-- | libthreads/alpha/csw.S | 200 | ||||
-rw-r--r-- | libthreads/alpha/cthreads.h | 61 | ||||
-rw-r--r-- | libthreads/alpha/lock.S | 84 | ||||
-rw-r--r-- | libthreads/alpha/thread.c | 100 | ||||
-rw-r--r-- | libthreads/call.c | 28 | ||||
-rw-r--r-- | libthreads/cancel-cond.c | 4 | ||||
-rw-r--r-- | libthreads/cprocs.c | 325 | ||||
-rw-r--r-- | libthreads/cthread_data.c | 77 | ||||
-rw-r--r-- | libthreads/cthread_internals.h | 177 | ||||
-rw-r--r-- | libthreads/cthreads.c | 196 | ||||
-rw-r--r-- | libthreads/cthreads.h | 412 | ||||
-rw-r--r-- | libthreads/i386/csw.S | 76 | ||||
-rw-r--r-- | libthreads/i386/cthreads.h | 50 | ||||
-rw-r--r-- | libthreads/i386/lock.s | 28 | ||||
-rw-r--r-- | libthreads/i386/thread.c | 105 | ||||
-rw-r--r-- | libthreads/libthreads.map | 27 | ||||
-rw-r--r-- | libthreads/lockfile.c | 65 | ||||
-rw-r--r-- | libthreads/malloc.c | 438 | ||||
-rw-r--r-- | libthreads/mig_support.c | 108 | ||||
-rw-r--r-- | libthreads/options.h | 44 | ||||
-rw-r--r-- | libthreads/rwlock.c | 8 | ||||
-rw-r--r-- | libthreads/rwlock.h | 38 | ||||
-rw-r--r-- | libthreads/stack.c | 118 | ||||
-rw-r--r-- | libthreads/sync.c | 9 |
26 files changed, 1659 insertions, 1411 deletions
diff --git a/libthreads/ChangeLog b/libthreads/ChangeLog deleted file mode 100644 index ebb6a424..00000000 --- a/libthreads/ChangeLog +++ /dev/null @@ -1,269 +0,0 @@ -Sat Jul 20 15:47:24 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (lndist-i386-files): Look for I386SRCS and I386HDRS in - $(srcdir). - -Thu Jun 6 07:29:31 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * malloc.c (more_memory): Use assert_perror instead of MACH_CALL. - "cthread_internals.h": Include removed. - -Thu May 9 11:13:42 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (installhdrs, installhdrsubdir): Install headers using - the generic technique, now that installhdrsubdir is available. - - * rwlock.h: If _RWLOCK_DEFINE_FUNCTIONS is defined, then clear - _EXTERN_INLINE, but *after* header files have been included. - * rwlock.c (_RWLOCK_DEFINE_FUNCTIONS): New macro; use in place of - clearing _EXTERN_INLINE, which conflicts with machine-sp.h. - -Sat May 4 05:33:57 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> - - * cthreads.h [lint] (NEVER): Spurious global variable removed. - [!lint] (NEVER): Useless macro removed. - - * Makefile (SRCS): Add rwlock.c. - (LCLHDRS): Add rwlock.h. - (install): Depend on $(includedir)/rwlock.h. - ($(includedir)/%.h: %.h): New rule. - ($(includedir)/cthreads.h): Target removed, obviated by that rule. - * rwlock.h: Moved to libthreads from libshouldbeinlibc. - (_EXTERN_INLINE): New macro. - Use it for all the inline defns. - * rwlock.c: New file. - -Thu Apr 11 17:55:24 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (CFLAGS): Turn off -Wall. - - * Makefile (VPATH): Fix up for new configure reality. - -Thu Mar 7 15:52:38 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * malloc.c (realloc): Use LOG2_MIN_SIZE. - (LOG2_MIN_SIZE): New macro. - - * malloc.c (realloc): Don't bother allocating a new block if the - new size request fits in the old one and doesn't waste any space. - Only free the old block if we successfully got a new one. - -Wed Mar 6 18:05:57 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * malloc.c [MCHECK] (struct header): New type. - (union header): Only define if !MCHECK. - (HEADER_SIZE, HEADER_NEXT, HEADER_FREE, HEADER_CHECK): New macros. - [MCHECK] (MIN_SIZE): Add correct definition for this case. - (more_memory, malloc, free, realloc): Use above macros, and add - appropiate checks & frobs in MCHECK case. - -Wed Jan 31 20:05:57 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * cancel-cond.c: Add assert to check for signal bug. - -Wed Jan 24 13:38:11 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * cthreads.h: Use prototypes for functions of zero args. - -Sun Dec 10 08:41:36 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * stack.c (addr_range_check, probe_stack): Functions #if 0'd out. - (stack_init): Don't call probe_stack or frob old stack at all. - Default cthread_stack_size to 16 pages if it is zero. - -Wed Dec 6 14:48:37 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * cprocs.c (condition_unimplies): Take address of (*impp)->next in - assignment to IMPP on loop step instruction. - -Wed Oct 4 16:22:27 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * i386/csw.S (JUMPTARGET): New macro, versions for [PIC] and not. - Use it in place of EXT. - * Makefile (csw_pic.o): Bogus braindead target from hell removed. - Bushnell will be shot. - -Fri Sep 22 13:51:22 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * cprocs.c: Include hurd/threadvar.h. - -Sat Sep 16 13:42:02 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile (CPPFLAGS): Variable removed. - (lndist-i386-files): Use $(top_srcdir) in place of $(srcdir). - -Wed Sep 13 15:49:17 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> - - * cthreads.h (CONDITION_INITIALIZER): Provide initial zero for - IMPLICATIONS member. - (condition_init): Bother initializing NAME and IMPLICATIONS members. - -Wed Aug 30 11:10:27 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> - - * cthreads.h (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. - * cprocs.c (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. - - * cthreads.h (hurd_condition_wait): Provide declaration. - -Tue Aug 29 10:48:59 1995 Michael I. Bushnell, p/BSG <mib@duality.gnu.ai.mit.edu> - - * cthread_internals.h (cproc_block): Provide decl. - -Sat Aug 26 14:08:15 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * cancel-cond.c (hurd_condition_wait_cancel): Name changed to - `hurd_condition_wait'. - -Tue Aug 22 19:26:38 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile (SRCS): Add a backslash. - -Mon Aug 21 12:52:38 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile (SRCS): Add cancel-cond.c. - * cancel-cond.c: New file. - -Thu Jul 6 13:39:25 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * Makefile (install): Don't *always* install cthreads.h; do it - only if it's new. - - * Makefile: Removed dependencies that are now automatically - generated. - - * Makefile (csw_pic.o): Provide slightly cheating rule. - -Fri May 12 14:25:35 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * i386/csw.S: Use EXT macro instead of explicit underscores. - * i386/asm.h: File removed; it is installed by libc. - * Makefile (I386HDRS): Variable removed. - ($(OBJS)): Don't depend on i386/asm.h. - - * Makefile (CPPFLAGS): Use $(srcdir) instead of $(hurdsource). - -Wed Apr 12 14:33:06 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * Makefile (lndist, lndist-i386-files): Change $(hurdsource) to - $(srcdir). - ($(hurdsource)/hurd-snap/$(dir)/i386): Likewise. - -Tue Apr 4 17:04:45 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile (CPPFLAGS): Define. - ($(OBJS) rule): Fix typo in target. - (install-cthreads.h): Use $(INSTALL_DATA). - - * cthreads.h (mutex_lock, mutex_unlock): Use __ names for *_solid. - * cprocs.c (mutex_lock_solid, mutex_unlock_solid): Renamed to __*. - (_cthread_mutex_lock_routine, _cthread_mutex_unlock_routine): Variables - removed. - -Fri Jul 22 10:47:51 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu> - - * Makefile: Rewritten in accord with new scheme. - -Tue Jul 19 12:22:01 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * Makefile (generic-sources): Restored malloc.c. - (malloc-sources, malloc-objects): Deleted variables. - (DIST_FILES): Deleted $(malloc-sources) - (all): Deleted libmalloc.a. - (libmalloc.a): Delted target. - ($(hurdinst)/lib/libmalloc.a): Deleted target. - (install): Deleted $(hurdinst)/lib/libmalloc.a. - (clean): Deleted libmalloc.a. - -Tue Jul 5 14:17:28 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * Makefile (SRCS, TAGSHDRS): New variables. - (TAGS): Deleted local definition; now it's in Makeconf. - -Thu May 19 00:54:54 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * cprocs.c (_cthread_mutex_lock_routine, - _cthread_mutex_unlock_routine): New variables. - -Thu May 5 19:33:49 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu) - - * Makefile: (generic-sources): Removed malloc.c. - (malloc-sources, malloc-objects): new variables. - (DIST_FILES): added $(malloc-sources). - (libmalloc.a, $(hurdinst)/lib/libmalloc.a): New targets. - ($(hurdinst)/lib/malloc.o): Deleted target. - (all): added libmalloc.a. - (install): Changed $(hurdinst)/lib/malloc.o to - $(hurdinst)/lib/libmalloc.a - (clean): Added libmaloc.a. - -Thu May 5 04:30:34 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * cthreads.c (cthread_init): Pass STACK instead of P to mig_init. - - * cprocs.c (cproc_create): Pass normal offset value to - cproc_stack_base. Explicitly store CHILD ptr at base of its stack. - - * stack.c (stack_init): Set __hurd_threadvar_stack_mask to find - the lowest address of the stack segment. - [STACK_GROWTH_UP]: Set __hurd_threadvar_stack_offset to - sizeof(ur_cthread_t*). - [! STACK_GROWTH_UP]: Set __hurd_threadvar_stack_offset to the size - of the stack minus space for the cproc_self ptr and thread variables. - - * malloc.c (malloc, free, realloc): Change declarations to - standard types, so as not to conflict with the declarations in - <stdlib.h>. - - * cthread_internals.h: #if 0 out declaration of malloc. - (struct cproc): #if 0 out `reply_port' member; libc implements that. - * cprocs.c (cproc_alloc): #if 0 out initialization of P->reply_port. - - * Makefile (generic-sources): Omit sync.c. libc implements that. - - * cprocs.c (cproc_block): Add __hurd_threadvar_max * sizeof (long - int) to 2nd arg to cproc_stack_base. - - * stack.c: Include <hurd/threadvar.h>. - (__hurd_threadvar_stack_mask, __hurd_threadvar_stack_offset, - __hurd_threadvar_max): Define variables (uninitialized). - (stack_init): Set __hurd_threadvar_stack_mask to cthread_stack_mask. - Set __hurd_threadvar_stack_offset to point past the cproc_self ptr. - Add __hurd_threadvar_max * sizeof (long int) to 2nd arg to - cproc_stack_base. - - * cthreads.h: #if 0 include of <machine/cthreads.h>. - Instead, include <machine-sp.h>. - (cthread_sp): Define using __thread_stack_pointer. - #if 0 out spin_lock definitions. Just include <spin-lock.h> instead. - (struct mutex): Move `held' member to be first in the structure. - -Wed May 4 14:55:15 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu) - - * i386/thread.c: Changed inclusions because we aren't using - -I flags the way CMU's makefiles do. - - * i386/csw.S: Convert comment character to /* */ pairs. - - * Renamed csw.s to csw.S so that GCC knows to run cpp on it. - * Makefile (machine-sources): Change csw.s to csw.S. - -Wed May 4 07:11:46 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) - - * Makefile (GEN_SRCS): Renamed generic-sources. - (I386_SRCS): Replaced with machine-sources, omitting directory. - (SRCS): Renamed sources. Include $(machine-sources) and prepend - $(machine)/ directory name. - (headers): Define variable. - (OBJS): Renamed objects. - (VPATH): Define to $(machine). diff --git a/libthreads/Makefile b/libthreads/Makefile index d915751a..e9fa571b 100644 --- a/libthreads/Makefile +++ b/libthreads/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. +# Copyright (C) 1994,95,96,97,2000,2010 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -15,15 +15,13 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# This is currently i386 specific. XXX - dir := libthreads makemode := library # In GNU mig_support.c, sync.c and machine/lock.s are omitted; that work is # all done in libc. -SRCS := call.c cprocs.c cthread_data.c cthreads.c stack.c malloc.c \ - cancel-cond.c rwlock.c +SRCS := call.c cprocs.c cthread_data.c cthreads.c stack.c \ + cancel-cond.c rwlock.c lockfile.c I386SRCS := i386/csw.S i386/thread.c # In GNU machine/cthreads.h is omitted; that work is done in libc headers. @@ -37,7 +35,7 @@ libname = libthreads installhdrs = cthreads.h rwlock.h installhdrsubdir = . -VPATH += $(srcdir)/$(machine) +VPATH += $(srcdir)/$(asm_syntax) include ../Makeconf @@ -52,3 +50,16 @@ lndist-i386-files: $(top_srcdir)/hurd-snap/$(dir)/i386 $(top_srcdir)/hurd-snap/$(dir)/i386: mkdir $@ + +ifeq ($(VERSIONING),yes) + +# Adding this dependency gets it included in the command line, +# where ld will read it as a linker script. +$(libname).so.$(hurd-version): $(srcdir)/$(libname).map + +lndist: lndist-map-file + +lndist-map-file: $(top_srcdir)/hurd-snap/$(dir) + ln $(addprefix $(srcdir)/,$(libname).map) $< + +endif diff --git a/libthreads/alpha/csw.S b/libthreads/alpha/csw.S new file mode 100644 index 00000000..8c6ae309 --- /dev/null +++ b/libthreads/alpha/csw.S @@ -0,0 +1,200 @@ +/* + * Mach Operating System + * Copyright (c) 1993,1992 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: csw.s,v $ + * Revision 2.3 93/01/19 08:55:56 danner + * Locks are longs now. Put MBs before and after releasing + * locks. + * [93/01/15 af] + * + * Revision 2.2 93/01/14 18:04:23 danner + * Fixed bug in cproc_prepare, it was not setting up + * the PV register properly. Safer GP usage too. + * ANSIfied comments. + * [92/12/22 03:00:50 af] + * + * Created. + * [92/05/31 af] + * + */ +/* + * alpha/csw.s + * + * Context switch and cproc startup for ALPHA COROUTINE implementation. + */ +#include <mach/alpha/asm.h> + + .text + .align 4 + +#define CSW_IMASK \ + IM_S0|IM_S1|IM_S2|IM_S3|IM_S4|IM_S5|IM_S6|IM_RA|IM_GP + +#define ARG_SAVE (6*8) +#define SAVED_S0 (6*8) +#define SAVED_S1 (7*8) +#define SAVED_S2 (8*8) +#define SAVED_S3 (9*8) +#define SAVED_S4 (10*8) +#define SAVED_S5 (11*8) +#define SAVED_S6 (12*8) +#define SAVED_GP (13*8) +#define SAVED_PC (14*8) +#define SAVED_BYTES (15*8) + +/* + * Suspend the current thread and resume the next one. + * + * void + * cproc_switch(cur, next, lock) + * long *cur; + * long *next; + * simple_lock *lock; + */ +LEAF(cproc_switch,3) + subq sp,SAVED_BYTES,sp /* allocate space for registers */ + /* Save them registers */ + stq ra,SAVED_PC(sp) + stq gp,SAVED_GP(sp) + stq s0,SAVED_S0(sp) + stq s1,SAVED_S1(sp) + stq s2,SAVED_S2(sp) + stq s3,SAVED_S3(sp) + stq s4,SAVED_S4(sp) + stq s5,SAVED_S5(sp) + stq s6,SAVED_S6(sp) + + stq sp,0(a0) /* save current sp */ + ldq sp,0(a1) /* restore next sp */ + /* Reload them registers */ + ldq ra,SAVED_PC(sp) + ldq gp,SAVED_GP(sp) + ldq s0,SAVED_S0(sp) + ldq s1,SAVED_S1(sp) + ldq s2,SAVED_S2(sp) + ldq s3,SAVED_S3(sp) + ldq s4,SAVED_S4(sp) + ldq s5,SAVED_S5(sp) + ldq s6,SAVED_S6(sp) + /* return to next thread */ + .set noreorder + mb + stq zero,0(a2) /* clear lock */ + mb + .set reorder + addq sp,SAVED_BYTES,sp + RET + END(cproc_switch) + +/* + * void + * cproc_start_wait(parent_context, child, stackp, lock) + * long *parent_context; + * cproc_t child; + * long stackp; + * simple_lock *lock; + */ +NESTED(cproc_start_wait, 4, SAVED_BYTES, zero, CSW_IMASK, 0) + ldgp gp,0(pv) + subq sp,SAVED_BYTES,sp /* allocate space for registers */ + /* Save parent registers */ + stq ra,SAVED_PC(sp) + stq gp,SAVED_GP(sp) + stq s0,SAVED_S0(sp) + stq s1,SAVED_S1(sp) + stq s2,SAVED_S2(sp) + stq s3,SAVED_S3(sp) + stq s4,SAVED_S4(sp) + stq s5,SAVED_S5(sp) + stq s6,SAVED_S6(sp) + + stq sp,0(a0) /* save parent sp */ + + .set noreorder + mb + stq zero,0(a3) /* release lock */ + mb + .set reorder + + mov a2,sp /* get child sp */ + subq sp,ARG_SAVE,sp /* regsave (sanity) */ + mov a1,a0 + CALL(cproc_waiting) /* cproc_waiting(child) */ + /* + * Control never returns here. + */ + END(cproc_start_wait) + +/* + * void + * cproc_prepare(child, child_context, stack) + * long *child_context; + * long *stack; + */ +LEAF(cproc_prepare,3) + ldgp gp,0(pv) + subq a2,ARG_SAVE,a2 /* cthread_body's fake frame */ + stq a0,0(a2) /* cthread_body(child) */ + subq a2,SAVED_BYTES,a2 /* cproc_switch's ``frame'' */ + stq s0,SAVED_S0(a2) + stq s1,SAVED_S1(a2) + stq s2,SAVED_S2(a2) + stq s3,SAVED_S3(a2) + stq s4,SAVED_S4(a2) + stq s5,SAVED_S5(a2) + stq s6,SAVED_S6(a2) + stq gp,SAVED_GP(a2) + stq a2,0(a1) /* child context */ + lda v0,1f + stq v0,SAVED_PC(a2) + RET + + /* + * The reason we are getting here is to load + * arguments in registers where they are supposed + * to be. The code above only put the argument(s) + * on the stack, now we'll load them. + */ +1: ldgp gp,0(ra) /* we get here from a cswitch */ + lda v0,cthread_body + ldq a0,0(sp) + mov v0,ra + mov ra,pv /* funcall or return, either way */ + RET + END(cproc_prepare) + +/* + * unsigned long + * cthread_sp() + * + * Returns the current stack pointer. + */ + +LEAF(cthread_sp,0) + mov sp, v0 + RET + END(cthread_sp); diff --git a/libthreads/alpha/cthreads.h b/libthreads/alpha/cthreads.h new file mode 100644 index 00000000..f2218f40 --- /dev/null +++ b/libthreads/alpha/cthreads.h @@ -0,0 +1,61 @@ +/* + * Mach Operating System + * Copyright (c) 1993,1992 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: cthreads.h,v $ + * Revision 2.4 93/11/17 19:00:42 dbg + * When compiling with GCC, inline cthread_sp(). + * [93/09/21 af] + * + * Revision 2.3 93/01/19 08:56:02 danner + * Locks are now 64bits. + * [92/12/30 af] + * + * Revision 2.2 93/01/14 18:04:28 danner + * Created. + * [92/05/31 af] + * + */ + +#ifndef _MACHINE_CTHREADS_H_ +#define _MACHINE_CTHREADS_H_ + +typedef long spin_lock_t; +#define SPIN_LOCK_INITIALIZER 0 +#define spin_lock_init(s) *(s)=0 +#define spin_lock_locked(s) (*(s) != 0) + +#if defined(__GNUC__) + +#define cthread_sp() \ + ({ register vm_offset_t _sp__; \ + __asm__("or $31,$30,%0" \ + : "=r" (_sp__) ); \ + _sp__; }) + +#endif /* __GNUC__ */ + +#endif _MACHINE_CTHREADS_H_ diff --git a/libthreads/alpha/lock.S b/libthreads/alpha/lock.S new file mode 100644 index 00000000..657ac1f8 --- /dev/null +++ b/libthreads/alpha/lock.S @@ -0,0 +1,84 @@ +/* + * Mach Operating System + * Copyright (c) 1992 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: lock.s,v $ + * Revision 2.3 93/03/09 10:59:04 danner + * Lost in previous merge: + * Added memory barriers where needed. + * Locks are longs now. + * [93/01/15 af] + * + * Revision 2.2 93/01/14 18:04:31 danner + * Mumble, "try_lock" really means "try_hard_once". + * That is, try hard until you either get it or lose it. + * [92/12/24 af] + * Created a while back. + * [92/12/10 af] + * + */ + +#include <mach/alpha/asm.h> + +/* + The C interface for this function is + + boolean_t + spin_try_lock_sw(m) + long * m; + + The function has a slightly different semantics than TAS: it will + return a boolean value that indicates whether the lock was acquired + or not. If not, we'll presume that the user will retry after some + appropriate delay. + */ + .text + .align 4 + .set noreorder + +LEAF(spin_try_lock,1) + mb + ldq_l t0,0(a0) + or zero,2,v0 /* build lock value */ + bne t0,nope /* already set, forget it */ + stq_c v0,0(a0) /* see if we still had the lock */ + beq v0,yipe /* if we just took an interrupt.. */ + RET /* if v0 != 0 then we got it */ +nope: + mov zero,v0 /* failed to acquire lock */ + RET +yipe: br zero,spin_try_lock /* I love branch predictions.. */ + + END(spin_try_lock) + +LEAF(spin_unlock,1) + mb /* but this might be needed.. */ + stq zero,0(a0) /* no need for interlocks (sec 10.5.2) */ + mb /* but this might be needed.. */ + RET + + END(spin_unlock) + diff --git a/libthreads/alpha/thread.c b/libthreads/alpha/thread.c new file mode 100644 index 00000000..db2cb0c8 --- /dev/null +++ b/libthreads/alpha/thread.c @@ -0,0 +1,100 @@ +/* + * Mach Operating System + * Copyright (c) 1992 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: thread.c,v $ + * Revision 1.1 2002/05/27 02:13:47 roland + * 2002-05-26 Roland McGrath <roland@frob.com> + * + * * alpha/cthreads.h, alpha/thread.c, alpha/csw.S, alpha/lock.S: + * New files, verbatim from CMU release MK83a user/threads/alpha. + * + * Revision 2.3 93/02/01 09:56:49 danner + * mach/mach.h -> mach.h + * [93/01/28 danner] + * + * Revision 2.2 93/01/14 18:04:35 danner + * Created. + * [92/05/31 af] + * + */ +/* + * alpha/thread.c + * + * Cproc startup for ALPHA Cthreads implementation. + */ + + +#include <cthreads.h> +#include "cthread_internals.h" + +#include <mach.h> + +#if 0 +/* + * C library imports: + */ +extern bzero(); +#endif + +/* + * Set up the initial state of a MACH thread + * so that it will invoke routine(child) + * when it is resumed. + */ +#warning TLS support not implemented +void +cproc_setup( + register cproc_t child, + thread_t thread, + tcbhead_t *tcb, + void (*routine)(cproc_t)) +{ + register integer_t *top; + struct alpha_thread_state state; + register struct alpha_thread_state *ts; + kern_return_t r; + + /* + * Set up ALPHA call frame and registers. + */ + ts = &state; + bzero((char *) ts, sizeof(struct alpha_thread_state)); + + top = (integer_t *) (child->stack_base + child->stack_size); + + /* + * Set pc & pv to procedure entry, pass one arg in register, + * allocate room for 6 regsave on the stack frame (sanity). + */ + ts->pc = (natural_t) routine; + ts->r27 = (natural_t) routine; + ts->r16 = (integer_t) child; + ts->r30 = (integer_t) (top - 6); /* see ARG_SAVE in csw.s */ + + + MACH_CALL(thread_set_state(thread,ALPHA_THREAD_STATE,(thread_state_t) &state,ALPHA_THREAD_STATE_COUNT),r); +} diff --git a/libthreads/call.c b/libthreads/call.c index 26efc8fc..85bd4f38 100644 --- a/libthreads/call.c +++ b/libthreads/call.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: 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 * @@ -42,40 +46,34 @@ #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/cancel-cond.c b/libthreads/cancel-cond.c index b7780d03..b7793f85 100644 --- a/libthreads/cancel-cond.c +++ b/libthreads/cancel-cond.c @@ -77,7 +77,7 @@ hurd_condition_wait (condition_t c, mutex_t m) #ifdef WAIT_DEBUG p->waiting_for = (char *)c; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ mutex_unlock (m); @@ -94,7 +94,7 @@ hurd_condition_wait (condition_t c, mutex_t m) #ifdef WAIT_DEBUG p->waiting_for = (char *)0; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ } spin_lock (&ss->lock); diff --git a/libthreads/cprocs.c b/libthreads/cprocs.c index 71a6a3ad..7f63fc0d 100644 --- a/libthreads/cprocs.c +++ b/libthreads/cprocs.c @@ -1,120 +1,132 @@ -/* +/* * 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-Oct-94 Johannes Helander (jvh) Helsinki University of Technology + * Set the wait_type field. + * * $Log: cprocs.c,v $ - * Revision 1.7 1995/09/22 17:51:10 roland - * Include hurd/threadvar.h. + * Revision 1.16 2002/05/27 02:50:10 roland + * 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. * - * Revision 1.6 1995/08/30 15:57:47 mib - * Repair typos. + * Revision 2.18 93/03/09 10:59:10 danner + * Lint. + * [93/03/06 af] * - * 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 2.17 93/01/19 08:55:44 danner + * Added missing spin_lock_t type from cproc_list_lock decl. + * [92/12/30 af] * - * 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. * [92/03/06 rpd] - * + * * Revision 2.14 91/08/28 11:19:16 jsb * Fixed the loop in cproc_fork_child that frees cprocs. * [91/08/23 rpd] - * + * * Revision 2.13 91/07/31 18:33:04 dbg * Fix some more bad types. Ints are NOT pointers. - * + * * Fix argument type mismatch in cproc_create. * [91/07/30 17:32:59 dbg] - * + * * Revision 2.12 91/05/14 17:56:11 mrt * Correcting copyright - * + * * Revision 2.11 91/02/14 14:19:26 mrt * Added new Mach copyright * [91/02/13 12:40:50 mrt] - * + * * Revision 2.10 90/11/05 14:36:41 rpd * Added cproc_fork_{prepare,parent,child}. * [90/11/02 rwd] - * + * * Fix for positive stack growth. * [90/11/01 rwd] - * + * * Add spin_lock_t. * [90/10/31 rwd] - * + * * Revision 2.9 90/10/12 13:07:12 rpd * Fix type * [90/10/10 15:09:59 rwd] - * + * * Comment code. * [90/10/02 rwd] - * + * * Revision 2.8 90/09/09 14:34:44 rpd * Remove special mutex. Remove thread_calls and debug_mutex * [90/08/24 rwd] * Fix up old call to cthread_msg_busy to new format. * [90/08/22 rwd] - * + * * Revision 2.7 90/08/06 15:09:17 rwd * Fixed arguments to cthread_mach_msg. * [90/06/26 rwd] * Add additional STATISTICS. * [90/06/07 rwd] - * + * * Attempt to reduce number of times a cthread is released to to a * msg_receive by adding min/max instead of single number to * cthread_msg calls. * [90/06/06 rwd] - * + * * Revision 2.6 90/06/02 15:13:36 rpd * Converted to new IPC. * [90/03/20 20:46:16 rpd] - * + * * Revision 2.5 90/05/29 18:40:11 rwd * Don't incr special field until the mutex grab is successful. * [90/05/09 rwd] - * + * * Revision 2.4 90/03/14 21:12:02 rwd * Added WAIT_DEBUG code for deadlock debugging. * [90/03/01 rwd] * Insert cprocs in cproc_list as allocated. * [90/03/01 10:20:16 rwd] - * + * * Revision 2.3 90/01/19 14:36:57 rwd * Make cthread_msg_busy only release new thread if this is still * busy. Ie don't release two on back to back calls. @@ -126,7 +138,7 @@ * Change cproc_self pointer to top of stack. Now need to change * the stack of the first thread. * [89/12/12 rwd] - * + * * Revision 2.2 89/12/08 19:53:13 rwd * Added CPROC_CONDWAIT state to deal with lock held * across mutex_unlock problem. @@ -134,7 +146,7 @@ * Changed mutexes to not hand off. MUTEX_EXTRA conditional is * now obsolete. * [89/11/27 rwd] - * + * * Add MUTEX_EXTRA code for extra kernel threads to serve special * mutexes in time of need. * [89/11/25 rwd] @@ -144,15 +156,15 @@ * macro which tries the spin_lock before making a subroutine call. * Mutex_unlock is now a macro with mutex_unlock_solid for worst case. * [89/11/13 rwd] - * + * * Rewrite most to merge coroutine and thread implementation. * New routines are cthread_set_kernel_limit, cthread_kernel_limit, * cthread_wire, cthread_unwire, and cthread_receive. * [89/10/23 rwd] - * + * * Revision 2.1 89/08/03 17:07:10 rwd * Created. - * + * * 11-Apr-89 David Golub (dbg) at Carnegie-Mellon University * Made condition_yield loop break if swtch_pri returns TRUE (in * case we fix it). @@ -208,7 +220,7 @@ * to eliminate dependency on cproc layout. */ /* - * File: cprocs.c + * File: cprocs.c * Author: Eric Cooper, Carnegie Mellon University * Date: Aug, 1987 * @@ -221,15 +233,7 @@ #include "cthread_internals.h" #include <mach/message.h> #include <hurd/threadvar.h> /* GNU */ - -/* - * 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(); +#include <assert.h> /* * Port_entry's are used by cthread_mach_msg to store information @@ -280,10 +284,10 @@ int cthread_no_mutex = 0; /* total number times woken to get mutex and couldn't */ private spin_lock_t mutex_count_lock = SPIN_LOCK_INITIALIZER; /* lock for above */ -#endif STATISTICS +#endif /* STATISTICS */ cproc_t cproc_list = NO_CPROC; /* list of all cprocs */ -private cproc_list_lock = SPIN_LOCK_INITIALIZER; +private spin_lock_t cproc_list_lock = SPIN_LOCK_INITIALIZER; /* lock for above */ private int cprocs_started = FALSE; /* initialized? */ private struct cthread_queue ready = QUEUE_INITIALIZER; @@ -311,8 +315,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; } @@ -323,8 +327,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; } @@ -333,47 +337,28 @@ 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; - /* - * A wired thread has a port associated with it for all - * of its wait/block cases. We also prebuild a wakeup - * message. - */ - - if (p->wired == MACH_PORT_NULL) { - MACH_CALL(mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - &p->wired), r); - MACH_CALL(mach_port_insert_right(mach_task_self(), - p->wired, p->wired, - MACH_MSG_TYPE_MAKE_SEND), r); - p->msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); - p->msg.msgh_size = 0; /* initialized in call */ - p->msg.msgh_remote_port = p->wired; - p->msg.msgh_local_port = MACH_PORT_NULL; - p->msg.msgh_kind = MACH_MSGH_KIND_NORMAL; - p->msg.msgh_id = 0; -#ifdef STATISTICS - spin_lock(&wired_lock); - cthread_wired++; - spin_unlock(&wired_lock); -#endif STATISTICS - } + /* In GNU, we wire all threads on creation (in cproc_alloc). */ + assert (p->wired != MACH_PORT_NULL); } /* * Unwire a cthread. Deallocate its wait port. */ -void cthread_unwire() +void +cthread_unwire(void) { register cproc_t p = cproc_self(); - kern_return_t r; + /* This is bad juju in GNU, where all cthreads must be wired. */ + abort(); +#if 0 if (p->wired != MACH_PORT_NULL) { MACH_CALL(mach_port_mod_refs(mach_task_self(), p->wired, MACH_PORT_RIGHT_SEND, -1), r); @@ -384,14 +369,16 @@ void cthread_unwire() spin_lock(&wired_lock); cthread_wired--; spin_unlock(&wired_lock); -#endif STATISTICS +#endif /* STATISTICS */ } +#endif } private cproc_t -cproc_alloc() +cproc_alloc(void) { register cproc_t p = (cproc_t) malloc(sizeof(struct cproc)); + kern_return_t r; p->incarnation = NO_CTHREAD; #if 0 @@ -400,9 +387,31 @@ cproc_alloc() #endif spin_lock_init(&p->lock); - p->wired = MACH_PORT_NULL; p->state = CPROC_RUNNING; p->busy = 0; + + /* + * In GNU, every cthread must be wired. So we just + * initialize P->wired on creation. + * + * A wired thread has a port associated with it for all + * of its wait/block cases. We also prebuild a wakeup + * message. + */ + + MACH_CALL(mach_port_allocate(mach_task_self(), + MACH_PORT_RIGHT_RECEIVE, + &p->wired), r); + MACH_CALL(mach_port_insert_right(mach_task_self(), + p->wired, p->wired, + MACH_MSG_TYPE_MAKE_SEND), r); + p->msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); + p->msg.msgh_size = 0; /* initialized in call */ + p->msg.msgh_remote_port = p->wired; + p->msg.msgh_local_port = MACH_PORT_NULL; + p->msg.msgh_kind = MACH_MSGH_KIND_NORMAL; + p->msg.msgh_id = 0; + spin_lock(&cproc_list_lock); p->list = cproc_list; cproc_list = p; @@ -416,7 +425,7 @@ cproc_alloc() */ vm_offset_t -cproc_init() +cproc_init(void) { kern_return_t r; @@ -453,9 +462,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; @@ -469,7 +476,7 @@ private int cproc_ready(p, preq) mach_error("mach_msg", r); exit(1); } -#endif CHECK_STATUS +#endif /* CHECK_STATUS */ return TRUE; } spin_lock(&p->lock); /* is it ready to be queued? It @@ -497,7 +504,7 @@ private int cproc_ready(p, preq) } #ifdef STATISTICS cthread_ready++; -#endif STATISTICS +#endif /* STATISTICS */ ready_count++; if ((s->state & CPROC_CONDWAIT) && !(s->wired)) { @@ -523,7 +530,7 @@ private int cproc_ready(p, preq) mach_error("mach_msg", r); exit(1); } -#endif CHECK_STATUS +#endif /* CHECK_STATUS */ return TRUE; } spin_unlock(&ready_lock); @@ -536,8 +543,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; @@ -548,7 +554,7 @@ cproc_waiting(p) cthread_waiting++; cthread_waiters++; spin_unlock(&ready_lock); -#endif STATISTICS +#endif /* STATISTICS */ for (;;) { MACH_CALL(mach_msg(&msg, MACH_RCV_MSG, 0, sizeof msg, wait_port, @@ -560,14 +566,14 @@ cproc_waiting(p) ready_count++; #ifdef STATISTICS cthread_none++; -#endif STATISTICS +#endif /* STATISTICS */ spin_unlock(&ready_lock); - } + } #ifdef STATISTICS cthread_ready--; cthread_running++; cthread_waiting--; -#endif STATISTICS +#endif /* STATISTICS */ spin_unlock(&ready_lock); spin_lock(&new->lock); new->state = CPROC_RUNNING; @@ -584,8 +590,8 @@ cproc_waiting(p) * */ -cproc_t -cproc_waiter() +private cproc_t +cproc_waiter(void) { register cproc_t waiter; @@ -599,7 +605,7 @@ cproc_waiter() spin_lock(&waiters_lock); cthread_wait_stacks++; spin_unlock(&waiters_lock); -#endif STATISTICS +#endif /* STATISTICS */ waiter = cproc_alloc(); MACH_CALL(vm_allocate(mach_task_self(), &base, cthread_wait_stack_size, TRUE), r); @@ -617,7 +623,8 @@ cproc_waiter() * You must hold cproc_self()->lock when called. */ -cproc_block() +void +cproc_block(void) { extern unsigned int __hurd_threadvar_max; /* GNU */ register cproc_t waiter, new, p = cproc_self(); @@ -638,13 +645,13 @@ cproc_block() spin_lock(&ready_lock); #ifdef STATISTICS cthread_blocked++; -#endif STATISTICS +#endif /* STATISTICS */ cthread_queue_deq(&ready, cproc_t, new); if (new) { #ifdef STATISTICS cthread_ready--; cthread_switches++; -#endif STATISTICS +#endif /* STATISTICS */ ready_count--; spin_unlock(&ready_lock); spin_lock(&p->lock); @@ -655,7 +662,7 @@ cproc_block() cthread_wakeup++; cthread_switches--; spin_unlock(&ready_lock); -#endif STATISTICS +#endif /* STATISTICS */ cproc_ready(new, 1); /* requeue at head were it was */ } else { p->state = CPROC_BLOCKED; @@ -668,7 +675,7 @@ cproc_block() wait_count++; #ifdef STATISTICS cthread_running--; -#endif STATISTICS +#endif /* STATISTICS */ spin_unlock(&ready_lock); waiter = cproc_waiter(); spin_lock(&p->lock); @@ -679,7 +686,7 @@ cproc_block() #ifdef STATISTICS cthread_running++; cthread_wakeup++; -#endif STATISTICS +#endif /* STATISTICS */ spin_unlock(&ready_lock); spin_lock(&waiters_lock); cthread_queue_preq(&waiters, waiter); @@ -689,7 +696,7 @@ cproc_block() spin_lock(&waiter->lock); /* in case still switching */ spin_unlock(&waiter->lock); cproc_start_wait - (&p->context, waiter, + (&p->context, waiter, cproc_stack_base(waiter, sizeof(ur_cthread_t *) + /* Account for GNU per-thread @@ -705,7 +712,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; @@ -718,16 +725,17 @@ cproc_create() spin_lock(&n_kern_lock); if (cthread_max_kernel_threads == 0 || cthread_kernel_threads < cthread_max_kernel_threads) { + tcbhead_t *tcb = _dl_allocate_tls(NULL); cthread_kernel_threads++; spin_unlock(&n_kern_lock); MACH_CALL(thread_create(mach_task_self(), &n), r); - cproc_setup(child, n, cthread_body); /* machine dependent */ + cproc_setup(child, n, tcb, cthread_body); /* machine dependent */ MACH_CALL(thread_resume(n), r); #ifdef STATISTICS spin_lock(&ready_lock); cthread_running++; spin_unlock(&ready_lock); -#endif STATISTICS +#endif /* STATISTICS */ } else { vm_offset_t stack; spin_unlock(&n_kern_lock); @@ -746,18 +754,16 @@ cproc_create() variables. */ __hurd_threadvar_max * sizeof (long int)); - cproc_prepare(child, &child->context, stack); + cproc_prepare(child, &child->context, stack, &cthread_body); /* Set up the cproc_self ptr at the base of CHILD's stack. */ - ur_cthread_ptr(stack) = child; + ur_cthread_ptr(stack) = (ur_cthread_t) child; cproc_ready(child,0); } return child; } 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(); @@ -768,7 +774,7 @@ condition_wait(c, m) spin_unlock(&c->lock); #ifdef WAIT_DEBUG p->waiting_for = (char *)c; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ mutex_unlock(m); @@ -783,7 +789,7 @@ condition_wait(c, m) #ifdef WAIT_DEBUG p->waiting_for = (char *)0; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ /* * Re-acquire the mutex and return. @@ -798,7 +804,7 @@ void condition_implies (condition_t implicator, condition_t implicatand) { struct cond_imp *imp; - + imp = malloc (sizeof (struct cond_imp)); imp->implicatand = implicatand; imp->next = implicator->implications; @@ -811,7 +817,7 @@ void condition_unimplies (condition_t implicator, condition_t implicatand) { struct cond_imp **impp; - + for (impp = &implicator->implications; *impp; impp = &(*impp)->next) { if ((*impp)->implicatand == implicatand) @@ -827,8 +833,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; @@ -849,8 +854,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; @@ -881,7 +885,7 @@ cond_broadcast(c) } void -cthread_yield() +cthread_yield(void) { register cproc_t new, p = cproc_self(); @@ -892,7 +896,7 @@ cthread_yield() spin_lock(&ready_lock); #ifdef STATISTICS cthread_yields++; -#endif STATISTICS +#endif /* STATISTICS */ cthread_queue_deq(&ready, cproc_t, new); if (new) { cthread_queue_enq(&ready, p); @@ -923,7 +927,7 @@ __mutex_lock_solid(void *ptr) #ifdef WAIT_DEBUG p->waiting_for = (char *)m; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ while (1) { spin_lock(&m->lock); if (cthread_queue_head(&m->queue, cproc_t) == NO_CPROC) { @@ -937,7 +941,7 @@ __mutex_lock_solid(void *ptr) spin_unlock(&m->lock); #ifdef WAIT_DEBUG p->waiting_for = (char *)0; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ return; } else { if (!queued) cthread_queue_enq(&m->queue, p); @@ -947,14 +951,14 @@ __mutex_lock_solid(void *ptr) if (spin_try_lock(&m->held)) { #ifdef WAIT_DEBUG p->waiting_for = (char *)0; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ return; } #ifdef STATISTICS spin_lock(&mutex_count_lock); cthread_no_mutex++; spin_unlock(&mutex_count_lock); -#endif STATISTICS +#endif /* STATISTICS */ } } } @@ -990,8 +994,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; @@ -1014,8 +1018,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(); @@ -1036,7 +1040,7 @@ cthread_msg_busy(port, min, max) spin_lock(&port_lock); cthread_rnone++; spin_unlock(&port_lock); -#endif STATISTICS +#endif /* STATISTICS */ } } else { port_entry->held--; @@ -1046,8 +1050,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; @@ -1058,24 +1062,18 @@ mach_port_t port; spin_lock(&port_entry->lock); if (port_entry->held < port_entry->max) { port_entry->held++; - p->busy = (int)port_entry; + p->busy = port_entry; } spin_unlock(&port_entry->lock); } } 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(); @@ -1105,7 +1103,7 @@ cthread_mach_msg(header, option, spin_unlock(&port_entry->lock); #ifdef WAIT_DEBUG p->waiting_for = (char *)port_entry; -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ cproc_block(); } else { port_entry->held++; @@ -1120,8 +1118,8 @@ cthread_mach_msg(header, option, } #ifdef WAIT_DEBUG p->waiting_for = (char *)0; -#endif WAIT_DEBUG - p->busy = (int)port_entry; +#endif /* WAIT_DEBUG */ + p->busy = port_entry; if ((option & MACH_SEND_MSG) && !sent) { r = mach_msg(header, option, send_size, rcv_size, rcv_name, @@ -1134,7 +1132,8 @@ cthread_mach_msg(header, option, return r; } -cproc_fork_prepare() +void +cproc_fork_prepare(void) { register cproc_t p = cproc_self(); @@ -1143,7 +1142,8 @@ cproc_fork_prepare() spin_lock(&cproc_list_lock); } -cproc_fork_parent() +void +cproc_fork_parent(void) { register cproc_t p = cproc_self(); @@ -1152,7 +1152,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; @@ -1180,7 +1181,7 @@ cproc_fork_child() cthread_switches = 0; cthread_no_mutex = 0; spin_lock_init(&mutex_count_lock); -#endif STATISTICS +#endif /* STATISTICS */ for(l=cproc_list;l!=NO_CPROC;l=m) { m=l->next; diff --git a/libthreads/cthread_data.c b/libthreads/cthread_data.c index 0814130d..02e6fa82 100644 --- a/libthreads/cthread_data.c +++ b/libthreads/cthread_data.c @@ -1,12 +1,21 @@ /* * 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 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). @@ -26,23 +35,23 @@ * [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 */ @@ -58,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); @@ -80,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); @@ -104,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 { /* @@ -125,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; @@ -141,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; @@ -159,6 +165,7 @@ any_t x; return(cthread_setspecific(CTHREAD_KEY_RESERVED, x)); else { ASSERT(t == self); + return(-1); } } @@ -169,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) { @@ -183,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 c3aa8050..81e3b91c 100644 --- a/libthreads/cthread_internals.h +++ b/libthreads/cthread_internals.h @@ -1,79 +1,112 @@ -/* +/* * 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 + * 26-Oct-94 Johannes Helander (jvh) Helsinki University of Technology + * Defined WAIT_DEBUG and initialized wait_enum + * * $Log: cthread_internals.h,v $ - * Revision 1.2 1994/05/05 10:58:01 roland - * entered into RCS + * Revision 1.6 2002/05/27 02:50:10 roland + * 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. + * + * 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 2.16 93/05/10 17:51:23 rvb + * Flush stdlib + * [93/05/05 09:12:29 rvb] + * + * 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. * [92/08/02 jfriedl] - * + * * Revision 2.13 92/03/06 14:09:24 rpd * Added yield, defined using thread_switch. * [92/03/06 rpd] - * + * * Revision 2.12 92/03/01 00:40:23 rpd * Removed exit declaration. It conflicted with the real thing. * [92/02/29 rpd] - * + * * Revision 2.11 91/08/28 11:19:23 jsb * Fixed MACH_CALL to allow multi-line expressions. * [91/08/23 rpd] - * + * * Revision 2.10 91/07/31 18:33:33 dbg * Protect against redefinition of ASSERT. * [91/07/30 17:33:21 dbg] - * + * * Revision 2.9 91/05/14 17:56:24 mrt * Correcting copyright - * + * * Revision 2.8 91/02/14 14:19:42 mrt * Added new Mach copyright * [91/02/13 12:41:02 mrt] - * + * * Revision 2.7 90/11/05 14:36:55 rpd * Added spin_lock_t. * [90/10/31 rwd] - * + * * Revision 2.6 90/09/09 14:34:51 rpd * Remove special field. * [90/08/24 rwd] - * + * * Revision 2.5 90/06/02 15:13:44 rpd * Converted to new IPC. * [90/03/20 20:52:47 rpd] - * + * * Revision 2.4 90/03/14 21:12:11 rwd * Added waiting_for field for debugging deadlocks. * [90/03/01 rwd] * Added list field to keep a master list of all cprocs. * [90/03/01 rwd] - * + * * Revision 2.3 90/01/19 14:37:08 rwd * Keep track of real thread for use in thread_* substitutes. * Add CPROC_ARUN for about to run and CPROC_HOLD to avoid holding @@ -82,7 +115,7 @@ * Add busy field to be used by cthread_msg calls to make sure we * have the right number of blocked kernel threads. * [89/12/21 rwd] - * + * * Revision 2.2 89/12/08 19:53:28 rwd * Added CPROC_CONDWAIT state * [89/11/28 rwd] @@ -101,7 +134,7 @@ * basically a merge of coroutine and thread. Added * cthread_receivce call for use by servers. * [89/10/23 rwd] - * + * */ /* * cthread_internals.h @@ -128,6 +161,14 @@ # endif #endif +/* Type of the TCB. */ +typedef struct +{ + void *tcb; /* Points to this structure. */ + void *dtv; /* Vector of pointers to TLS data. */ + thread_t self; /* This thread's control port. */ +} tcbhead_t; + /* * Low-level thread implementation. * This structure must agree with struct ur_cthread in cthreads.h @@ -139,14 +180,14 @@ typedef struct cproc { struct cproc *list; /* for master cproc list */ #ifdef WAIT_DEBUG volatile char *waiting_for; /* address of mutex/cond waiting for */ -#endif WAIT_DEBUG +#endif /* WAIT_DEBUG */ #if 0 /* This is not needed in GNU; libc handles it. */ 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 @@ -155,19 +196,17 @@ typedef struct cproc { #define CPROC_CONDWAIT 4 mach_port_t wired; /* is cthread wired to kernel thread */ - int busy; /* used with cthread_msg calls */ + void *busy; /* used with cthread_msg calls */ 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. */ /* @@ -190,9 +229,9 @@ extern void mach_error(); quit(1, "error in %s at %d: %s\n", __FILE__, __LINE__, \ mach_error_string(ret)); \ } else -#else CHECK_STATUS +#else /* CHECK_STATUS */ #define MACH_CALL(expr, ret) (ret) = (expr) -#endif CHECK_STATUS +#endif /* CHECK_STATUS */ #define private static #ifndef ASSERT @@ -207,3 +246,79 @@ 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 void cproc_block(void); + +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, + tcbhead_t *tcb, void (*_routine)(cproc_t)); + + +/* From glibc. */ + +/* Dynamic linker TLS allocation. */ +extern void *_dl_allocate_tls(void *); diff --git a/libthreads/cthreads.c b/libthreads/cthreads.c index d45a02b4..aef20bed 100644 --- a/libthreads/cthreads.c +++ b/libthreads/cthreads.c @@ -1,78 +1,125 @@ -/* +/* * 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: cthreads.c,v $ + * 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++. + * + * $Log: cthreads.c,v $ + * Revision 1.15 2002/07/31 02:35:14 marcus + * Add comment to last change, for the benefit of the next merge :) + * + * Revision 1.14 2002/07/31 02:20:44 marcus + * 2002-07-29 Marcus Brinkmann <marcus@gnu.org> + * + * * cthreads.c (cthread_init): Move cthread_alloc call before + * cproc_init call (lost in merge). + * + * Revision 1.13 2002/05/28 23:55:55 roland + * 2002-05-28 Roland McGrath <roland@frob.com> + * + * * cthreads.c (cthread_fork_prepare, cthread_fork_parent, + * cthread_fork_child): Don't call malloc_fork_* (lost in merge). + * + * Revision 1.12 2002/05/27 02:50:10 roland + * 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. + * + * 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 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] + * + * 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. * [92/05/11 14:41:08 cmaeda] - * + * * Revision 2.10 91/08/28 11:19:26 jsb * Fixed mig_init initialization in cthread_fork_child. * [91/08/23 rpd] - * + * * Revision 2.9 91/07/31 18:34:23 dbg * Fix bad self-pointer reference. - * + * * Don't declare _setjmp and _longjmp; they are included by * cthreads.h. * [91/07/30 17:33:50 dbg] - * + * * Revision 2.8 91/05/14 17:56:31 mrt * Correcting copyright - * + * * Revision 2.7 91/02/14 14:19:47 mrt * Added new Mach copyright * [91/02/13 12:41:07 mrt] - * + * * Revision 2.6 90/11/05 14:37:03 rpd * Added cthread_fork_{prepare,parent,child}. * [90/11/02 rwd] - * + * * Add spin_lock_t. * [90/10/31 rwd] - * + * * Revision 2.5 90/08/07 14:30:58 rpd * Removed RCS keyword nonsense. - * + * * Revision 2.4 90/06/02 15:13:49 rpd * Converted to new IPC. * [90/03/20 20:56:44 rpd] - * + * * Revision 2.3 90/01/19 14:37:12 rwd * Make cthread_init return pointer to new stack. * [89/12/18 19:17:45 rwd] - * + * * Revision 2.2 89/12/08 19:53:37 rwd * Change cproc and cthread counters to globals with better names. * [89/11/02 rwd] - * + * * Revision 2.1 89/08/03 17:09:34 rwd * Created. - * + * * * 31-Dec-87 Eric Cooper (ecc) at Carnegie Mellon University * Changed cthread_exit() logic for the case of the main thread, @@ -101,22 +148,12 @@ */ #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: - */ +#ifdef HAVE_USELOCALE +# include <locale.h> +#endif /* * Thread status bits. @@ -125,9 +162,9 @@ extern void mig_init(); #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; @@ -143,9 +180,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; @@ -177,8 +212,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; @@ -186,8 +220,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; @@ -196,9 +230,13 @@ cthread_init() if (cthreads_started) return 0; + + /* cthread_alloc must be called before cproc_init, because + malloc is not usable between initializing the new stack and + switching to it. */ + t = cthread_alloc((cthread_fn_t) 0, (any_t) 0); stack = cproc_init(); cthread_cprocs = 1; - t = cthread_alloc((cthread_fn_t) 0, (any_t) 0); #ifdef cthread_md_init cthread_md_init(); @@ -224,16 +262,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; @@ -251,10 +288,15 @@ cthread_body(self) */ mutex_unlock(&cthread_lock); cthread_assoc(self, t); /* assume thread's identity */ - if (_setjmp(t->catch) == 0) { /* catch for cthread_exit() */ + if (_setjmp(t->catch_exit) == 0) { /* catch for cthread_exit() */ /* * Execute the fork request. */ +#ifdef HAVE_USELOCALE + /* A fresh thread needs to be bound to the + global locale. */ + uselocale (LC_GLOBAL_LOCALE); +#endif t->result = (*(t->func))(t->arg); } /* @@ -286,9 +328,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; @@ -320,11 +360,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); @@ -338,21 +377,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) result); + exit((int) (integer_t) result); } else { - _longjmp(t->catch, TRUE); + _longjmp(t->catch_exit, TRUE); } } @@ -363,64 +405,58 @@ 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; cproc_fork_child(); - malloc_fork_child(); mutex_unlock(&cthread_lock); spin_unlock(&free_lock); condition_init(&cthread_needed); diff --git a/libthreads/cthreads.h b/libthreads/cthreads.h index 601d3984..d937dcca 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,35 +25,79 @@ */ /* * HISTORY - * $Log: cthreads.h,v $ - * 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. + * 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++. * - * Revision 1.7 1995/07/18 17:15:51 mib - * Reverse previous change. + * 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. * - * 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 + * $Log: cthreads.h,v $ + * Revision 1.19 2002/05/28 23:55:58 roland + * 2002-05-28 Roland McGrath <roland@frob.com> + * + * * cthreads.h (hurd_condition_wait, condition_implies, + * condition_unimplies): Restore decls lost in merge. + * (mutex_clear): Define as mutex_init instead of bogon (lost in merge). + * + * Revision 1.18 2002/05/27 02:50:10 roland + * 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. + * + * 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>: @@ -193,62 +237,49 @@ #ifndef _CTHREADS_ #define _CTHREADS_ 1 -/* MIB XXX */ -#define CTHREAD_DATA - #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() ((int) __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; - -#endif /* not (c_plusplus || __STDC__) */ +#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 -#include <mach/mach.h> -#include <mach/machine/vm_param.h> +typedef void *any_t; /* XXX - obsolete, should be deleted. */ -#ifndef TRUE +#if defined(TRUE) +#else /* not defined(TRUE) */ #define TRUE 1 #define FALSE 0 -#endif /* TRUE */ - -#ifndef MACRO_BEGIN - -#define MACRO_BEGIN do { -#define MACRO_END } while (0) +#endif -#endif MACRO_BEGIN +/* Enable mutex holder debugging */ +/* #define WAIT_DEBUG */ +/* Record function name instead of thread pointer */ +/* #define WAIT_FUNC_DEBUG */ /* * 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. @@ -268,7 +299,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 \ @@ -300,7 +331,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); \ } \ @@ -317,20 +348,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. */ @@ -344,12 +379,32 @@ 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. */ +#ifdef WAIT_FUNC_DEBUG + const char *fname; +#else /* WAIT_FUNC_DEBUG */ + struct cthread *holder; +#endif /* WAIT_FUNC_DEBUG */ } *mutex_t; +#ifdef WAIT_DEBUG +#ifdef WAIT_FUNC_DEBUG +#define WAIT_CLEAR_DEBUG(m) (m)->fname = 0 +#define WAIT_SET_DEBUG(m) (m)->fname = __FUNCTION__ +#else /* WAIT_FUNC_DEBUG */ +#define WAIT_CLEAR_DEBUG(m) (m)->holder = 0 +#define WAIT_SET_DEBUG(m) (m)->holder = cthread_self() +#endif /* WAIT_FUNC_DEBUG */ +#else /* WAIT_DEBUG */ +#define WAIT_CLEAR_DEBUG(m) (void) 0 +#define WAIT_SET_DEBUG(m) (void) 0 +#endif /* WAIT_DEBUG */ + /* 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) \ @@ -357,37 +412,36 @@ typedef struct mutex { spin_lock_init(&(m)->lock); \ cthread_queue_init(&(m)->queue); \ spin_lock_init(&(m)->held); \ + WAIT_CLEAR_DEBUG(m); \ MACRO_END #define mutex_set_name(m, x) ((m)->name = (x)) #define mutex_name(m) ((m)->name != 0 ? (m)->name : "?") -#define mutex_clear(m) /* nop */??? -#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) mutex_init(m) +#define mutex_free(m) free((m)) -#define mutex_try_lock(m) spin_try_lock(&(m)->held) +#define mutex_try_lock(m) (spin_try_lock(&(m)->held) ? WAIT_SET_DEBUG(m), 1 : 0) #define mutex_lock(m) \ MACRO_BEGIN \ if (!spin_try_lock(&(m)->held)) { \ __mutex_lock_solid(m); \ } \ + WAIT_SET_DEBUG(m); \ MACRO_END #define mutex_unlock(m) \ MACRO_BEGIN \ if (spin_unlock(&(m)->held), \ - cthread_queue_head(&(m)->queue, int) != 0) { \ + cthread_queue_head(&(m)->queue, vm_offset_t) != 0) { \ __mutex_unlock_solid(m); \ } \ + WAIT_CLEAR_DEBUG(m); \ MACRO_END - /* * Condition variables. */ typedef struct condition { spin_lock_t lock; struct cthread_queue queue; - char *name; + const char *name; struct cond_imp *implications; } *condition_t; @@ -398,8 +452,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); \ @@ -417,7 +473,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) \ @@ -434,29 +490,23 @@ 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 int cond_signal(condition_t _cond); -extern void -condition_wait C_ARG_DECLS((condition_t c, mutex_t m)); +extern void cond_broadcast(condition_t _cond); -extern int -hurd_condition_wait C_ARG_DECLS((condition_t c, mutex_t m)); +extern void condition_wait(condition_t _cond, mutex_t _mutex); +extern int hurd_condition_wait(condition_t _cond, mutex_t _mutex); -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_implies(condition_t _implicator, + condition_t _implicatand); +extern void condition_unimplies(condition_t _implicator, + condition_t _implicatand); /* * Threads. */ -typedef any_t (*cthread_fn_t) C_ARG_DECLS((any_t arg)); +typedef void * (*cthread_fn_t)(void *arg); #include <setjmp.h> @@ -465,34 +515,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 @@ -503,20 +547,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())) @@ -524,37 +568,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 int cthread_limit(void); + +extern void cthread_set_kernel_limit(int _n); + +extern int cthread_kernel_limit(void); + +extern void cthread_wire(void); + +extern void cthread_unwire(void); -extern char * -cthread_name C_ARG_DECLS((cthread_t t)); +extern void cthread_msg_busy(mach_port_t _port, int _min, int _max); -extern int -cthread_count C_ARG_DECLS((void)); +extern void cthread_msg_active(mach_port_t _prt, int _min, int _max); -extern void -cthread_set_limit C_ARG_DECLS((int n)); +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 int -cthread_limit C_ARG_DECLS((void)); +extern void cthread_fork_prepare(void); -extern void -cthread_wire C_ARG_DECLS((void)); +extern void cthread_fork_parent(void); -#ifdef CTHREAD_DATA +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 @@ -562,7 +649,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; @@ -572,27 +659,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> */ @@ -607,18 +692,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/csw.S b/libthreads/i386/csw.S index 0951c5cc..69c93652 100644 --- a/libthreads/i386/csw.S +++ b/libthreads/i386/csw.S @@ -1,31 +1,57 @@ -/* +/* * Mach Operating System * Copyright (c) 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: csw.S,v $ + * Revision 1.9 1998/07/20 06:58:28 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.8 1997/04/04 01:31:16 thomas + * Thu Apr 3 20:29:27 1997 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + * + * * i386/csw.S: Define __ELF__ too. + * + * Revision 1.7 1996/10/24 19:30:10 thomas + * Mon Oct 21 22:05:48 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + * + * * i386/csw.S (CALL_MCOUNT): New macro. + * (cproc_swtich, cproc_start_wait, cproc_prepare): Use CALL_MCOUNT. + * + * Revision 1.6 1996/08/29 17:44:42 thomas + * *** empty log message *** + * + * Revision 1.5 1995/10/04 20:55:28 roland + * (JUMPTARGET): New macro, versions for [PIC] and not. + * Use it in place of EXT. + * * Revision 1.4 1995/10/04 20:22:17 roland * [PIC] (EXT): Redefine to use PLT. * @@ -38,28 +64,31 @@ * Revision 2.7 91/07/31 18:36:32 dbg * Fix for ANSI C preprocessor. * [91/07/30 17:35:16 dbg] - * + * * Revision 2.6 91/05/14 17:56:56 mrt * Correcting copyright - * + * * Revision 2.5 91/05/08 13:35:49 dbg * Unlock lock with a locked instruction (xchg). * [91/03/20 dbg] - * + * * Revision 2.4 91/02/14 14:20:02 mrt * Changed to new Mach copyright * [91/02/13 12:15:27 mrt] - * + * * Revision 2.3 91/01/08 16:46:20 rpd * Don't use Times - horta doesn't like it for some reason. * [91/01/06 rpd] - * + * * Revision 2.2 90/05/03 15:54:37 dbg * Created. * [90/02/05 dbg] - * + * */ -#include <i386/asm.h> +#define ELF +#undef __ELF__ +#define __ELF__ 1 +#include <mach/i386/asm.h> #ifdef PIC #define JUMPTARGET(name) EXT(name##@PLT) @@ -67,12 +96,21 @@ #define JUMPTARGET(name) EXT(name) #endif +#ifdef PROF +#define CALL_MCOUNT \ + pushl %ebp; movl %esp, %ebp; call JUMPTARGET(mcount); popl %ebp; +#else +#define CALL_MCOUNT +#endif + + /* * Suspend the current thread and resume the next one. * * void cproc_switch(int *cur, int *next, int *lock) */ ENTRY(cproc_switch) + CALL_MCOUNT pushl %ebp /* save ebp */ movl %esp,%ebp /* set frame pointer to get arguments */ pushl %ebx /* save ebx */ @@ -86,7 +124,7 @@ ENTRY(cproc_switch) movl (%eax),%esp /* get new stack pointer */ xorl %eax,%eax /* unlock */ xchgl %eax,(%edx) /* the lock - now old thread can run */ - + popl %edi /* restore di */ popl %esi /* si */ popl %ebx /* bx */ @@ -104,6 +142,7 @@ ENTRY(cproc_switch) * int *lock) */ ENTRY(cproc_start_wait) + CALL_MCOUNT pushl %ebp /* save ebp */ movl %esp,%ebp /* set frame pointer */ pushl %ebx /* save ebx */ @@ -126,9 +165,11 @@ ENTRY(cproc_start_wait) * it, it will start up as if it called * cproc_body(child) * - * void cproc_prepare(cproc_t child, int *context, int stack) + * void cproc_prepare(cproc_t child, int *context, int stack, + * void (*cthread_body)(cproc_t)); */ ENTRY(cproc_prepare) + CALL_MCOUNT pushl %ebp /* save ebp */ movl %esp,%ebp /* set frame pointer */ movl B_ARG2,%edx /* get child`s stack */ @@ -142,8 +183,8 @@ ENTRY(cproc_prepare) /* 20 return PC from cthread_body */ /* 24 argument to cthread_body */ movl $0,12(%edx) /* clear frame pointer */ - movl $JUMPTARGET(cthread_body),16(%edx) - /* resume at cthread_body */ + movl B_ARG3,%ecx /* get address of cthread_body passed in */ + movl %ecx,16(%edx) /* set child to resume at cthread_body */ movl $0,20(%edx) /* fake return address from cthread_body */ movl B_ARG0,%ecx /* get child thread pointer */ movl %ecx,24(%edx) /* set as argument to cthread_body */ @@ -151,4 +192,3 @@ ENTRY(cproc_prepare) movl %edx,(%ecx) /* save context */ leave ret - diff --git a/libthreads/i386/cthreads.h b/libthreads/i386/cthreads.h index 8ffe4b72..694387b6 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 @@ -25,7 +25,37 @@ */ /* * HISTORY - * $Log: cthreads.h,v $ + * $Log: cthreads.h,v $ + * Revision 1.3 2007/03/03 23:57:37 sthibaul + * 2006-03-04 Samuel Thibault <samuel.thibault@ens-lyon.org> + * + * * libpthread/sysdeps/i386/machine-sp.h (thread_stack_pointer): + * Optimize esp read. + * * libpthread/i386/cthreads.h (cthread_sp): Likewise. + * + * Revision 1.2 2002/05/27 02:50:10 roland + * 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. + * + * 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,22 +96,20 @@ 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)) ); \ + : "=&r" (_u__), "=m" (*(p)) :: "memory" ); \ 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" (_r__), "=m" (*(p)) :: "memory" ); \ + _r__; })) #define cthread_sp() \ - ({ int _sp__; \ - asm("movl %%esp, %0" \ - : "=g" (_sp__) ); \ + ({ register int _sp__ asm("esp"); \ _sp__; }) #endif /* __GNUC__ */ 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 8ba81826..00537be5 100644 --- a/libthreads/i386/thread.c +++ b/libthreads/i386/thread.c @@ -1,50 +1,52 @@ -/* +/* * 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 * 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: 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] + * + * 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] - * + * * Revision 2.2 90/05/03 15:55:03 dbg * Created (from 68020 version). * [90/02/05 dbg] - * + * */ /* * i386/thread.c @@ -52,20 +54,28 @@ */ #ifndef lint -static char rcs_id[] = "$Header: cvs-sans-libpthread/hurd/libthreads/i386/thread.c,v 1.2 1994/05/04 19:05:26 mib Exp $"; -#endif not lint +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 <cthreads.h> +#include "cthread_internals.h" +#include <mach.h> +#include <mach/i386/mach_i386.h> +#include <mach/mig_errors.h> -#include <mach/mach.h> - -/* - * C library imports: - */ -extern bzero(); +#define HURD_TLS_DESC_DECL(desc, tcb) \ + struct descriptor desc = \ + { /* low word: */ \ + 0xffff /* limit 0..15 */ \ + | (((unsigned int) (tcb)) << 16) /* base 0..15 */ \ + , /* high word: */ \ + ((((unsigned int) (tcb)) >> 16) & 0xff) /* base 16..23 */ \ + | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ \ + | (0xf << 16) /* limit 16..19 */ \ + | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ \ + | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ + } /* * Set up the initial state of a MACH thread @@ -73,42 +83,53 @@ extern bzero(); * 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, tcbhead_t *tcb, void (*routine)(cproc_t)) { - register int *top = (int *) (child->stack_base + child->stack_size); + extern unsigned int __hurd_threadvar_max; /* GNU */ + register int *top = (int *) + cproc_stack_base (child, + sizeof(ur_cthread_t *) + + /* Account for GNU per-thread variables. */ + __hurd_threadvar_max * + sizeof (long int)); struct i386_thread_state state; register struct i386_thread_state *ts = &state; kern_return_t r; unsigned int count; + HURD_TLS_DESC_DECL(desc, tcb); + int sel; /* * Set up i386 call frame and registers. * Read registers first to get correct segment values. */ count = i386_THREAD_STATE_COUNT; - MACH_CALL(thread_get_state(thread,i386_THREAD_STATE,(thread_state_t) &state,&count),r); + MACH_CALL(thread_get_state(thread,i386_REGS_SEGS_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 */ ts->ebp = 0; /* clear frame pointer */ - MACH_CALL(thread_set_state(thread,i386_THREAD_STATE,(thread_state_t) &state,i386_THREAD_STATE_COUNT),r); + asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0)); + tcb->tcb = tcb; + tcb->self = thread; + if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */ + __i386_set_ldt (thread, sel, &desc, 1); + else + __i386_set_gdt (thread, &sel, desc); + ts->gs = sel; + + MACH_CALL(thread_set_state(thread,i386_REGS_SEGS_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) { - int x; - - return (int) &x; + return (int) __thread_stack_pointer (); } - diff --git a/libthreads/libthreads.map b/libthreads/libthreads.map new file mode 100644 index 00000000..1a041f71 --- /dev/null +++ b/libthreads/libthreads.map @@ -0,0 +1,27 @@ +/* This is the version script file used for building libthreads.so. -*- C -*- + It is in the form of a linker script, to be including as an input + file in the link command, rather than with --version-script. */ + +/* We only use this file when we build against a libio-using libc, + which we presume will be 2.2 that is expecting our lockfile.c + hooks. Therefore the flockfile functions are added to the + GLIBC_2.2.6 version node. The rest of the library's symbols will use + HURD_CTHREADS_0.3. */ + +VERSION +{ + GLIBC_2.2.6 + { + global: + _IO_flockfile; _IO_funlockfile; _IO_ftrylockfile; + flockfile; funlockfile; ftrylockfile; + local: + _cthreads_flockfile; _cthreads_funlockfile; _cthreads_ftrylockfile; + }; + + HURD_CTHREADS_0.3 + { + global: + *; + }; +}; diff --git a/libthreads/lockfile.c b/libthreads/lockfile.c new file mode 100644 index 00000000..eeb1a2f3 --- /dev/null +++ b/libthreads/lockfile.c @@ -0,0 +1,65 @@ +/* lockfile - Handle locking and unlocking of streams. Hurd cthreads version. + Copyright (C) 2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <cthreads.h> /* Must come before <stdio.h>! */ +#include <stdio.h> + + +#ifdef _STDIO_USES_IOSTREAM + +void +_cthreads_flockfile (_IO_FILE *fp) +{ + _IO_lock_lock (*fp->_lock); +} + +void +_cthreads_funlockfile (_IO_FILE *fp) +{ + _IO_lock_unlock (*fp->_lock); +} + +int +_cthreads_ftrylockfile (_IO_FILE *fp) +{ + return __libc_lock_trylock_recursive (*fp->_lock); +} + +# undef _IO_flockfile +# undef _IO_funlockfile +# undef _IO_ftrylockfile +# undef flockfile +# undef funlockfile +# undef ftrylockfile + +void _IO_flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void _IO_funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int _IO_ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +void flockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_flockfile"))); +void funlockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_funlockfile"))); +int ftrylockfile (_IO_FILE *) + __attribute__ ((alias ("_cthreads_ftrylockfile"))); + +#endif /* _STDIO_USES_IOSTREAM */ diff --git a/libthreads/malloc.c b/libthreads/malloc.c deleted file mode 100644 index abf971f7..00000000 --- a/libthreads/malloc.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 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: malloc.c,v $ - * Revision 1.6 1996/03/07 21:13:08 miles - * (realloc): - * Use LOG2_MIN_SIZE. - * Don't bother allocating a new block if the new size request fits in the old - * one and doesn't waste any space. - * Only free the old block if we successfully got a new one. - * (LOG2_MIN_SIZE): New macro. - * - * Revision 1.5 1996/03/06 23:51:04 miles - * [MCHECK] (struct header): New type. - * (union header): Only define if !MCHECK. - * (HEADER_SIZE, HEADER_NEXT, HEADER_FREE, HEADER_CHECK): New macros. - * [MCHECK] (MIN_SIZE): Add correct definition for this case. - * (more_memory, malloc, free, realloc): - * Use above macros, and add appropiate checks & frobs in MCHECK case. - * - * Revision 1.4 1994/05/05 11:21:42 roland - * entered into RCS - * - * Revision 2.7 91/05/14 17:57:34 mrt - * Correcting copyright - * - * Revision 2.6 91/02/14 14:20:26 mrt - * Added new Mach copyright - * [91/02/13 12:41:21 mrt] - * - * Revision 2.5 90/11/05 14:37:33 rpd - * Added malloc_fork* code. - * [90/11/02 rwd] - * - * Add spin_lock_t. - * [90/10/31 rwd] - * - * Revision 2.4 90/08/07 14:31:28 rpd - * Removed RCS keyword nonsense. - * - * Revision 2.3 90/06/02 15:14:00 rpd - * Converted to new IPC. - * [90/03/20 20:56:57 rpd] - * - * Revision 2.2 89/12/08 19:53:59 rwd - * Removed conditionals. - * [89/10/23 rwd] - * - * Revision 2.1 89/08/03 17:09:46 rwd - * Created. - * - * - * 13-Sep-88 Eric Cooper (ecc) at Carnegie Mellon University - * Changed realloc() to copy min(old size, new size) bytes. - * Bug found by Mike Kupfer at Olivetti. - */ -/* - * File: malloc.c - * Author: Eric Cooper, Carnegie Mellon University - * Date: July, 1988 - * - * Memory allocator for use with multiple threads. - */ - - -#include <assert.h> -#include <cthreads.h> - -#define MCHECK - -/* - * C library imports: - */ -extern bcopy(); - -/* - * Structure of memory block header. - * When free, next points to next block on free list. - * When allocated, fl points to free list. - * Size of header is 4 bytes, so minimum usable block size is 8 bytes. - */ - -#define CHECK_BUSY 0x8a3c743e -#define CHECK_FREE 0x66688b92 - -#ifdef MCHECK - -typedef struct header { - long check; - union { - struct header *next; - struct free_list *fl; - } u; -} *header_t; - -#define HEADER_SIZE sizeof (struct header) -#define HEADER_NEXT(h) ((h)->u.next) -#define HEADER_FREE(h) ((h)->u.fl) -#define HEADER_CHECK(h) ((h)->check) -#define MIN_SIZE 16 -#define LOG2_MIN_SIZE 4 - -#else /* ! MCHECK */ - -typedef union header { - union header *next; - struct free_list *fl; -} *header_t; - -#define HEADER_SIZE sizeof (union header) -#define HEADER_NEXT(h) ((h)->next) -#define HEADER_FREE(h) ((h)->fl) -#define MIN_SIZE 8 /* minimum block size */ -#define LOG2_MIN_SIZE 3 - -#endif /* MCHECK */ - -typedef struct free_list { - spin_lock_t lock; /* spin lock for mutual exclusion */ - header_t head; /* head of free list for this size */ -#ifdef DEBUG - int in_use; /* # mallocs - # frees */ -#endif DEBUG -} *free_list_t; - -/* - * Free list with index i contains blocks of size 2 ^ (i + LOG2_MIN_SIZE) - * including header. Smallest block size is MIN_SIZE, with MIN_SIZE - - * HEADER_SIZE bytes available to user. Size argument to malloc is a signed - * integer for sanity checking, so largest block size is 2^31. - */ -#define NBUCKETS 29 - -static struct free_list malloc_free_list[NBUCKETS]; - -static void -more_memory(size, fl) - int size; - register free_list_t fl; -{ - register int amount; - register int n; - vm_address_t where; - register header_t h; - kern_return_t r; - - if (size <= vm_page_size) { - amount = vm_page_size; - n = vm_page_size / size; - /* We lose vm_page_size - n*size bytes here. */ - } else { - amount = size; - n = 1; - } - - r = vm_allocate(mach_task_self(), &where, (vm_size_t) amount, TRUE); - assert_perror (r); - - h = (header_t) where; - do { - HEADER_NEXT (h) = fl->head; -#ifdef MCHECK - HEADER_CHECK (h) = CHECK_FREE; -#endif - fl->head = h; - h = (header_t) ((char *) h + size); - } while (--n != 0); -} - -/* Declaration changed to standard one for GNU. */ -void * -malloc(size) - register size_t size; -{ - register int i, n; - register free_list_t fl; - register header_t h; - - if ((int) size < 0) /* sanity check */ - return 0; - size += HEADER_SIZE; - /* - * Find smallest power-of-two block size - * big enough to hold requested size plus header. - */ - i = 0; - n = MIN_SIZE; - while (n < size) { - i += 1; - n <<= 1; - } - ASSERT(i < NBUCKETS); - fl = &malloc_free_list[i]; - spin_lock(&fl->lock); - h = fl->head; - if (h == 0) { - /* - * Free list is empty; - * allocate more blocks. - */ - more_memory(n, fl); - h = fl->head; - if (h == 0) { - /* - * Allocation failed. - */ - spin_unlock(&fl->lock); - return 0; - } - } - /* - * Pop block from free list. - */ - fl->head = HEADER_NEXT (h); - -#ifdef MCHECK - assert (HEADER_CHECK (h) == CHECK_FREE); - HEADER_CHECK (h) = CHECK_BUSY; -#endif - -#ifdef DEBUG - fl->in_use += 1; -#endif DEBUG - spin_unlock(&fl->lock); - /* - * Store free list pointer in block header - * so we can figure out where it goes - * at free() time. - */ - HEADER_FREE (h) = fl; - /* - * Return pointer past the block header. - */ - return ((char *) h) + HEADER_SIZE; -} - -/* Declaration changed to standard one for GNU. */ -void -free(base) - void *base; -{ - register header_t h; - register free_list_t fl; - register int i; - - if (base == 0) - return; - /* - * Find free list for block. - */ - h = (header_t) (base - HEADER_SIZE); - -#ifdef MCHECK - assert (HEADER_CHECK (h) == CHECK_BUSY); -#endif - - fl = HEADER_FREE (h); - i = fl - malloc_free_list; - /* - * Sanity checks. - */ - if (i < 0 || i >= NBUCKETS) { - ASSERT(0 <= i && i < NBUCKETS); - return; - } - if (fl != &malloc_free_list[i]) { - ASSERT(fl == &malloc_free_list[i]); - return; - } - /* - * Push block on free list. - */ - spin_lock(&fl->lock); - HEADER_NEXT (h) = fl->head; -#ifdef MCHECK - HEADER_CHECK (h) = CHECK_FREE; -#endif - fl->head = h; -#ifdef DEBUG - fl->in_use -= 1; -#endif DEBUG - spin_unlock(&fl->lock); - return; -} - -/* Declaration changed to standard one for GNU. */ -void * -realloc(old_base, new_size) - void *old_base; - size_t new_size; -{ - register header_t h; - register free_list_t fl; - register int i; - unsigned int old_size; - char *new_base; - - if (old_base == 0) - return malloc (new_size); - - /* - * Find size of old block. - */ - h = (header_t) (old_base - HEADER_SIZE); -#ifdef MCHECK - assert (HEADER_CHECK (h) == CHECK_BUSY); -#endif - fl = HEADER_FREE (h); - i = fl - malloc_free_list; - /* - * Sanity checks. - */ - if (i < 0 || i >= NBUCKETS) { - ASSERT(0 <= i && i < NBUCKETS); - return 0; - } - if (fl != &malloc_free_list[i]) { - ASSERT(fl == &malloc_free_list[i]); - return 0; - } - /* - * Free list with index i contains blocks of size - * 2 ^ (i + * LOG2_MIN_SIZE) including header. - */ - old_size = (1 << (i + LOG2_MIN_SIZE)) - HEADER_SIZE; - - if (new_size <= old_size - && new_size > (((old_size + HEADER_SIZE) >> 1) - HEADER_SIZE)) - /* The new size still fits in the same block, and wouldn't fit in - the next smaller block! */ - return old_base; - - /* - * Allocate new block, copy old bytes, and free old block. - */ - new_base = malloc(new_size); - if (new_base) - bcopy(old_base, new_base, - (int) (old_size < new_size ? old_size : new_size)); - - if (new_base || new_size == 0) - /* Free OLD_BASE, but only if the malloc didn't fail. */ - free (old_base); - - return new_base; -} - -#ifdef DEBUG -void -print_malloc_free_list() -{ - register int i, size; - register free_list_t fl; - register int n; - register header_t h; - int total_used = 0; - int total_free = 0; - - fprintf(stderr, " Size In Use Free Total\n"); - for (i = 0, size = MIN_SIZE, fl = malloc_free_list; - i < NBUCKETS; - i += 1, size <<= 1, fl += 1) { - spin_lock(&fl->lock); - if (fl->in_use != 0 || fl->head != 0) { - total_used += fl->in_use * size; - for (n = 0, h = fl->head; h != 0; h = HEADER_NEXT (h), n += 1) - ; - total_free += n * size; - fprintf(stderr, "%10d %10d %10d %10d\n", - size, fl->in_use, n, fl->in_use + n); - } - spin_unlock(&fl->lock); - } - fprintf(stderr, " all sizes %10d %10d %10d\n", - total_used, total_free, total_used + total_free); -} -#endif DEBUG - -void malloc_fork_prepare() -/* - * Prepare the malloc module for a fork by insuring that no thread is in a - * malloc critical section. - */ -{ - register int i; - - for (i = 0; i < NBUCKETS; i++) { - spin_lock(&malloc_free_list[i].lock); - } -} - -void malloc_fork_parent() -/* - * Called in the parent process after a fork() to resume normal operation. - */ -{ - register int i; - - for (i = NBUCKETS-1; i >= 0; i--) { - spin_unlock(&malloc_free_list[i].lock); - } -} - -void malloc_fork_child() -/* - * Called in the child process after a fork() to resume normal operation. - */ -{ - register int i; - - for (i = NBUCKETS-1; i >= 0; i--) { - spin_unlock(&malloc_free_list[i].lock); - } -} diff --git a/libthreads/mig_support.c b/libthreads/mig_support.c index bb9e6a5e..cd0d4124 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. + * someone accidentally 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/options.h b/libthreads/options.h index 952720de..b8074693 100644 --- a/libthreads/options.h +++ b/libthreads/options.h @@ -1,57 +1,71 @@ -/* +/* * Mach Operating System * Copyright (c) 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: options.h,v $ + * $Log: options.h,v $ + * Revision 1.2 2002/05/27 02:50:10 roland + * 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. + * * Revision 2.8 91/05/14 17:58:35 mrt * Correcting copyright - * + * * Revision 2.7 91/02/14 14:21:03 mrt * Added new Mach copyright * [91/02/13 12:41:31 mrt] - * + * * Revision 2.6 90/09/09 14:35:04 rpd * Remove special option , debug_mutex and thread_calls. * [90/08/24 rwd] - * + * * Revision 2.5 90/06/02 15:14:14 rpd * Removed RCS Source, Header lines. * [90/05/03 00:07:27 rpd] - * + * * Revision 2.4 90/03/14 21:12:15 rwd * Added new option: * WAIT_DEBUG: keep track of who a blocked thread is * waiting for. * [90/03/01 rwd] - * + * * Revision 2.3 90/01/19 14:37:25 rwd * New option: * THREAD_CALLS: cthread_* version of thread_* calls. * [90/01/03 rwd] - * + * * Revision 2.2 89/12/08 19:54:09 rwd * Added code: * MUTEX_SPECIAL: Have extra kernel threads available for @@ -77,7 +91,7 @@ * [89/11/13 rwd] * Added copyright. Removed all options. * [89/10/23 rwd] - * + * */ /* * options.h @@ -87,4 +101,4 @@ #define SPIN_RESCHED /*#define CHECK_STATUS*/ /*#define RED_ZONE*/ -#define WAIT_DEBUG +/*#define WAIT_DEBUG*/ diff --git a/libthreads/rwlock.c b/libthreads/rwlock.c index 6fcb08c4..ae6a7c48 100644 --- a/libthreads/rwlock.c +++ b/libthreads/rwlock.c @@ -1,6 +1,2 @@ -/* This file defines the real functions for the inlines in rwlock.h. */ - -#include <cthreads.h> - -#define _RWLOCK_DEFINE_FUNCTIONS /* Define the real functions. */ -#include <rwlock.h> +#define RWLOCK_DEFINE_EI +#include "rwlock.h" diff --git a/libthreads/rwlock.h b/libthreads/rwlock.h index 7abbfff1..44d9a35d 100644 --- a/libthreads/rwlock.h +++ b/libthreads/rwlock.h @@ -21,6 +21,13 @@ #include <cthreads.h> #include <assert.h> +#include <features.h> + +#ifdef RWLOCK_DEFINE_EI +#define RWLOCK_EI +#else +#define RWLOCK_EI __extern_inline +#endif struct rwlock { @@ -31,17 +38,20 @@ struct rwlock int readers_waiting; }; -#ifdef _RWLOCK_DEFINE_FUNCTIONS -#undef _EXTERN_INLINE -#define _EXTERN_INLINE -#else /* ! _RWLOCK_DEFINE_FUNCTIONS */ -#ifndef _EXTERN_INLINE -#define _EXTERN_INLINE extern __inline -#endif -#endif /* _RWLOCK_DEFINE_FUNCTIONS */ +extern void rwlock_reader_lock (struct rwlock *lock); + +extern void rwlock_writer_lock (struct rwlock *lock); + +extern void rwlock_reader_unlock (struct rwlock *lock); + +extern void rwlock_writer_unlock (struct rwlock *lock); + +extern void rwlock_init (struct rwlock *lock); + +#if defined(__USE_EXTERN_INLINES) || defined(RWLOCK_DEFINE_EI) /* Get a reader lock on reader-writer lock LOCK for disknode DN */ -_EXTERN_INLINE void +RWLOCK_EI void rwlock_reader_lock (struct rwlock *lock) { mutex_lock (&lock->master); @@ -58,7 +68,7 @@ rwlock_reader_lock (struct rwlock *lock) } /* Get a writer lock on reader-writer lock LOCK for disknode DN */ -_EXTERN_INLINE void +RWLOCK_EI void rwlock_writer_lock (struct rwlock *lock) { mutex_lock (&lock->master); @@ -75,7 +85,7 @@ rwlock_writer_lock (struct rwlock *lock) } /* Release a reader lock on reader-writer lock LOCK for disknode DN */ -_EXTERN_INLINE void +RWLOCK_EI void rwlock_reader_unlock (struct rwlock *lock) { mutex_lock (&lock->master); @@ -87,7 +97,7 @@ rwlock_reader_unlock (struct rwlock *lock) } /* Release a writer lock on reader-writer lock LOCK for disknode DN */ -_EXTERN_INLINE void +RWLOCK_EI void rwlock_writer_unlock (struct rwlock *lock) { mutex_lock (&lock->master); @@ -99,7 +109,7 @@ rwlock_writer_unlock (struct rwlock *lock) } /* Initialize reader-writer lock LOCK */ -_EXTERN_INLINE void +RWLOCK_EI void rwlock_init (struct rwlock *lock) { mutex_init (&lock->master); @@ -109,6 +119,8 @@ rwlock_init (struct rwlock *lock) lock->writers_waiting = 0; } +#endif /* Use extern inlines. */ + #define RWLOCK_INITIALIZER \ { MUTEX_INITIALIZER, CONDITION_INITIALIZER, 0, 0, 0 } diff --git a/libthreads/stack.c b/libthreads/stack.c index bc4ef8cd..d6dd9fff 100644 --- a/libthreads/stack.c +++ b/libthreads/stack.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 @@ -26,8 +26,25 @@ /* * HISTORY * $Log: stack.c,v $ - * Revision 1.4 1994/05/05 16:00:09 roland - * entered into RCS + * Revision 1.8 2002/05/27 02:50:41 roland + * 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, stack.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. + * + * Revision 2.14 93/01/14 18:05:58 danner + * Converted file to ANSI C. + * [92/12/18 pds] + * 64bit cleanup. + * [92/12/02 af] * * Revision 2.13 92/01/14 16:48:54 rpd * Fixed addr_range_check to deallocate the object port from vm_region. @@ -126,12 +143,10 @@ #define BYTES_TO_PAGES(b) (((b) + vm_page_size - 1) / vm_page_size) -int cthread_stack_mask; +vm_offset_t cthread_stack_mask; vm_size_t cthread_stack_size; private vm_address_t next_stack_base; -vm_offset_t cproc_stack_base(); /* forward */ - /* * Set up a stack segment for a thread. * Segment has a red zone (invalid page) @@ -161,7 +176,9 @@ setup_stack(p, base) register cproc_t p; register vm_address_t base; { +#if defined(RED_ZONE) register kern_return_t r; +#endif /* defined(RED_ZONE) */ p->stack_base = base; /* @@ -171,20 +188,19 @@ setup_stack(p, base) /* * Protect red zone. */ -#ifdef RED_ZONE +#if defined(RED_ZONE) MACH_CALL(vm_protect(mach_task_self(), base + vm_page_size, vm_page_size, FALSE, VM_PROT_NONE), r); -#endif RED_ZONE +#endif /* defined(RED_ZONE) */ /* * Store self pointer. */ *(cproc_t *)&ur_cthread_ptr(base) = p; } -#if 0 /* roland@gnu */ -vm_offset_t -addr_range_check(start_addr, end_addr, desired_protection) - vm_offset_t start_addr, end_addr; - vm_prot_t desired_protection; +#if 0 /* GNU */ +private vm_offset_t +addr_range_check(vm_offset_t start_addr, vm_offset_t end_addr, + vm_prot_t desired_protection) { register vm_offset_t addr; @@ -222,10 +238,8 @@ addr_range_check(start_addr, end_addr, desired_protection) * 1. stack grows DOWN * 2. There is an unallocated region below the stack. */ -void -probe_stack(stack_bottom, stack_top) - vm_offset_t *stack_bottom; - vm_offset_t *stack_top; +private void +probe_stack(vm_offset_t *stack_bottom, vm_offset_t *stack_top) { /* * Since vm_region returns the region starting at @@ -270,9 +284,8 @@ probe_stack(stack_bottom, stack_top) /* * Check that the entire range exists and is writable */ - } while (end_addr = (addr_range_check(start_addr, - end_addr, - VM_PROT_READ|VM_PROT_WRITE))); + } while ((end_addr = addr_range_check(start_addr, end_addr, + VM_PROT_READ|VM_PROT_WRITE))); /* * Back off to previous power of 2. */ @@ -282,13 +295,12 @@ probe_stack(stack_bottom, stack_top) #endif /* For GNU: */ -unsigned long int __hurd_threadvar_stack_mask; -unsigned long int __hurd_threadvar_stack_offset; -unsigned int __hurd_threadvar_max; +extern unsigned long int __hurd_threadvar_stack_mask; +extern unsigned long int __hurd_threadvar_stack_offset; +extern unsigned int __hurd_threadvar_max; vm_offset_t -stack_init(p) - cproc_t p; +stack_init(cproc_t p) { #if 0 vm_offset_t stack_bottom, @@ -296,11 +308,7 @@ stack_init(p) start; vm_size_t size; kern_return_t r; -#endif - - void alloc_stack(); -#if 0 /* * Probe for bottom and top of stack, as a power-of-2 size. */ @@ -312,27 +320,27 @@ stack_init(p) */ if (cthread_stack_size == 0) cthread_stack_size = stack_top - stack_bottom; -#else /* roland@gnu */ +#else /* GNU */ if (cthread_stack_size == 0) cthread_stack_size = vm_page_size * 16; /* Reasonable default. */ -#endif +#endif /* GNU */ -#ifdef STACK_GROWTH_UP +#if defined(STACK_GROWTH_UP) cthread_stack_mask = ~(cthread_stack_size - 1); -#else STACK_GROWTH_UP +#else /* not defined(STACK_GROWTH_UP) */ cthread_stack_mask = cthread_stack_size - 1; -#endif STACK_GROWTH_UP - - /* Set up the variables so GNU can find its per-thread variables. */ - __hurd_threadvar_stack_mask = ~(cthread_stack_size - 1); - /* The GNU per-thread variables will be stored just after the - cthread-self pointer at the base of the stack. */ -#ifdef STACK_GROWTH_UP - __hurd_threadvar_stack_offset = sizeof (ur_cthread_t *); +#endif /* defined(STACK_GROWTH_UP) */ + + /* Set up the variables so GNU can find its per-thread variables. */ + __hurd_threadvar_stack_mask = ~(cthread_stack_size - 1); + /* The GNU per-thread variables will be stored just after the + cthread-self pointer at the base of the stack. */ +#ifdef STACK_GROWTH_UP + __hurd_threadvar_stack_offset = sizeof (ur_cthread_t *); #else - __hurd_threadvar_stack_offset = (cthread_stack_size - - sizeof (ur_cthread_t *) - - __hurd_threadvar_max * sizeof (long)); + __hurd_threadvar_stack_offset = (cthread_stack_size - + sizeof (ur_cthread_t *) - + __hurd_threadvar_max * sizeof (long)); #endif /* @@ -345,28 +353,27 @@ stack_init(p) */ alloc_stack(p); -#if 0 +#if 0 /* GNU */ /* * Delete rest of old stack. */ -#ifdef STACK_GROWTH_UP +#if defined(STACK_GROWTH_UP) start = (cthread_sp() | (vm_page_size - 1)) + 1 + vm_page_size; size = stack_top - start; -#else STACK_GROWTH_UP +#else /* not defined(STACK_GROWTH_UP) */ start = stack_bottom; size = (cthread_sp() & ~(vm_page_size - 1)) - stack_bottom - vm_page_size; -#endif STACK_GROWTH_UP +#endif /* defined(STACK_GROWTH_UP) */ MACH_CALL(vm_deallocate(mach_task_self(),start,size),r); -#endif +#endif /* GNU */ /* * Return new stack; it gets passed back to the caller * of cthread_init who must switch to it. */ - return cproc_stack_base(p, - sizeof(ur_cthread_t *) + + return cproc_stack_base(p, sizeof(ur_cthread_t *) + /* Account for GNU per-thread variables. */ __hurd_threadvar_max * sizeof (long int)); } @@ -382,8 +389,7 @@ stack_init(p) */ void -alloc_stack(p) - cproc_t p; +alloc_stack(cproc_t p) { vm_address_t base = next_stack_base; @@ -400,11 +406,11 @@ cproc_stack_base(cproc, offset) register cproc_t cproc; register int offset; { -#ifdef STACK_GROWTH_UP +#if defined(STACK_GROWTH_UP) return (cproc->stack_base + offset); -#else STACK_GROWTH_UP +#else /* not defined(STACK_GROWTH_UP) */ return (cproc->stack_base + cproc->stack_size - offset); -#endif STACK_GROWTH_UP +#endif /* defined(STACK_GROWTH_UP) */ } 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 |