about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1998-11-22 17:32:14 +0000
committerRoland McGrath <roland@gnu.org>1998-11-22 17:32:14 +0000
commit54509b04ce486ce04e3a0f92ef44beb5307374c9 (patch)
treead603fd5985bbb2925aaa0f5f9f062ced6c880b1 /sysdeps
parentb17f830fe1d176cf28cef34b5241aabaf3198e9c (diff)
downloadglibc-54509b04ce486ce04e3a0f92ef44beb5307374c9.tar.gz
glibc-54509b04ce486ce04e3a0f92ef44beb5307374c9.tar.xz
glibc-54509b04ce486ce04e3a0f92ef44beb5307374c9.zip
1998-11-22 Roland McGrath <roland@baalperazim.frob.com>
* sysdeps/mach/hurd/i386/init-first.c (init): Provide temporary storage 
for the per-thread variables of the main user thread to make it 
possible to use malloc as soon as _hurd_preinit_hook has been run. 
For cthreads, copy values to new stack from there. 
For non-cthreads, malloc threadvar array here and copy from temp space. 
(init1): No longer initialize threadvars here. 
(doinit1): Made static void at top level. 
(init): Folded into [PIC] _init or [!PIC] doinit1, since GCC cannot 
inline a function that uses dynamic auto arrays.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/mach/hurd/i386/init-first.c235
1 files changed, 126 insertions, 109 deletions
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
index 6854a1b3dc..dbbcc78218 100644
--- a/sysdeps/mach/hurd/i386/init-first.c
+++ b/sysdeps/mach/hurd/i386/init-first.c
@@ -105,20 +105,6 @@ init1 (int argc, char *arg0, ...)
       }
     }
 
-  if (__hurd_threadvar_stack_mask == 0)
-    {
-      /* We are not using cthreads, so we will have just a single allocated
-	 area for the per-thread variables of the main user thread.  */
-      unsigned long int i;
-      __hurd_threadvar_stack_offset
-	= (unsigned long int) malloc (__hurd_threadvar_max *
-				      sizeof (unsigned long int));
-      if (__hurd_threadvar_stack_offset == 0)
-	__libc_fatal ("Can't allocate single-threaded per-thread variables.");
-      for (i = 0; i < __hurd_threadvar_max; ++i)
-	((unsigned long int *) __hurd_threadvar_stack_offset)[i] = 0;
-    }
-
   if ((void *) d != argv[0] && (d->portarray || d->intarray))
     /* Initialize library data structures, start signal processing, etc.  */
     _hurd_init (d->flags, argv,
@@ -133,95 +119,6 @@ init1 (int argc, char *arg0, ...)
 }
 
 
-static inline void
-init (int *data)
-{
-  int argc = *data;
-  char **argv = (void *) (data + 1);
-  char **envp = &argv[argc + 1];
-  struct hurd_startup_data *d;
-
-  __environ = envp;
-  while (*envp)
-    ++envp;
-  d = (void *) ++envp;
-
-  /* The user might have defined a value for this, to get more variables.
-     Otherwise it will be zero on startup.  We must make sure it is set
-     properly before before cthreads initialization, so cthreads can know
-     how much space to leave for thread variables.  */
-  if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
-    __hurd_threadvar_max = _HURD_THREADVAR_MAX;
-
-
-  /* After possibly switching stacks, call `init1' (above) with the user
-     code as the return address, and the argument data immediately above
-     that on the stack.  */
-
-  if (_cthread_init_routine)
-    {
-      /* Initialize cthreads, which will allocate us a new stack to run on.  */
-      void *newsp = (*_cthread_init_routine) ();
-      struct hurd_startup_data *od;
-
-      /* Copy the argdata from the old stack to the new one.  */
-      newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
-		      (char *) d - (char *) data);
-
-      /* Set up the Hurd startup data block immediately following
-	 the argument and environment pointers on the new stack.  */
-      od = (newsp + ((char *) d - (char *) data));
-      if ((void *) argv[0] == d)
-	/* We were started up by the kernel with arguments on the stack.
-	   There is no Hurd startup data, so zero the block.  */
-	memset (od, 0, sizeof *od);
-      else
-	/* Copy the Hurd startup data block to the new stack.  */
-	*od = *d;
-
-      /* Push the user code address on the top of the new stack.  It will
-	 be the return address for `init1'; we will jump there with NEWSP
-	 as the stack pointer.  */
-      *--(int *) newsp = data[-1];
-      ((void **) data)[-1] = &&switch_stacks;
-      /* Force NEWSP into %ecx and &init1 into %eax, which are not restored
-	 by function return.  */
-      asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1));
-    }
-  else
-    {
-      /* The argument data is just above the stack frame we will unwind by
-	 returning.  Mutate our own return address to run the code below.  */
-      int usercode = data[-1];
-      ((void **) data)[-1] = &&call_init1;
-      /* Force USERCODE into %eax and &init1 into %ecx, which are not
-	 restored by function return.  */
-      asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
-    }
-
-  return;
-
- switch_stacks:
-  /* Our return address was redirected to here, so at this point our stack
-     is unwound and callers' registers restored.  Only %ecx and %eax are
-     call-clobbered and thus still have the values we set just above.
-     Fetch from there the new stack pointer we will run on, and jmp to the
-     run-time address of `init1'; when it returns, it will run the user
-     code with the argument data at the top of the stack.  */
-  asm volatile ("movl %eax, %esp; jmp *%ecx");
-  /* NOTREACHED */
-
- call_init1:
-  /* As in the stack-switching case, at this point our stack is unwound and
-     callers' registers restored, and only %ecx and %eax communicate values
-     from the lines above.  In this case we have stashed in %eax the user
-     code return address.  Push it on the top of the stack so it acts as
-     init1's return address, and then jump there.  */
-  asm volatile ("pushl %eax; jmp *%ecx");
-  /* NOTREACHED */
-}
-
-
 #ifdef PIC
 /* This function is called to initialize the shared C library.
    It is called just before the user _start code from i386/elf/start.S,
@@ -239,9 +136,133 @@ _init (int argc, ...)
 
   RUN_HOOK (_hurd_preinit_hook, ());
 
-  init (&argc);
-}
+#else
+
+/* In statically-linked programs, this function is
+   called from _hurd_stack_setup (below).  */
+static void
+doinit1 (int argc, ...)
+{
 #endif
+  /* This block used to be a separate inline function.
+     But GCC refuses to inline a function that uses alloca
+     or dynamically-sized auto arrays.  */
+  {
+    int *const data = &argc;
+    char **argv = (void *) (data + 1);
+    char **envp = &argv[argc + 1];
+    struct hurd_startup_data *d;
+
+    unsigned long int threadvars[__hurd_threadvar_max];
+
+    /* Provide temporary storage for thread-specific variables on the startup
+       stack so the cthreads initialization code can use them for malloc et al,
+    or so we can use malloc below for the real threadvars array.  */
+    memset (threadvars, 0, sizeof threadvars);
+    __hurd_threadvar_stack_offset = (unsigned long int) threadvars;
+
+    __environ = envp;
+    while (*envp)
+      ++envp;
+    d = (void *) ++envp;
+
+    /* The user might have defined a value for this, to get more variables.
+       Otherwise it will be zero on startup.  We must make sure it is set
+       properly before before cthreads initialization, so cthreads can know
+       how much space to leave for thread variables.  */
+    if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
+      __hurd_threadvar_max = _HURD_THREADVAR_MAX;
+
+
+    /* After possibly switching stacks, call `init1' (above) with the user
+       code as the return address, and the argument data immediately above
+       that on the stack.  */
+
+    if (_cthread_init_routine)
+      {
+	void *newsp;
+	struct hurd_startup_data *od;
+
+	/* Initialize cthreads, which will allocate us a new
+	   stack to run on.  */
+	newsp = (*_cthread_init_routine) ();
+
+	/* Copy per-thread variables from that temporary
+	   area onto the new cthread stack.  */
+	memcpy (__hurd_threadvar_location_from_sp (0, newsp),
+		threadvars, sizeof threadvars);
+
+	/* Copy the argdata from the old stack to the new one.  */
+	newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data,
+			(char *) d - (char *) data);
+
+	/* Set up the Hurd startup data block immediately following
+	   the argument and environment pointers on the new stack.  */
+	od = (newsp + ((char *) d - (char *) data));
+	if ((void *) argv[0] == d)
+	  /* We were started up by the kernel with arguments on the stack.
+	     There is no Hurd startup data, so zero the block.  */
+	  memset (od, 0, sizeof *od);
+	else
+	  /* Copy the Hurd startup data block to the new stack.  */
+	  *od = *d;
+
+	/* Push the user code address on the top of the new stack.  It will
+	   be the return address for `init1'; we will jump there with NEWSP
+	   as the stack pointer.  */
+	*--(int *) newsp = data[-1];
+	((void **) data)[-1] = &&switch_stacks;
+	/* Force NEWSP into %ecx and &init1 into %eax, which are not restored
+	   by function return.  */
+	asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1));
+      }
+    else
+      {
+	/* We are not using cthreads, so we will have just a single allocated
+	   area for the per-thread variables of the main user thread.  */
+	void *array;
+	int usercode;
+
+	array = malloc (sizeof threadvars);
+	if (array == NULL)
+	  __libc_fatal ("Can't allocate single-threaded thread variables.");
+
+	/* Copy per-thread variables from the temporary array into the
+	   newly malloc'd space.  */
+	memcpy (array, threadvars, sizeof threadvars);
+	__hurd_threadvar_stack_offset = (unsigned long int) array;
+
+	/* The argument data is just above the stack frame we will unwind by
+	   returning.  Mutate our own return address to run the code below.  */
+	usercode = data[-1];
+	((void **) data)[-1] = &&call_init1;
+	/* Force USERCODE into %eax and &init1 into %ecx, which are not
+	   restored by function return.  */
+	asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
+      }
+
+    return;
+
+  switch_stacks:
+    /* Our return address was redirected to here, so at this point our
+       stack is unwound and callers' registers restored.  Only %ecx and
+       %eax are call-clobbered and thus still have the values we set just
+       above.  Fetch from there the new stack pointer we will run on, and
+       jmp to the run-time address of `init1'; when it returns, it will run
+       the user code with the argument data at the top of the stack.  */
+    asm volatile ("movl %eax, %esp; jmp *%ecx");
+    /* NOTREACHED */
+
+  call_init1:
+    /* As in the stack-switching case, at this point our stack is unwound
+       and callers' registers restored, and only %ecx and %eax communicate
+       values from the lines above.  In this case we have stashed in %eax
+       the user code return address.  Push it on the top of the stack so it
+       acts as init1's return address, and then jump there.  */
+    asm volatile ("pushl %eax; jmp *%ecx");
+    /* NOTREACHED */
+  }
+}
 
 
 void
@@ -264,10 +285,6 @@ _hurd_stack_setup (int argc __attribute__ ((unused)), ...)
   void doinit (int *data)
     {
       /* This function gets called with the argument data at TOS.  */
-      void doinit1 (int argc, ...)
-	{
-	  init (&argc);
-	}
 
       /* Push the user return address after the argument data, and then
 	 jump to `doinit1' (above), so it is as if __libc_init_first's