]> sourceware.org Git - glibc.git/commitdiff
Thu Aug 17 16:18:38 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
authorRoland McGrath <roland@gnu.org>
Thu, 17 Aug 1995 22:55:22 +0000 (22:55 +0000)
committerRoland McGrath <roland@gnu.org>
Thu, 17 Aug 1995 22:55:22 +0000 (22:55 +0000)
* hurd/intr-msg.c: Use INTR_MSG_TRAP macro from machine-dependent
  "intr-msg.h" for special syscall code, instead of i386-specific asm.
* hurd/hurdsig.c: Use INTR_MSG_BACK_OUT macro from
  machine-dependent "intr-msg.h" before mutating thread state to
  skip RPC.

* sysdeps/mach/hurd/i386/trampoline.c: If PC is inside
  _hurd_intr_rpc_mach_msg special syscall code, use real SP saved in
%ecx.

* Makeconfig (link-libc): New variable; use shared library if
  available.
(+link): Use it.

* sysdeps/mach/hurd/fork.c (_hurd_fork_locks): Variable removed.
   Instead, declare with `symbol_set_declare'.
(fork): Use symbol_set_* macros for _hurd_fork_locks.
Use SS->thread instead of __mach_thread_self ().  Suspend all
  other threads during task_create and port copying.

ChangeLog
Makeconfig
hurd/hurdsig.c
hurd/intr-msg.c
sysdeps/mach/hurd/fork.c
sysdeps/mach/hurd/i386/trampoline.c

index 27b84aee7e2975931c76e2d63b62fbff1baab047..7c56c65ab0ae9b621fae152c72fd8fa18b591c24 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+Thu Aug 17 16:18:38 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
+
+       * hurd/intr-msg.c: Use INTR_MSG_TRAP macro from machine-dependent
+       "intr-msg.h" for special syscall code, instead of i386-specific asm.
+       * hurd/hurdsig.c: Use INTR_MSG_BACK_OUT macro from
+       machine-dependent "intr-msg.h" before mutating thread state to
+       skip RPC.
+
+       * sysdeps/mach/hurd/i386/trampoline.c: If PC is inside
+       _hurd_intr_rpc_mach_msg special syscall code, use real SP saved in
+       %ecx.
+
+       * Makeconfig (link-libc): New variable; use shared library if
+       available.
+       (+link): Use it.
+
+       * sysdeps/mach/hurd/fork.c (_hurd_fork_locks): Variable removed.
+       Instead, declare with `symbol_set_declare'.
+       (fork): Use symbol_set_* macros for _hurd_fork_locks.  
+       Use SS->thread instead of __mach_thread_self ().  Suspend all
+       other threads during task_create and port copying.
+
 Wed Aug 16 17:04:26 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
 
        * hurd/intr-msg.c: Fixed calculation of syscall %esp.
index 0ebe04392bb50056bd755dfa34532306e28cd5f2..23db67ff3340c8f78e62b95c00ba6e6cf891c36e 100644 (file)
@@ -267,11 +267,18 @@ endif
 
 # Command for linking programs with the C library.
 ifndef +link
-+link = $(CC) -nostdlib $(LDFLAGS) -o $@ \
++link = $(CC) -nostdlib -nostartfiles $(LDFLAGS) -o $@ \
        $(addprefix $(csu-objpfx),start.o $(+preinit)) \
-       $(^:lib=$(common-objpfx)libc.a) $(gnulib) $(common-objpfx)libc.a \
+       $(^:$(common-objpfx)libc.a=$(link-libc)) \
        $(addprefix $(csu-objpfx),$(+postinit))
 endif
+ifndef link-libc
+ifeq (yes,$(build-shared))
+link-libc = -L$(common-objdir) -lc $(gnulib)
+else
+link-libc = $(common-objpfx)libc.a $(gnulib) $(common-objpfx)libc.a
+endif
+endif
 ifndef gnulib
 gnulib := -lgcc
 endif
index 10dbceb4f4a058767d87492e2074792d7d314609..ca4e22925bd53664c2902b3c9423084877930772 100644 (file)
@@ -250,7 +250,8 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
 
   return portloc;
 }
-
+\f
+#include "intr-msg.h"
 
 /* SS->thread is suspended.
 
@@ -274,7 +275,7 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
                     mach_msg_type_name_t reply_port_type,
                     int untraced)
 {
-  extern const void _hurd_intr_rpc_msg_do_trap, _hurd_intr_rpc_msg_in_trap;
+  extern const void _hurd_intr_rpc_msg_in_trap;
   mach_port_t rcv_port = MACH_PORT_NULL;
   mach_port_t intr_port;
 
@@ -294,6 +295,7 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
       /* The thread is about to do the RPC, but hasn't yet entered
         mach_msg.  Mutate the thread's state so it knows not to try
         the RPC.  */
+      INTR_MSG_BACK_OUT (&state->basic);
       MACHINE_THREAD_STATE_SET_PC (&state->basic,
                                   &_hurd_intr_rpc_msg_in_trap);
       state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
index 6f670b538fdd216a676a59c320cff6af2b1a738a..024cbfbd3ef650348259ed17fb6890a594281f7b 100644 (file)
@@ -21,6 +21,9 @@ Cambridge, MA 02139, USA.  */
 #include <mach/mig_errors.h>
 #include <hurd/signal.h>
 
+#include "intr-msg.h"
+
+
 error_t
 _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
                         mach_msg_option_t option,
@@ -56,17 +59,8 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
       ss->cancel = 0;
     }
   else 
-  /*       err = intr_msg_trap (msg, option, send_size,
-          rcv_size, rcv_name, timeout, notify);
-          */
-    asm (".globl _hurd_intr_rpc_msg_do_trap\n" 
-        ".globl _hurd_intr_rpc_msg_in_trap\n"
-        "                              movl %%esp, %%ecx\n"
-        "                              leal %1, %%esp\n"
-        "                              movl $-25, %%eax\n"
-        "_hurd_intr_rpc_msg_do_trap:   lcall $7, $0 # status in %0\n"
-        "_hurd_intr_rpc_msg_in_trap:   movl %%ecx, %%esp"
-        : "=a" (err) : "m" ((&msg)[-1]) : "%ecx");
+    err = INTR_MSG_TRAP (msg, option, send_size,
+                        rcv_size, rcv_name, timeout, notify);
 
   switch (err)
     {
index b8b15743cd8ded8540dfdbb8c0ff76853981c9ac..66b1ba84c701824be4eaed620b76dec8b1c1beb0 100644 (file)
@@ -29,11 +29,7 @@ Cambridge, MA 02139, USA.  */
 
 
 /* Things that want to be locked while forking.  */
-struct
-  {
-    size_t n;
-    struct mutex *locks[0];
-  } _hurd_fork_locks;
+symbol_set_declare (_hurd_fork_locks)
 
 
 /* Things that want to be called before we fork, to prepare the parent for
@@ -62,7 +58,6 @@ __fork (void)
   pid_t pid;
   size_t i;
   error_t err;
-  thread_t thread_self = __mach_thread_self ();
   struct hurd_sigstate *volatile ss;
 
   ss = _hurd_self_sigstate ();
@@ -87,14 +82,32 @@ __fork (void)
       mach_msg_type_number_t nporttypes = 0;
       thread_t *threads = NULL;
       mach_msg_type_number_t nthreads = 0;
-      int ports_locked = 0;
+      int ports_locked = 0, stopped = 0;
+
+      void resume_threads (void)
+       {
+         if (! stopped)
+           return;
+
+         assert (threads);
+
+         for (i = 0; i < nthreads; ++i)
+           if (threads[i] != ss->thread)
+             __thread_resume (threads[i]);
+         stopped = 0;
+       }
 
       /* Run things that prepare for forking before we create the task.  */
       RUN_HOOK (_hurd_fork_prepare_hook, ());
 
       /* Lock things that want to be locked before we fork.  */
-      for (i = 0; i < _hurd_fork_locks.n; ++i)
-       __mutex_lock (_hurd_fork_locks.locks[i]);
+      {
+       void *const *p;
+       for (p = symbol_set_first_element (_hurd_fork_locks);
+            ! symbol_set_end_p (_hurd_fork_locks, p);
+            ++p)
+         __mutex_lock (*p);
+      }
       __mutex_lock (&_hurd_siglock);
       
       newtask = MACH_PORT_NULL;
@@ -108,8 +121,16 @@ __fork (void)
        __spin_lock (&_hurd_ports[i].lock);
       ports_locked = 1;
 
-      /* Create the child task.  It will inherit a copy of our memory.  */
-      err = __task_create (__mach_task_self (), 1, &newtask);
+      /* Stop all other threads while copying the address space,
+        so nothing changes.  */
+      err = __proc_dostop (_hurd_ports[INIT_PORT_PROC].port, ss->thread);
+      if (!err)
+        {
+          stopped = 1;
+
+         /* Create the child task.  It will inherit a copy of our memory.  */
+         err = __task_create (__mach_task_self (), 1, &newtask);
+        }
 
       /* Unlock the global signal state lock, so we do not
         block the signal thread any longer than necessary.  */
@@ -263,7 +284,7 @@ __fork (void)
                  if (err = __proc_task2proc (portnames[i], newtask, &insert))
                    LOSE;
                }
-             else if (portnames[i] == thread_self)
+             else if (portnames[i] == ss->thread)
                {
                  /* For the name we use for our own thread port, we will
                     insert the thread port for the child main user thread
@@ -372,6 +393,10 @@ __fork (void)
        __spin_unlock (&_hurd_ports[i].lock);
       ports_locked = 0;
 
+      /* All state has now been copied from the parent.  It is safe to
+         resume other parent threads.  */
+      resume_threads ();
+
       /* Create the child main user thread and signal thread.  */
       if ((err = __thread_create (newtask, &thread)) ||
          (err = __thread_create (newtask, &sigthread)))
@@ -381,8 +406,8 @@ __fork (void)
          dead name rights with the names we want to give the thread ports
          in the child as placeholders.  Now deallocate them so we can use
          the names.  */
-      if ((err = __mach_port_deallocate (newtask, thread_self)) ||
-         (err = __mach_port_insert_right (newtask, thread_self,
+      if ((err = __mach_port_deallocate (newtask, ss->thread)) ||
+         (err = __mach_port_insert_right (newtask, ss->thread,
                                           thread, MACH_MSG_TYPE_COPY_SEND)))
        LOSE;
       /* We have one extra user reference created at the beginning of this
@@ -390,9 +415,9 @@ __fork (void)
         accounted for in the child below).  This extra right gets consumed
         in the child by the store into _hurd_sigthread in the child fork.  */
       if (thread_refs > 1 &&
-         (err = __mach_port_mod_refs (newtask, thread_self,
+         (err = __mach_port_mod_refs (newtask, ss->thread,
                                       MACH_PORT_RIGHT_SEND,
-                                      thread_refs - 1)))
+                                      thread_refs)))
        LOSE;
       if ((_hurd_msgport_thread != MACH_PORT_NULL) /* Let user have none.  */
          && ((err = __mach_port_deallocate (newtask, _hurd_msgport_thread)) ||
@@ -474,6 +499,8 @@ __fork (void)
        for (i = 0; i < _hurd_nports; ++i)
          __spin_unlock (&_hurd_ports[i].lock);
 
+      resume_threads ();
+
       if (newtask != MACH_PORT_NULL)
        {
          if (err)
@@ -486,8 +513,6 @@ __fork (void)
        __mach_port_deallocate (__mach_task_self (), sigthread);
       if (newproc != MACH_PORT_NULL)
        __mach_port_deallocate (__mach_task_self (), newproc);
-      if (thread_self != MACH_PORT_NULL)
-       __mach_port_deallocate (__mach_task_self (), thread_self);
 
       if (portnames)
        __vm_deallocate (__mach_task_self (),
@@ -525,7 +550,7 @@ __fork (void)
 
       /* We are the only thread in this new task, so we will
         take the task-global signals.  */
-      _hurd_sigthread = thread_self;
+      _hurd_sigthread = ss->thread;
 
       /* Unchain the sigstate structures for threads that existed in the
         parent task but don't exist in this task (the child process).
@@ -575,8 +600,13 @@ __fork (void)
 
   /* Unlock things we locked before creating the child task.
      They are locked in both the parent and child tasks.  */
-  for (i = 0; i < _hurd_fork_locks.n; ++i)
-    __mutex_unlock (_hurd_fork_locks.locks[i]);
+  {
+    void *const *p;
+    for (p = symbol_set_first_element (_hurd_fork_locks);
+        ! symbol_set_end_p (_hurd_fork_locks, p);
+        ++p)
+      __mutex_unlock (*p);
+  }
 
   _hurd_critical_section_unlock (ss);
 
index 7adffc40be58f258da4285e56038844efdcb07c0..9e947a46e799aae89ec62a34e91db84f97653e6a 100644 (file)
@@ -45,6 +45,9 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
                        struct machine_thread_all_state *state)
 {
   __label__ trampoline, rpc_wait_trampoline, firewall;
+  extern const void _hurd_intr_rpc_msg_in_trap;
+  extern const void _hurd_intr_rpc_msg_cx_sp;
+  extern const void _hurd_intr_rpc_msg_sp_restored;
   void *volatile sigsp;
   struct sigcontext *scp;
   struct 
@@ -80,6 +83,11 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
   if (! machine_get_basic_state (ss->thread, state))
     return NULL;
 
+  /* Save the original SP in the gratuitous `esp' slot.
+     We may need to reset the SP (the `uesp' slot) to avoid clobbering an
+     interrupted RPC frame.  */
+  state->basic.esp = state->basic.uesp;
+
   if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
       !(ss->sigaltstack.ss_flags & (SA_DISABLE|SA_ONSTACK)))
     {
@@ -88,6 +96,24 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
       /* XXX need to set up base of new stack for
         per-thread variables, cthreads.  */
     }
+  /* This code has intimate knowledge of the special mach_msg system call
+     done in intr-msg.c; that code does: 
+                                       movl %esp, %ecx
+                                       leal ARGS, %esp
+       _hurd_intr_rpc_msg_cx_sp:       movl $-25, %eax
+       _hurd_intr_rpc_msg_do_trap:     lcall $7, $0
+       _hurd_intr_rpc_msg_in_trap:     movl %ecx, %esp
+        _hurd_intr_rpc_msg_sp_restored:
+     We must check for the window during which %esp points at the
+     mach_msg arguments.  The space below until %ecx is used by
+     the _hurd_intr_rpc_mach_msg frame, and must not be clobbered.  */
+  else if (state->basic.eip >= (int) &_hurd_intr_rpc_msg_cx_sp && 
+          state->basic.eip < (int) &_hurd_intr_rpc_msg_sp_restored)
+    /* The SP now points at the mach_msg args, but there is more stack
+       space used below it.  The real SP is saved in %ecx; we must push the
+       new frame below there, and restore that value as the SP on
+       sigreturn.  */
+    sigsp = (char *) (state->basic.uesp = state->basic.ecx);
   else
     sigsp = (char *) state->basic.uesp;
 
@@ -166,7 +192,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
         message reception, since the request message has already been
         sent.  */
 
-      struct mach_msg_trap_args *args = (void *) state->basic.uesp;
+      struct mach_msg_trap_args *args = (void *) state->basic.esp;
 
       if (_hurdsig_catch_fault (SIGSEGV))
        {
@@ -192,6 +218,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
       state->basic.eip = (int) &&rpc_wait_trampoline;
       /* The reply-receiving trampoline code runs initially on the original
         user stack.  We pass it the signal stack pointer in %ebx.  */
+      state->basic.uesp = state->basic.esp; /* Restore mach_msg syscall SP.  */
       state->basic.ebx = (int) sigsp;
       /* After doing the message receive, the trampoline code will need to
         update the %eax value to be restored by sigreturn.  To simplify
This page took 0.064231 seconds and 5 git commands to generate.