diff options
-rw-r--r-- | hurd/ChangeLog | 4 | ||||
-rw-r--r-- | hurd/exceptions.h | 3 | ||||
-rw-r--r-- | libhurd-mm/ChangeLog | 9 | ||||
-rw-r--r-- | libhurd-mm/exceptions.c | 26 | ||||
-rw-r--r-- | libhurd-mm/ia32-exception-entry.S | 20 | ||||
-rw-r--r-- | libpthread/ChangeLog | 5 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/pt-thread-halt.c | 4 |
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 ()) |