summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2009-02-19 19:15:59 +0100
committerNeal H. Walfield <neal@gnu.org>2009-02-19 19:15:59 +0100
commitee4b520e643c9f51fdb51a5267a988a0e50937eb (patch)
treedcaac962c5620c03f51dab5680412abec1d39ed5
parent9af34e63adeda0004857d0d32a90d1272ce07d50 (diff)
Fix signal handling.
-rw-r--r--libpthread/sysdeps/viengoos/ia32/signal-dispatch-lowlevel.c61
-rw-r--r--ruth/ruth.c9
2 files changed, 44 insertions, 26 deletions
diff --git a/libpthread/sysdeps/viengoos/ia32/signal-dispatch-lowlevel.c b/libpthread/sysdeps/viengoos/ia32/signal-dispatch-lowlevel.c
index 5f235de..7e2e367 100644
--- a/libpthread/sysdeps/viengoos/ia32/signal-dispatch-lowlevel.c
+++ b/libpthread/sysdeps/viengoos/ia32/signal-dispatch-lowlevel.c
@@ -43,6 +43,9 @@ extern char _signal_dispatch_entry;
/* Stack layout:
x86 x86-64
+ \
+ > sig_info_t structure.
+ 8 14 /
7 13 rflags
6 12 dx
5 11 cx
@@ -121,38 +124,45 @@ __asm__ (".globl _signal_dispatch_entry\n\t"
/* Set dx to the interrupted context's sp. */
"pop "R(dx)"\n\t"
- "and "R(cx)", "R(cx)"\n\t"
- "jz after_move\n\t"
-
/* We need to move the remaining state to the interrupted
stack. */
- /* Make some space on that stack (which may be this stack!). */
- "sub $(4*"WS"), "R(dx)"\n\t"
+ /* Make some space on that stack. As that stack may be this
+ stack, we need to be careful: this will overwrite the
+ siginfo structure and possibly part of the first save
+ area. */
+ "sub $(3*"WS"), "R(dx)"\n\t"
- /* Move the saved registers to the user stack. */
- /* ax. */
- "pop 0*"WS"("R(dx)")\n\t"
- /* cx. */
- "pop 1*"WS"("R(dx)")\n\t"
- /* dx. */
- "pop 2*"WS"("R(dx)")\n\t"
- /* Flags. */
- "pop 3*"WS"("R(dx)")\n\t"
+ /* Move the saved flags, dx and cx to the user stack and
+ restore ax. */
+ /* flags. */
+ "mov 3*"WS"("R(sp)"), "R(ax)"\n\t"
+ "mov "R(ax)", 2*"WS"("R(dx)")\n\t"
+
+ /* dx. */
+ "mov 2*"WS"("R(sp)"), "R(ax)"\n\t"
+ "mov "R(ax)", 1*"WS"("R(dx)")\n\t"
+
+ /* We don't need rax any more. We can restore it. */
+ "pop "R(ax)"\n\t"
+ /* cx. */
+ "pop 0*"WS"("R(dx)")\n\t"
/* Restore the interrupted context's sp - 5 * WS (the four
saved registers above and the interrupted context's
IP). */
"mov "R(dx)", "R(sp)"\n\t"
- /* Clear the SA_ONSTACK flag. */
+ /* Clear the SA_ONSTACK flag, if required (i.e., &SS_FLAGS is
+ not NULL). */
+ "and "R(cx)", "R(cx)"\n\t"
+ "jz after_clear\n\t"
"lock; and $~1, 0("R(cx)")\n\t"
+ "after_clear:\n\t"
- "after_move:\n\t"
- /* Restore the flag register, the scratch regs and the
- original sp and ip. */
- "pop "R(ax)"\n\t"
+ /* Restore the flag register, cx, dx, and the original sp and
+ ip. */
"pop "R(cx)"\n\t"
"pop "R(dx)"\n\t"
"popf\n\t"
@@ -255,7 +265,13 @@ signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid,
/* Set up the call frame for a call to signal_dispatch_entry. */
- /* Allocate save area 1. */
+ /* Copy the signinfo structure onto the target stack. */
+ siginfo_t *sip;
+ sp -= (sizeof (si) + sizeof (uintptr_t) - 1) / sizeof (uintptr_t);
+ sip = sp;
+ * sip = si;
+
+ /* Allocate save area 1, which requires space for 4 registers. */
sp -= 4;
/* The interrupted context's sp - WS. (In the case where INTR_SP is
@@ -269,13 +285,14 @@ signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid,
else
* -- sp = 0;
- /* Allocate save area 2. */
+ /* Allocate save area 2, which requires space for 6 registers on
+ x86-64. */
#ifdef __x86_64
sp -= 6;
#endif
/* A pointer to the siginfo structure. */
- * -- sp = (uintptr_t) &si;
+ * -- sp = (uintptr_t) sip;
/* The ss. */
* -- sp = (uintptr_t) ss;
diff --git a/ruth/ruth.c b/ruth/ruth.c
index ed7f554..039a24f 100644
--- a/ruth/ruth.c
+++ b/ruth/ruth.c
@@ -226,7 +226,8 @@ main (int argc, char *argv[])
assert (ret);
assert (shadow);
- storage_free (vg_addr_chop (VG_PTR_TO_ADDR (shadow), PAGESIZE_LOG2), 1);
+ storage_free (vg_addr_chop (VG_PTR_TO_ADDR (shadow), PAGESIZE_LOG2),
+ true);
}
as_free (root, 1);
@@ -311,6 +312,7 @@ main (int argc, char *argv[])
printf ("ok.\n");
}
+#if 0
{
static volatile int done;
char stack[0x1000];
@@ -362,6 +364,7 @@ main (int argc, char *argv[])
printf ("ok.\n");
}
+#endif
{
printf ("Checking pthread library... ");
@@ -430,10 +433,9 @@ main (int argc, char *argv[])
printf ("ok.\n");
}
-#if 0
{
printf ("Checking signals... ");
- int d = 0;
+ int d = 5;
pthread_t thread;
@@ -640,7 +642,6 @@ main (int argc, char *argv[])
printf ("ok.\n");
}
-#endif
{
printf ("Checking activity creation... ");