mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-19 13:40:59 +08:00
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.
This commit is contained in:
parent
191abc516c
commit
3fe9de0da5
22
ChangeLog
22
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.
|
||||
|
11
Makeconfig
11
Makeconfig
@ -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
|
||||
|
@ -250,7 +250,8 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
|
||||
|
||||
return portloc;
|
||||
}
|
||||
|
||||
|
||||
#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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user