1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Mon Aug 14 16:51:13 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* hurd/thread-cancel.c: New file.
	* sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler): In
 	rpc_wait case, frob mach_msg args to set timeout on receive.
	(_hurdsig_rcv_interrupted_p): Function removed.
	* sysdeps/mach/hurd/alpha/trampoline.c: Likewise.
	* sysdeps/mach/hurd/hppa/trampoline.c: Likewise.
	* sysdeps/mach/hurd/mips/trampoline.c: Likewise.
	* hurd/intr-msg.c: New file.
	* hurd/hurd/signal.h (struct hurd_sigstate): New member `cancel'.
	(_hurdsig_rcv_interrupted_p): Declaration removed.
	(HURD_EINTR_RPC): Macro removed.
	(_hurd_longjmp_thread_state, _hurd_interrupted_rpc_timeout): Declare
	these.
	* hurd/intr-rpc.h: New file.
	* hurd/intr-rpc.defs: Just import intr-rpc.h.
	* hurd/hurdsig.c (_hurd_interrupted_rpc_timeout): New variable.
	(interrupted_reply_port_location): Take new flag arg; only catch
	faults if it's set.
	(abort_rpcs): Rename to _hurdsig_abort_rpcs; take same new flag arg.
	No longer use _hurdsig_rcv_interrupted_p; instead compare PC to
 	&_hurd_intr_rpc_msg_in_trap.  If before it, mutate state to simulate
 	MACH_SEND_INTERRUPTED return; on it, interrupt the operation.  All
 	callers changed.
	* hurd/hurd.h (hurd_thread_cancel, hurd_check_cancel): Declare these.
	* hurd/Makefile (distribute): Remove intr-rpc.awk.
	(sig): Add thread-cancel.
	(transform-user-stub, transform-user-stub-output): Variables removed.
	* sysdeps/mach/hurd/dl-sysdep.c: Change all RPCs from
 	`__hurd_intr_rpc_*' to `__*'.
	(_hurd_intr_rpc_mach_msg): New function.
	(_hurd_thread_sigstate): Function removed.
	* sysdeps/mach/hurd/ioctl.c: Use _hurd_intr_rpc_mach_msg function,
 	instead of __mach_msg inside HURD_EINTR_RPC macro.

	* sysdeps/generic/morecore.c [__GNU_LIBRARY__]: Declare `__sbrk'
 	to take ptrdiff_t arg.

	* sysdeps/mach/hurd/fork.c: Remove _hurd_longjmp_thread_state decl.

	* sysdeps/mach/hurd/kill.c (kill_pid): Don't make `inline'.

	* libc-symbols.h [GCC >= 2.7] (strong_alias, weak_symbol,
 	weak_alias): Use `extern' storage class.
This commit is contained in:
Roland McGrath
1995-08-14 22:49:23 +00:00
parent 047f282dd7
commit 54da5be39c
19 changed files with 490 additions and 336 deletions

View File

@ -41,6 +41,9 @@ thread_t _hurd_sigthread;
/* Linked-list of per-thread signal state. */
struct hurd_sigstate *_hurd_sigstates;
/* Timeout for RPC's after interrupt_operation. */
mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000;
static void
default_sigaction (struct sigaction actions[NSIG])
@ -76,9 +79,6 @@ _hurd_thread_sigstate (thread_t thread)
__sigemptyset (&ss->pending);
memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
ss->suspended = 0;
#ifdef noteven
__condition_init (&ss->arrived);
#endif
ss->intr_port = MACH_PORT_NULL;
ss->context = NULL;
@ -225,16 +225,17 @@ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
}
/* Find the location of the MiG reply port cell in use by the thread whose
state is described by THREAD_STATE. Make sure that this location can be
set without faulting, or else return NULL. */
state is described by THREAD_STATE. If SIGTHREAD is nonzero, make sure
that this location can be set without faulting, or else return NULL. */
static mach_port_t *
interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
int sigthread)
{
mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
(_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
if (_hurdsig_catch_fault (SIGSEGV))
if (sigthread && _hurdsig_catch_fault (SIGSEGV))
{
assert (_hurdsig_fault_sigcode == (long int) portloc);
/* Faulted trying to read the stack. */
@ -244,7 +245,8 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
/* Fault now if this pointer is bogus. */
*(volatile mach_port_t *) portloc = *portloc;
_hurdsig_end_catch_fault ();
if (sigthread)
_hurdsig_end_catch_fault ();
return portloc;
}
@ -266,12 +268,14 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
be applied back to the thread if it might ever run again, else zero. */
static mach_port_t
abort_rpcs (struct hurd_sigstate *ss, int signo,
struct machine_thread_all_state *state, int *state_change,
mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
int untraced)
_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
struct machine_thread_all_state *state, int *state_change,
mach_port_t *reply_port,
mach_msg_type_name_t reply_port_type,
int untraced)
{
mach_port_t msging_port;
extern const void _hurd_intr_rpc_msg_do_trap, _hurd_intr_rpc_msg_in_trap;
mach_port_t rcv_port = MACH_PORT_NULL;
mach_port_t intr_port;
*state_change = 0;
@ -285,71 +289,69 @@ abort_rpcs (struct hurd_sigstate *ss, int signo,
receive completes immediately or aborts. */
abort_thread (ss, state, reply_port, reply_port_type, untraced);
if (_hurdsig_rcv_interrupted_p (state, &msging_port))
if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
{
error_t err;
/* The RPC request message was sent and the thread was waiting for
the reply message; now the message receive has been aborted, so
the mach_msg_call will return MACH_RCV_INTERRUPTED. We must tell
the server to interrupt the pending operation. The thread must
wait for the reply message before running the signal handler (to
guarantee that the operation has finished being interrupted), so
our nonzero return tells the trampoline code to finish the message
receive operation before running the handler. */
err = __interrupt_operation (intr_port);
if (err)
{
mach_port_t *reply;
/* The interrupt didn't work.
Destroy the receive right the thread is blocked on. */
__mach_port_destroy (__mach_task_self (), msging_port);
/* The system call return value register now contains
MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
call. Since we have just destroyed the receive right, the
retry will fail with MACH_RCV_INVALID_NAME. Instead, just
change the return value here to EINTR so mach_msg will not
retry and the EINTR error code will propagate up. */
state->basic.SYSRETURN = EINTR;
*state_change = 1;
/* If that was the thread's MiG reply port (which I think should
always be the case), clear the reply port cell so it won't be
reused. */
reply = interrupted_reply_port_location (state);
if (reply != NULL && *reply == msging_port)
*reply = MACH_PORT_NULL;
}
/* All threads whose RPCs were interrupted by the interrupt_operation
call above will retry their RPCs unless we clear SS->intr_port.
So we clear it for the thread taking a signal when SA_RESTART is
clear, so that its call returns EINTR. */
if (!(ss->actions[signo].sa_flags & SA_RESTART))
ss->intr_port = MACH_PORT_NULL;
return err ? MACH_PORT_NULL : msging_port;
/* 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. */
MACHINE_THREAD_STATE_SET_PC (&state->basic,
&_hurd_intr_rpc_msg_in_trap);
state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
*state_change = 1;
}
else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap &&
/* The thread was blocked in the system call. After thread_abort,
the return value register indicates what state the RPC was in
when interrupted. */
state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
{
/* The RPC request message was sent and the thread was waiting for
the reply message; now the message receive has been aborted, so
the mach_msg call will return MACH_RCV_INTERRUPTED. We must tell
the server to interrupt the pending operation. The thread must
wait for the reply message before running the signal handler (to
guarantee that the operation has finished being interrupted), so
our nonzero return tells the trampoline code to finish the message
receive operation before running the handler. */
/* One of the following is true:
mach_port_t *reply = interrupted_reply_port_location (state,
sigthread);
error_t err = __interrupt_operation (intr_port);
1. The RPC has not yet been sent. The thread will start its operation
after the signal has been handled.
if (err)
{
if (reply)
{
/* The interrupt didn't work.
Destroy the receive right the thread is blocked on. */
__mach_port_destroy (__mach_task_self (), *reply);
*reply = MACH_PORT_NULL;
}
2. The RPC has finished, but not yet cleared SS->intr_port.
The thread will clear SS->intr_port after running the handler.
/* The system call return value register now contains
MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
call. Since we have just destroyed the receive right, the
retry will fail with MACH_RCV_INVALID_NAME. Instead, just
change the return value here to EINTR so mach_msg will not
retry and the EINTR error code will propagate up. */
state->basic.SYSRETURN = EINTR;
*state_change = 1;
}
else if (reply)
rcv_port = *reply;
3. The RPC request message was being sent was aborted. The mach_msg
system call will return MACH_SEND_INTERRUPTED, and HURD_EINTR_RPC will
notice the interruption (either retrying the RPC or returning EINTR). */
/* All threads whose RPCs were interrupted by the interrupt_operation
call above will retry their RPCs unless we clear SS->intr_port.
So we clear it for the thread taking a signal when SA_RESTART is
clear, so that its call returns EINTR. */
if (! signo || !(ss->actions[signo].sa_flags & SA_RESTART))
ss->intr_port = MACH_PORT_NULL;
}
return MACH_PORT_NULL;
return rcv_port;
}
/* Abort the RPCs being run by all threads but this one;
all other threads should be suspended. If LIVE is nonzero, those
threads may run again, so they should be adjusted as necessary to be
@ -387,8 +389,9 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
/* Abort any operation in progress with interrupt_operation.
Record the reply port the thread is waiting on.
We will wait for all the replies below. */
reply_ports[nthreads++] = abort_rpcs (ss, signo, state, &state_changed,
NULL, 0, 0);
reply_ports[nthreads++] = _hurdsig_abort_rpcs (ss, signo, 1,
state, &state_changed,
NULL, 0, 0);
if (state_changed && live)
/* Aborting the RPC needed to change this thread's state,
and it might ever run again. So write back its state. */
@ -403,11 +406,18 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
{
error_t err;
mach_msg_header_t head;
err = __mach_msg (&head, MACH_RCV_MSG, 0, sizeof head,
err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
reply_ports[nthreads],
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if (err != MACH_RCV_TOO_LARGE)
assert_perror (err);
_hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
switch (err)
{
case MACH_RCV_TIMED_OUT:
case MACH_RCV_TOO_LARGE:
break;
default:
assert_perror (err);
}
}
}
@ -745,7 +755,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
if (! machine_get_basic_state (ss->thread, &thread_state))
goto sigbomb;
loc = interrupted_reply_port_location (&thread_state);
loc = interrupted_reply_port_location (&thread_state, 1);
if (loc && *loc != MACH_PORT_NULL)
/* This is the reply port for the context which called
sigreturn. Since we are abandoning that context entirely
@ -759,11 +769,11 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
}
else
{
wait_for_reply = (abort_rpcs (ss, signo,
&thread_state, &state_changed,
&reply_port, reply_port_type,
untraced)
!= MACH_PORT_NULL);
wait_for_reply
= (_hurdsig_abort_rpcs (ss, signo, 1,
&thread_state, &state_changed,
&reply_port, reply_port_type, untraced)
!= MACH_PORT_NULL);
if (ss->critical_section)
{
@ -790,7 +800,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
{
/* Fetch the thread variable for the MiG reply port,
and set it to MACH_PORT_NULL. */
mach_port_t *loc = interrupted_reply_port_location (&thread_state);
mach_port_t *loc = interrupted_reply_port_location (&thread_state,
1);
if (loc)
{
scp->sc_reply_port = *loc;