summaryrefslogtreecommitdiff
path: root/hurd
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-07-05 23:47:08 +0000
committerRoland McGrath <roland@gnu.org>1996-07-05 23:47:08 +0000
commite33b438a8456aecf60a661ee75ac5977a7b49815 (patch)
tree4cb110b68bb4ddf7611aba3a5382561535c16d65 /hurd
parent39d690795a63d66c893ceecf74b910977cdfc8f1 (diff)
Fri Jul 5 12:22:51 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* hurd/hurdsig.c (_hurd_internal_post_signal): In case of handled signal during critical section doing interruptible RPC, if _hurdsig_abort_rpcs wants to change thread state, do thread_set_state before thread_resume. If in critical section, pass 0 for SIGNO to _hurdsig_abort_rpcs so rpc is interrupted regardless of SA_RESTART.
Diffstat (limited to 'hurd')
-rw-r--r--hurd/hurdsig.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index a3ec24e9e6..1da3fa580d 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -802,19 +802,41 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
}
else
{
+ int crit = __spin_lock_locked (&ss->critical_section_lock);
+
wait_for_reply
- = (_hurdsig_abort_rpcs (ss, signo, 1,
+ = (_hurdsig_abort_rpcs (ss,
+ /* In a critical section, any RPC
+ should be cancelled instead of
+ restarted, regardless of
+ SA_RESTART, so the the entire
+ "atomic" operation can be aborted
+ as a unit. */
+ crit ? 0 : signo, 1,
&thread_state, &state_changed,
&reply)
!= MACH_PORT_NULL);
- if (__spin_lock_locked (&ss->critical_section_lock))
+ if (crit)
{
/* The thread is in a critical section. Mark the signal as
pending. When it finishes the critical section, it will
check for pending signals. */
mark_pending ();
- assert (! state_changed);
+ if (state_changed)
+ /* Some cases of interrupting an RPC must change the
+ thread state to back out the call. Normally this
+ change is rolled into the warping to the handler and
+ sigreturn, but we are not running the handler now
+ because the thread is in a critical section. Instead,
+ mutate the thread right away for the RPC interruption
+ and resume it; the RPC will return early so the
+ critical section can end soon. */
+ __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
+ (natural_t *) &thread_state.basic,
+ MACHINE_THREAD_STATE_COUNT);
+ /* */
+ ss->intr_port = MACH_PORT_NULL;
__thread_resume (ss->thread);
break;
}