summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hurd/ChangeLog4
-rw-r--r--hurd/exceptions.h3
-rw-r--r--libhurd-mm/ChangeLog9
-rw-r--r--libhurd-mm/exceptions.c26
-rw-r--r--libhurd-mm/ia32-exception-entry.S20
-rw-r--r--libpthread/ChangeLog5
-rw-r--r--libpthread/sysdeps/l4/hurd/pt-thread-halt.c4
7 files changed, 61 insertions, 10 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog
index 4ab7d89..ed656bb 100644
--- a/hurd/ChangeLog
+++ b/hurd/ChangeLog
@@ -1,3 +1,7 @@
+2007-12-13 Neal H. Walfield <neal@gnu.org>
+
+ * exceptions.h (exception_page_cleanup): New declaration.
+
2007-12-12 Neal H. Walfield <neal@gnu.org>
* addr.h (addr_extend): Use assertx instead of assert.
diff --git a/hurd/exceptions.h b/hurd/exceptions.h
index 9a94128..d8415af 100644
--- a/hurd/exceptions.h
+++ b/hurd/exceptions.h
@@ -104,6 +104,9 @@ extern struct exception_frame *
extern void exception_handler_normal (struct exception_frame *exception_frame);
+/* Should be called before destroyed the exception page associated
+ with a thread. */
+extern void exception_page_cleanup (struct exception_page *exception_page);
/* The first instruction of exception handler dispatcher. */
extern char exception_handler_entry;
diff --git a/libhurd-mm/ChangeLog b/libhurd-mm/ChangeLog
index 5256ecc..7e59cca 100644
--- a/libhurd-mm/ChangeLog
+++ b/libhurd-mm/ChangeLog
@@ -1,3 +1,12 @@
+2007-12-13 Neal H. Walfield <neal@gnu.org>
+
+ * exceptions.c (exception_frame_alloc): When allocating the first
+ frame, set EXCEPTION_PAGE->EXCEPTION_STACK_BOTTOM.
+ (exception_page_cleanup): New function.
+
+ * ia32-exception-entry.S (_exception_handler_end): Correctly
+ adjust the exception page's exception stack.
+
2007-12-12 Neal H. Walfield <neal@gnu.org>
* mmap.c (munmap): Free the virtual addresses.
diff --git a/libhurd-mm/exceptions.c b/libhurd-mm/exceptions.c
index 47f9790..71eb16c 100644
--- a/libhurd-mm/exceptions.c
+++ b/libhurd-mm/exceptions.c
@@ -93,6 +93,10 @@ exception_frame_alloc (struct exception_page *exception_page)
exception_frame->next->prev = exception_frame;
exception_page->exception_stack = exception_frame;
+
+ if (! exception_page->exception_stack_bottom)
+ /* This is the first frame we've allocated. */
+ exception_page->exception_stack_bottom = exception_frame;
}
return exception_frame;
@@ -310,3 +314,25 @@ exception_handler_init (void)
if (err)
panic ("Failed to install exception page");
}
+
+void
+exception_page_cleanup (struct exception_page *exception_page)
+{
+ struct exception_frame *f;
+ struct exception_frame *prev = exception_page->exception_stack_bottom;
+
+ int count = 0;
+ while ((f = prev))
+ {
+ prev = f->prev;
+ hurd_slab_dealloc (&exception_frame_slab, f);
+ count ++;
+ }
+
+ assertx (count == exception_page->frame_count,
+ "count: %d, exception_page->frame_count: %d",
+ count, exception_page->frame_count);
+
+ debug (0, "Freed %d frames", count);
+}
+
diff --git a/libhurd-mm/ia32-exception-entry.S b/libhurd-mm/ia32-exception-entry.S
index 6b23c9f..f511563 100644
--- a/libhurd-mm/ia32-exception-entry.S
+++ b/libhurd-mm/ia32-exception-entry.S
@@ -116,9 +116,9 @@ after_adjust:
normal mode.
To return to normal mode, we need to restore the saved
- registers, including the saved EAX, saved ESP and saved EIP.
- On x86, there is no way to atomically restore ESP and EIP from
- user code. The solution we use is:
+ registers, including the saved general registers, saved ESP
+ and saved EIP. On x86, there is no way to atomically restore
+ ESP and EIP from user code. The solution we use is:
- save the saved EIP on the user stack
- restore the saved ESP minus 4
@@ -132,15 +132,15 @@ after_adjust:
kernel can transition us back to activated mode.
But this raises another problem: the IP and SP that the kernel
- see are not those that return us to user code. As this code
+ sees are not those that return us to user code. As this code
relies on the exception stack, a nested stack will leave us in
an inconsistent state. (This can also happen if we receive a
message before returning to user code.) To avoid this, we
register our restore to normal mode function with the kernel.
- If the kernel transitions us back to activated while the EIP
- is in this range, then it does not save the EIP and ESP and
- invokes the exception handler with the interrupt_in_transition
- flag set. */
+ If the kernel transitions us back to activated mode while the
+ EIP is in this range, then it does not save the EIP and ESP
+ and invokes the exception handler with the
+ interrupt_in_transition flag set. */
/* Reset the activation bit. */
and $0xfffffffe, MODE(%edx)
@@ -262,8 +262,8 @@ _exception_handler_end:
/* Remove our exception frame, which is at the top
of the exception frame stack. */
- mov EF_NEXT(%edx), %ecx
- lock mov %ecx, EXCEPTION_STACK(%eax)
+ mov EF_NEXT(%eax), %ecx
+ lock mov %ecx, EXCEPTION_STACK(%edx)
popl %eax
popl %ecx
diff --git a/libpthread/ChangeLog b/libpthread/ChangeLog
index cc74c3e..8f5a0ed 100644
--- a/libpthread/ChangeLog
+++ b/libpthread/ChangeLog
@@ -1,3 +1,8 @@
+2007-12-13 Neal H. Walfield <neal@gnu.org>
+
+ * sysdeps/l4/hurd/pt-thread-halt.c: Include <hurd/exceptions.h>.
+ (__pthread_thread_halt): Call exception_page_cleanup.
+
2007-12-12 Neal H. Walfield <neal@gnu.org>
* sysdeps/l4/pt-block.c (__pthread_block): Clear the acceptor.
diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c
index 4aa112b..1e9a8ee 100644
--- a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c
+++ b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c
@@ -22,6 +22,8 @@
#include <pt-internal.h>
+#include <hurd/exceptions.h>
+
/* If we try to deallocate our self, we will end up causing a
deadlock. Thus, when a thread tries to free itself, we add it
here. The next thread to free a thread will free it. */
@@ -48,6 +50,8 @@ __pthread_thread_halt (struct __pthread *thread, int need_dealloc)
/* Free the exception page. */
assert (! ADDR_IS_VOID (exception_page.addr));
+ exception_page_cleanup (ADDR_TO_PTR (addr_extend (exception_page.addr,
+ 0, PAGESIZE_LOG2)));
storage_free (exception_page.addr, false);
if (tid == l4_myself ())