aboutsummaryrefslogtreecommitdiff
path: root/libthreads
diff options
context:
space:
mode:
Diffstat (limited to 'libthreads')
-rw-r--r--libthreads/ChangeLog269
-rw-r--r--libthreads/Makefile23
-rw-r--r--libthreads/alpha/csw.S200
-rw-r--r--libthreads/alpha/cthreads.h61
-rw-r--r--libthreads/alpha/lock.S84
-rw-r--r--libthreads/alpha/thread.c100
-rw-r--r--libthreads/call.c28
-rw-r--r--libthreads/cancel-cond.c4
-rw-r--r--libthreads/cprocs.c325
-rw-r--r--libthreads/cthread_data.c77
-rw-r--r--libthreads/cthread_internals.h177
-rw-r--r--libthreads/cthreads.c196
-rw-r--r--libthreads/cthreads.h412
-rw-r--r--libthreads/i386/csw.S76
-rw-r--r--libthreads/i386/cthreads.h50
-rw-r--r--libthreads/i386/lock.s28
-rw-r--r--libthreads/i386/thread.c105
-rw-r--r--libthreads/libthreads.map27
-rw-r--r--libthreads/lockfile.c65
-rw-r--r--libthreads/malloc.c438
-rw-r--r--libthreads/mig_support.c108
-rw-r--r--libthreads/options.h44
-rw-r--r--libthreads/rwlock.c8
-rw-r--r--libthreads/rwlock.h38
-rw-r--r--libthreads/stack.c118
-rw-r--r--libthreads/sync.c9
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