diff options
-rw-r--r-- | hurd/ChangeLog | 10 | ||||
-rw-r--r-- | hurd/exceptions.h | 15 | ||||
-rw-r--r-- | hurd/stddef.h | 10 | ||||
-rw-r--r-- | libhurd-mm/ChangeLog | 22 | ||||
-rw-r--r-- | libhurd-mm/Makefile.am | 1 | ||||
-rw-r--r-- | libhurd-mm/exceptions.c | 62 | ||||
-rw-r--r-- | libhurd-mm/ia32-exception-entry.S | 139 | ||||
-rw-r--r-- | libhurd-mm/pager.c | 9 | ||||
-rw-r--r-- | libpthread/ChangeLog | 29 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/ia32/pt-setup.c | 16 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c | 6 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/pt-setactivity-np.c | 2 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/pt-sysdep.h | 16 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/pt-thread-alloc.c | 53 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/pt-thread-halt.c | 72 | ||||
-rw-r--r-- | libpthread/sysdeps/l4/hurd/pt-thread-start.c | 5 | ||||
-rw-r--r-- | viengoos/ChangeLog | 12 | ||||
-rw-r--r-- | viengoos/as.c | 8 | ||||
-rw-r--r-- | viengoos/cap-lookup.c | 11 | ||||
-rw-r--r-- | viengoos/thread.c | 28 | ||||
-rw-r--r-- | viengoos/zalloc.c | 4 |
21 files changed, 382 insertions, 148 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog index 49ecbb6..fa2632a 100644 --- a/hurd/ChangeLog +++ b/hurd/ChangeLog @@ -1,3 +1,13 @@ +2008-05-29 Neal H. Walfield <neal@gnu.org> + + * exceptions.h: Include <hurd/stddef.h>. + [ASM]: Only define relevant macros. + (EXCEPTION_STACK_SIZE_LOG2): Define. + (EXCEPTION_STACK_SIZE): Define. + * stddef.h [ASM]: Only define relevant macros. + (PAGESIZE): Don't append C type specifier. + (PAGESIZE_LOG2): Likewise. + 2008-05-28 Neal H. Walfield <neal@gnu.org> * cap.h (slot_lookup_rel): Remove parameter type. Update users. diff --git a/hurd/exceptions.h b/hurd/exceptions.h index 4982efa..a359435 100644 --- a/hurd/exceptions.h +++ b/hurd/exceptions.h @@ -22,6 +22,10 @@ #ifndef _HURD_EXCEPTIONS_H #define _HURD_EXCEPTIONS_H 1 +#include <hurd/stddef.h> + +#ifndef ASM + #include <stdint.h> #include <hurd/cap.h> #include <hurd/thread.h> @@ -106,7 +110,16 @@ RPC(exception_collect, 1, 0, addr_t, principal) #undef RPC_STUB_PREFIX #undef RPC_ID_PREFIX #undef RPC_TARGET +#endif /* !ASM */ +/* The exception stack is 4 pages large. The word beyond the base of + the stack is a pointer to the exception page, which is usually the + last page of the stack. */ +#define EXCEPTION_STACK_SIZE_LOG2 (PAGESIZE_LOG2 + 2) +#define EXCEPTION_STACK_SIZE (1 << EXCEPTION_STACK_SIZE_LOG2) + +#ifndef ASM + /* Initialize the exception handler. */ extern void exception_handler_init (void); @@ -142,4 +155,6 @@ extern char exception_handler_entry; exception handler dispatcher. */ extern char exception_handler_end; +#endif /* !ASM */ + #endif diff --git a/hurd/stddef.h b/hurd/stddef.h index deb4af8..4616ac1 100644 --- a/hurd/stddef.h +++ b/hurd/stddef.h @@ -21,6 +21,8 @@ #ifndef _HURD_STDDEF_H #define _HURD_STDDEF_H 1 +#ifndef ASM + #include <l4/types.h> #include <assert.h> @@ -78,13 +80,15 @@ extern void __attribute__ ((__noreturn__)) #define panic(fmt, args...) \ panic_(__func__, __LINE__, fmt, ##args) + +#endif /* ! ASM */ /* XXX: We define these here as they are useful macros, everyone uses them and everyone includes this header file. We should put them somewhere else. */ #if i386 -#define PAGESIZE 0x1000U -#define PAGESIZE_LOG2 12U +#define PAGESIZE 0x1000 +#define PAGESIZE_LOG2 12 #else #error Not ported to this architecture. #endif @@ -94,7 +98,9 @@ extern void __attribute__ ((__noreturn__)) #define PAGE_SHIFT PAGESIZE_LOG2 #define PAGE_MASK (~(PAGE_SIZE-1)) +#ifndef ASM #define likely(expr) __builtin_expect ((expr), 1) #define unlikely(expr) __builtin_expect ((expr), 0) +#endif #endif /* _HURD_STDDEF_H */ diff --git a/libhurd-mm/ChangeLog b/libhurd-mm/ChangeLog index cab6986..c6ae6b6 100644 --- a/libhurd-mm/ChangeLog +++ b/libhurd-mm/ChangeLog @@ -1,3 +1,25 @@ +2008-05-29 Neal H. Walfield <neal@gnu.org> + + * exceptions.c (exception_handler_activated): Assume the fault is + on the stack if it is one page above or three pages below the + stack pointer. + (exception_handler_init): Allocate an area of address space + EXCEPTION_STACK_SIZE bytes larges. Fill it with pages. Set the + first page as the thread's exception page and the top of the area + minus one word as the stack pointer. Set the last word to the + location of the exception page. + * ia32-exception-entry.S: Include <hurd/exceptions.h>. + (PAGESIZE): Don't define. + (_exception_handler_entry): Rewrite to not assume that the + exception page is at the start of the page in which the stack + pointer is, but at the location stored in the word after the bottom + of the stack. + + * Makefile.am (libhurd_mm_a_CCASFLAGS): New variable. + + * pager.c (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE + - PAGESIZE bytes large. Write to each page. + 2008-05-28 Neal H. Walfield <neal@gnu.org> * as.h (slot_lookup): Remove parameter type. Update users. diff --git a/libhurd-mm/Makefile.am b/libhurd-mm/Makefile.am index 29c7f79..63d1726 100644 --- a/libhurd-mm/Makefile.am +++ b/libhurd-mm/Makefile.am @@ -28,6 +28,7 @@ includehurddir = $(includedir)/hurd includehurd_HEADERS = mm.h storage.h as.h libhurd_mm_a_CPPFLAGS = $(USER_CPPFLAGS) +libhurd_mm_a_CCASFLAGS = $(USER_CPPFLAGS) -DASM libhurd_mm_a_CFLAGS = $(USER_CFLAGS) -mpreferred-stack-boundary=2 libhurd_mm_a_SOURCES = mm.h \ capalloc.h capalloc.c \ diff --git a/libhurd-mm/exceptions.c b/libhurd-mm/exceptions.c index ecf7ce5..3631893 100644 --- a/libhurd-mm/exceptions.c +++ b/libhurd-mm/exceptions.c @@ -241,8 +241,7 @@ exception_handler_activated (struct exception_page *exception_page) = exception_frame_alloc (exception_page); utcb_state_save (exception_frame); - debug (5, "Exception handler called (0x%x.%x, exception_page: %p)", - l4_thread_no (l4_myself ()), l4_version (l4_myself ()), + debug (5, "Exception handler called (exception_page: %p)", exception_page); #ifndef NDEBUG @@ -271,12 +270,14 @@ exception_handler_activated (struct exception_page *exception_page) /* XXX: We assume that the stack grows down here. */ uintptr_t f = (uintptr_t) ADDR_TO_PTR (fault); - if ((f & ~(PAGESIZE - 1)) == ((sp - 1) & ~(PAGESIZE - 1)) - || (f & ~(PAGESIZE - 1)) == (sp & ~(PAGESIZE - 1))) - /* The fault occurs on the same page as the last byte of the - interrupted SP. It has got to be a stack fault. Handle - it here. */ + if (sp - PAGESIZE <= f && f <= sp + PAGESIZE * 4) + /* The fault occurs within four pages of the stack pointer. + It has got to be a stack fault. Handle it here. */ { + debug (5, "Handling fault at " ADDR_FMT " in activated mode " + "(ip: %x, sp: %x).", + ADDR_PRINTF (fault), ip, sp); + bool r = pager_fault (fault, ip, info); if (! r) { @@ -307,6 +308,10 @@ exception_handler_activated (struct exception_page *exception_page) return NULL; } + debug (5, "Handling fault at " ADDR_FMT " in normal mode " + "(ip: %x, sp: %x).", + ADDR_PRINTF (fault), ip, sp); + break; } @@ -336,25 +341,50 @@ exception_handler_init (void) extern struct hurd_startup_data *__hurd_startup_data; - struct storage storage = storage_alloc (ADDR_VOID, cap_page, - STORAGE_LONG_LIVED, - OBJECT_POLICY_DEFAULT, ADDR_VOID); + /* We use the start of the area (lowest address) as the exception page. */ + addr_t stack_area = as_alloc (EXCEPTION_STACK_SIZE_LOG2, 1, true); + void *stack_area_base + = ADDR_TO_PTR (addr_extend (stack_area, 0, EXCEPTION_STACK_SIZE_LOG2)); + + debug (5, "Exception area: %x-%x", + stack_area_base, stack_area_base + EXCEPTION_STACK_SIZE - 1); + + void *page; + for (page = stack_area_base; + page < stack_area_base + EXCEPTION_STACK_SIZE; + page += PAGESIZE) + { + addr_t slot = addr_chop (PTR_TO_ADDR (page), PAGESIZE_LOG2); + + as_slot_ensure (slot); + + struct storage storage; + storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_LONG_LIVED, + OBJECT_POLICY_DEFAULT, + slot); - if (ADDR_IS_VOID (storage.addr)) - panic ("Failed to allocate page for exception state"); + if (ADDR_IS_VOID (storage.addr)) + panic ("Failed to allocate page for exception state"); + } - struct exception_page *exception_page - = ADDR_TO_PTR (addr_extend (storage.addr, 0, PAGESIZE_LOG2)); + struct exception_page *exception_page = stack_area_base; /* XXX: We assume the stack grows down! SP is set to the end of the exception page. */ - exception_page->exception_handler_sp = (l4_word_t) exception_page + PAGESIZE; + exception_page->exception_handler_sp + = (uintptr_t) stack_area_base + EXCEPTION_STACK_SIZE; + + /* The word beyond the base of the stack is a pointer to the + exception page. */ + exception_page->exception_handler_sp -= sizeof (void *); + * (void **) exception_page->exception_handler_sp = exception_page; exception_page->exception_handler_ip = (l4_word_t) &exception_handler_entry; exception_page->exception_handler_end = (l4_word_t) &exception_handler_end; struct hurd_thread_exregs_in in; - in.exception_page = storage.addr; + in.exception_page = addr_chop (PTR_TO_ADDR (exception_page), PAGESIZE_LOG2); struct hurd_thread_exregs_out out; err = rm_thread_exregs (ADDR_VOID, __hurd_startup_data->thread, diff --git a/libhurd-mm/ia32-exception-entry.S b/libhurd-mm/ia32-exception-entry.S index ba92354..0b4d522 100644 --- a/libhurd-mm/ia32-exception-entry.S +++ b/libhurd-mm/ia32-exception-entry.S @@ -18,9 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ - .text +#include <hurd/exceptions.h> -#define PAGESIZE 0x1000 + .text /* Offsets into a struct exception_page. */ #define MODE (0*4) @@ -30,11 +30,12 @@ #define EXCEPTION_STACK (4*4) -#define ORIG_FLAGS (PAGESIZE-1*4) -#define SAVED_EAX (PAGESIZE-2*4) -#define SAVED_ECX (PAGESIZE-3*4) -#define SAVED_FLAGS (PAGESIZE-4*4) -#define SAVED_EDX (PAGESIZE-5*4) +/* Relative to one word beyond the bottom of the stack. */ +#define EXCEPTION_PAGE_PTR (-1*4) +#define SAVED_EAX (-2*4) +#define SAVED_ECX (-3*4) +#define SAVED_FLAGS (-4*4) +#define SAVED_EDX (-5*4) /* Offsets into a struct exception_fault. */ #define EF_SAVED_EAX (EF_SAVED_ECX-4) @@ -53,43 +54,63 @@ .globl exception_handler_entry, _exception_handler_entry exception_handler_entry: _exception_handler_entry: - /* Save the eflags before we do anything. */ - pushf - + + /* How we will use the stack: + + relative to entry sp + | relative to sp after saving edx + | | + v v + +0 +24 pointer to exception_page + -4 +20 saved eax \ + -8 +16 saved ecx \ save + -12 +12 saved flags / area + -16 +8 saved edx / + -20 +4 entry edx + -24 +0 entry eflags + */ + /* Adjust the stack: our saved EAX, ECX, EDX and FLAGS may be there. */ + sub $16, %esp /* %ESP points to the top of the exception page. If the interrupt in transition flag is not set, then we need to save - the caller saved registers. Otherwise, we were interrupt + the caller-saved registers. Otherwise, we were interrupted while returning to normal mode and the the saved state, not our registers, reflects the real user state (see big comment below for more information). */ pushl %edx + /* Save the eflags before we do anything serious. */ + pushf + /* %EDX is now the only register which we can touch. Make it - a pointer to the exception page. */ - mov %esp, %edx - and $0xfffff000, %edx + a pointer to the exception page. Recall: we stashed a pointer + to the exception page at the word following the botton of the + stack. */ + mov 24(%esp), %edx /* Now check if the interrupt in transition flag is set. */ bt $INTERRUPT_IN_TRANSITION_BIT, MODE(%edx) jc after_save /* Nope; we need to save the current EAX, ECX and eflags. */ - mov %eax, SAVED_EAX(%edx) - mov %ecx, SAVED_ECX(%edx) - mov ORIG_FLAGS(%edx), %ecx - mov %ecx, SAVED_FLAGS(%edx) + mov %eax, 20(%esp) + mov %ecx, 16(%esp) + /* entry eflags. */ popl %ecx - mov %ecx, SAVED_EDX(%edx) + mov %ecx, (12-4)(%esp) + /* entry edx. */ + popl %ecx + mov %ecx, (8-4-4)(%esp) jmp after_adjust after_save: - /* Adjust the stack: we saved %edx there. */ - add $4, %esp + /* Adjust the stack: we don't need our entry flags or entry edx. */ + add $8, %esp after_adjust: @@ -147,7 +168,13 @@ after_adjust: interrupt_in_transition flag set. */ /* Reset the activation bit. */ - and $0xfffffffe, MODE(%edx) + and $(~1), MODE(%edx) + + /* Set EAX to one word beyond the bottom of the stack (i.e., + pointing at the pointer to the exception page. */ + add $PAGESIZE, %esp + and $(~(PAGESIZE-1)), %esp + mov %esp, %eax /* Check for pending messages. This does not need to be atomic as if we get interrupted here, we automatically @@ -157,30 +184,34 @@ after_adjust: /* Restore the user stack. */ mov SAVED_SP(%edx), %esp - /* Copy the saved EIP, EAX and eflags to the stack. */ + + /* Copy the saved EIP and saved flags to the user stack. */ mov SAVED_IP(%edx), %ecx pushl %ecx - mov SAVED_FLAGS(%edx), %ecx + mov SAVED_FLAGS(%eax), %ecx pushl %ecx - mov SAVED_EAX(%edx), %eax - mov SAVED_ECX(%edx), %ecx - mov SAVED_EDX(%edx), %edx + /* Restore the general-purpose registers. */ + mov SAVED_EDX(%eax), %edx + mov SAVED_ECX(%eax), %ecx + mov SAVED_EAX(%eax), %eax /* Restore the saved eflags. */ popf - /* Restore the saved EIP and in doing so the saved ESP. */ + /* And finally, the saved EIP and in doing so the saved ESP. */ ret process_pending: /* This code is called if after leaving activated mode, we - detect a pending message. %EDX points to the exception page. */ + detect a pending message. %EDX points to the exception page + and eax one word beyond the bottom of the exception stack. */ /* Set activated mode and interrupt in transition. */ - or $0x5, MODE(%edx) + or $(1 | 4), MODE(%edx) /* Set the ESP to the top of the stack. */ - lea PAGESIZE(%edx), %esp + mov %eax, %esp + add $4, %esp /* Get the pending exception. */ call exception_fetch_exception @@ -190,28 +221,38 @@ process_pending: exception_frame_run: /* EAX contains the exception frame, EDX the exception page, - and ESP points into the exception page. */ + and ESP points after the saved edx. */ - /* Change our stack to that of the exception frame. */ + /* Change our stack to that of the exception frame and save + the stack pointer (which points to the lowest address of the + save area) in ECX. */ + mov %esp, %ecx lea EF_STACK_START(%eax), %esp - /* Copy all relevant register state from the exception page to - the exception frame. */ - mov SAVED_IP(%edx), %ecx - pushl %ecx - - mov SAVED_FLAGS(%edx), %ecx - pushl %ecx + /* Copy all relevant register state from the exception page + and save area to the exception frame. We use edx as the + intermediate. We can restore it from the exception stack + (it's the word following the base). */ - mov SAVED_EDX(%edx), %ecx - pushl %ecx - - mov SAVED_ECX(%edx), %ecx - pushl %ecx + mov SAVED_IP(%edx), %edx + mov %edx, EF_SAVED_IP(%eax) + + /* edx. */ + mov 0(%ecx), %edx + mov %edx, EF_SAVED_EDX(%eax) + /* flags. */ + mov 4(%ecx), %edx + mov %edx, EF_SAVED_FLAGS(%eax) + /* ecx. */ + mov 8(%ecx), %edx + mov %edx, EF_SAVED_ECX(%eax) + /* eax. */ + mov 12(%ecx), %edx + mov %edx, EF_SAVED_EAX(%eax) + + /* Restore the exception page pointer (edx). */ + mov 16(%ecx), %edx - mov SAVED_EAX(%edx), %ecx - pushl %ecx - /* Restore the user ESP. */ mov SAVED_SP(%edx), %esp @@ -219,7 +260,7 @@ exception_frame_run: the interrupted state. */ /* Reset the activation bit. */ - and $0xfffffffe, MODE(%edx) + and $(~1), MODE(%edx) /* XXX: Check for pending message. */ diff --git a/libhurd-mm/pager.c b/libhurd-mm/pager.c index 851711c..bd639ea 100644 --- a/libhurd-mm/pager.c +++ b/libhurd-mm/pager.c @@ -90,15 +90,16 @@ pager_deinstall (struct pager *pager) } static void __attribute__ ((noinline)) -ensure_stack(int i) +ensure_stack (int i) { /* XXX: If we fault on the stack while we have PAGERS_LOCK, we deadlock. Ensure that we have some stack space and hope it is enough. (This can't be too much as we may be running on the exception handler's stack.) */ - volatile char space[1024 + 512]; - space[0] = 0; - space[sizeof (space) - 1] = 0; + volatile char space[EXCEPTION_STACK_SIZE - PAGESIZE]; + int j; + for (j = sizeof (space) - 1; j >= 0; j -= PAGESIZE) + space[j] = i; } bool diff --git a/libpthread/ChangeLog b/libpthread/ChangeLog index e5c3ed7..7b204ad 100644 --- a/libpthread/ChangeLog +++ b/libpthread/ChangeLog @@ -1,3 +1,32 @@ +2008-05-29 Neal H. Walfield <neal@gnu.org> + + * sysdeps/l4/hurd/pt-sysdep.h Include <hurd/exceptions.h>. + (EXCEPTION_AREA_SIZE): Define. + (EXCEPTION_AREA_SIZE_LOG2): Likewise. + (EXCEPTION_PAGE): Likewise. + (PTHREAD_SYSDEP_MEMBERS): Change object's type to an addr_t. + Update users. Remove field exception_page, replace with + exception_area. Add field exception_area_va. + * sysdeps/l4/hurd/pt-thread-alloc.c: Include <hurd/as.h> and + <hurd/addr.h>. + (__pthread_thread_alloc): Allocate EXCEPTION_AREA_SIZE bytes of + address space. Save it in THREAD->EXCEPTION_AREA_VA. Allocate a + page for each page in that area. Save them in + THREAD->EXCEPTION_AREA. + * sysdeps/l4/hurd/ia32/pt-setup.c (__pthread_setup): Set + EXCEPTION_PAGE->EXCEPTION_HANDLER_SP to the end of + EXCEPTION_PAGE->EXCEPTION_HANDLER_SP minus one word, in which we + save the address of the exception page. + * sysdeps/l4/hurd/pt-thread-start.c (__pthread_thread_start): Set + IN.EXCEPTION_PAGE to the first page in THREAD->EXCEPTION_AREA_VA. + * sysdeps/l4/hurd/pt-thread-halt.c: Include <hurd/mutex.h>, + <hurd/as.h> and <hurd/addr.h>. + (saved_object_lock): New variable. + (__pthread_thread_halt): Lock SAVED_OBJECT_LOCK when accessing + SAVED_OBJECT. Free the address space used by the exception + area (THREAD->EXCEPTION_AREA_VA) and its associated + storage (THREAD->EXCEPTION_AREA). + 2008-05-27 Neal H. Walfield <neal@gnu.org> * pthread/pt-internal.h (__pthread_queue_iterate): Before diff --git a/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c index f598779..cc2f075 100644 --- a/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c +++ b/libpthread/sysdeps/l4/hurd/ia32/pt-setup.c @@ -1,4 +1,4 @@ -/* Setup thread stack. Hurd/i386 version. +/* Setup thread stack. Viengoos/i386 version. Copyright (C) 2000, 2002, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -96,14 +96,16 @@ __pthread_setup (struct __pthread *thread, if (__pthread_num_threads == 1) return 0; - assert (! ADDR_IS_VOID (thread->exception_page.addr)); + assert (! ADDR_IS_VOID (thread->exception_area[0])); - struct exception_page *exception_page - = ADDR_TO_PTR (addr_extend (thread->exception_page.addr, - 0, PAGESIZE_LOG2)); + struct exception_page *exception_page = thread->exception_area_va; - /* SP is set to the end of the exception page. */ - exception_page->exception_handler_sp = (uintptr_t) exception_page + PAGESIZE; + /* SP is set to the end of the exception area minus one word, which + is the location of the exception page. */ + exception_page->exception_handler_sp + = (uintptr_t) thread->exception_area_va + EXCEPTION_AREA_SIZE; + exception_page->exception_handler_sp -= sizeof (void *); + * (void **) exception_page->exception_handler_sp = thread->exception_area_va; exception_page->exception_handler_ip = (uintptr_t) &exception_handler_entry; exception_page->exception_handler_end = (uintptr_t) &exception_handler_end; diff --git a/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c index bb6ac2a..37ef821 100644 --- a/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c +++ b/libpthread/sysdeps/l4/hurd/ia32/signal-dispatch-lowlevel.c @@ -124,13 +124,13 @@ signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, struct hurd_thread_exregs_out out; error_t err; - err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + err = rm_thread_exregs (ADDR_VOID, thread->object, HURD_EXREGS_STOP | HURD_EXREGS_ABORT_IPC | HURD_EXREGS_GET_REGS, in, &out); if (err) panic ("Failed to modify thread " ADDR_FMT, - ADDR_PRINTF (thread->object.addr)); + ADDR_PRINTF (thread->object)); intr_sp = out.sp; @@ -205,7 +205,7 @@ signal_dispatch_lowlevel (struct signal_state *ss, pthread_t tid, in.sp = sp; in.ip = (uintptr_t) &_signal_dispatch_entry; - rm_thread_exregs (ADDR_VOID, thread->object.addr, + rm_thread_exregs (ADDR_VOID, thread->object, HURD_EXREGS_SET_SP_IP | HURD_EXREGS_START | HURD_EXREGS_ABORT_IPC, in, &out); diff --git a/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c index dbadb68..f2f0723 100644 --- a/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c +++ b/libpthread/sysdeps/l4/hurd/pt-setactivity-np.c @@ -31,7 +31,7 @@ pthread_setactivity_np (addr_t activity) in.activity = activity; struct hurd_thread_exregs_out out; - int err = rm_thread_exregs (ADDR_VOID, self->object.addr, + int err = rm_thread_exregs (ADDR_VOID, self->object, HURD_EXREGS_SET_ACTIVITY, in, &out); diff --git a/libpthread/sysdeps/l4/hurd/pt-sysdep.h b/libpthread/sysdeps/l4/hurd/pt-sysdep.h index 5c66330..08bcd14 100644 --- a/libpthread/sysdeps/l4/hurd/pt-sysdep.h +++ b/libpthread/sysdeps/l4/hurd/pt-sysdep.h @@ -1,5 +1,5 @@ -/* Internal defenitions for pthreads library. - Copyright (C) 2000, 2002, 2005, 2007 Free Software Foundation, Inc. +/* Internal definitions for pthreads library. + Copyright (C) 2000, 2002, 2005, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -30,10 +30,18 @@ /* The default stack size: 2MB. */ #define PTHREAD_STACK_DEFAULT (2 * 1024 * 1024) +#include <hurd/exceptions.h> + +#define EXCEPTION_AREA_SIZE EXCEPTION_STACK_SIZE +#define EXCEPTION_AREA_SIZE_LOG2 EXCEPTION_STACK_SIZE_LOG2 +/* The exception page is the first object. */ +#define EXCEPTION_PAGE 0 + #define PTHREAD_SYSDEP_MEMBERS \ - struct storage object; \ + addr_t object; \ l4_thread_id_t threadid; \ - struct storage exception_page; \ + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; \ + void *exception_area_va; \ l4_word_t my_errno; extern inline struct __pthread * diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c index daa13db..6941e10 100644 --- a/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c +++ b/libpthread/sysdeps/l4/hurd/pt-thread-alloc.c @@ -1,4 +1,4 @@ -/* Allocate kernel thread. Hurd/L4 version. +/* Allocate kernel thread. Viengoos version. Copyright (C) 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -23,6 +23,8 @@ #include <hurd/startup.h> #include <hurd/storage.h> +#include <hurd/as.h> +#include <hurd/addr.h> #include <pt-internal.h> @@ -36,40 +38,57 @@ __pthread_thread_alloc (struct __pthread *thread) /* The main thread is already running of course. */ if (__pthread_num_threads == 1) { - thread->object.addr = __hurd_startup_data->thread; - /* If the main thread exits, then we wait. Thus, we don't need - the shadow cap. */ - thread->object.cap = NULL; + thread->object = __hurd_startup_data->thread; thread->threadid = l4_myself (); return 0; } else { - struct storage storage; + addr_t exception_area = as_alloc (EXCEPTION_AREA_SIZE_LOG2, 1, true); - /* We can't don't use mmap as when the exception thread starts - running and it accesses its stack, it will fault, which we - naturally cannot handle. */ - storage = storage_alloc (ADDR_VOID, cap_page, - STORAGE_UNKNOWN, OBJECT_POLICY_DEFAULT, - ADDR_VOID); - if (ADDR_IS_VOID (storage.addr)) - return EAGAIN; + thread->exception_area_va + = ADDR_TO_PTR (addr_extend (exception_area, + 0, EXCEPTION_AREA_SIZE_LOG2)); - thread->exception_page = storage; + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) + { + addr_t slot = addr_chop (PTR_TO_ADDR (thread->exception_area_va + + i * PAGESIZE), + PAGESIZE_LOG2); + as_slot_ensure (slot); + struct storage storage = storage_alloc (ADDR_VOID, cap_page, + STORAGE_LONG_LIVED, + OBJECT_POLICY_DEFAULT, + slot); + if (ADDR_IS_VOID (storage.addr)) + { + int j; + for (j = 0; j < i; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); + return EAGAIN; + } + thread->exception_area[i] = storage.addr; + } + + struct storage storage; storage = storage_alloc (meta_data_activity, cap_thread, /* Threads are rarely shortly lived. */ STORAGE_MEDIUM_LIVED, OBJECT_POLICY_DEFAULT, ADDR_VOID); if (ADDR_IS_VOID (storage.addr)) { - storage_free (thread->exception_page.addr, false); + int j; + for (j = 0; j < EXCEPTION_AREA_SIZE / PAGESIZE; j ++) + storage_free (thread->exception_area[j], false); + as_free (exception_area, false); return EAGAIN; } - thread->object = storage; + thread->object = storage.addr; } return 0; diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c index 1e9a8ee..98fefaa 100644 --- a/libpthread/sysdeps/l4/hurd/pt-thread-halt.c +++ b/libpthread/sysdeps/l4/hurd/pt-thread-halt.c @@ -1,5 +1,5 @@ -/* Deallocate the kernel thread resources. L4/Hurd version. - Copyright (C) 2007 Software Foundation, Inc. +/* Deallocate the kernel thread resources. Viengoos version. + Copyright (C) 2007, 2008 Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,47 +23,75 @@ #include <pt-internal.h> #include <hurd/exceptions.h> +#include <hurd/mutex.h> +#include <hurd/as.h> +#include <hurd/addr.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. */ -static struct storage saved_object; +ss_mutex_t saved_object_lock; +static addr_t saved_object; void __pthread_thread_halt (struct __pthread *thread, int need_dealloc) { - struct storage exception_page = thread->exception_page; - thread->exception_page.addr = ADDR_VOID; + /* We may deallocate THREAD. First save any data we need. */ - struct storage object = thread->object; + addr_t exception_area[EXCEPTION_AREA_SIZE / PAGESIZE]; + memcpy (exception_area, thread->exception_area, + sizeof (thread->exception_area)); + memset (thread->exception_area, 0, sizeof (thread->exception_area)); + + void *va = thread->exception_area_va; + + addr_t object = thread->object; l4_thread_id_t tid = thread->threadid; if (need_dealloc) __pthread_dealloc (thread); - if (! ADDR_IS_VOID (saved_object.addr)) + /* The THREAD data structure is no longer valid. */ + thread = NULL; + + /* Deallocate any saved object. */ + ss_mutex_lock (&saved_object_lock); + if (! ADDR_IS_VOID (saved_object)) + { + storage_free (saved_object, false); + saved_object = ADDR_VOID; + } + ss_mutex_unlock (&saved_object_lock); + + /* Free the exception area. */ + + /* Clean up the exception page. */ + exception_page_cleanup + (ADDR_TO_PTR (addr_extend (exception_area[EXCEPTION_PAGE], + 0, PAGESIZE_LOG2))); + + /* Free the storage. */ + int i; + for (i = 0; i < EXCEPTION_AREA_SIZE / PAGESIZE; i ++) { - storage_free (saved_object.addr, false); - saved_object.cap->type = cap_void; - saved_object.addr = ADDR_VOID; + assert (! ADDR_IS_VOID (exception_area[i])); + storage_free (exception_area[i], false); } - /* 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); + /* And the address space. */ + as_free (addr_chop (PTR_TO_ADDR (va), EXCEPTION_AREA_SIZE_LOG2), false); if (tid == l4_myself ()) /* If we try to storage_free (storage.addr), we will freeze in the - middle. That's no good. Thus, we add ourself to the pool of - available objects. */ - saved_object = object; - else + middle. That's no good. We set SAVED_OBJECT to our thread + object and the next thread in will free us. */ { - storage_free (object.addr, false); - object.cap->type = cap_void; + ss_mutex_lock (&saved_object_lock); + saved_object = object; + ss_mutex_unlock (&saved_object_lock); } + else + storage_free (object, false); if (tid == l4_myself ()) { @@ -72,5 +100,5 @@ __pthread_thread_halt (struct __pthread *thread, int need_dealloc) l4_thread_no (l4_myself ()), l4_version (l4_myself ())); } else - thread_stop (object.addr); + thread_stop (object); } diff --git a/libpthread/sysdeps/l4/hurd/pt-thread-start.c b/libpthread/sysdeps/l4/hurd/pt-thread-start.c index 131f59d..9db399c 100644 --- a/libpthread/sysdeps/l4/hurd/pt-thread-start.c +++ b/libpthread/sysdeps/l4/hurd/pt-thread-start.c @@ -48,13 +48,14 @@ __pthread_thread_start (struct __pthread *thread) in.activity = ADDR_VOID; - in.exception_page = thread->exception_page.addr; + in.exception_page = addr_chop (PTR_TO_ADDR (thread->exception_area_va), + PAGESIZE_LOG2); in.sp = (l4_word_t) thread->mcontext.sp; in.ip = (l4_word_t) thread->mcontext.pc; in.user_handle = (l4_word_t) thread; - err = rm_thread_exregs (ADDR_VOID, thread->object.addr, + err = rm_thread_exregs (ADDR_VOID, thread->object, HURD_EXREGS_SET_ASPACE | HURD_EXREGS_SET_ACTIVITY | HURD_EXREGS_SET_EXCEPTION_PAGE diff --git a/viengoos/ChangeLog b/viengoos/ChangeLog index 41abf7d..155172e 100644 --- a/viengoos/ChangeLog +++ b/viengoos/ChangeLog @@ -1,3 +1,15 @@ +2008-05-29 Neal H. Walfield <neal@gnu.org> + + * as.c: Include <hurd/exceptions.h>. + (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE + bytes large. Write to each page. + * cap-lookup.c: Include <hurd/exceptions.h>. + (ensure_stack): Change SPACE to be EXCEPTION_STACK_SIZE - PAGESIZE + bytes large. Write to each page. + + * zalloc.c (ZONE_SIZE): Add suffix the 1 with a U type qualifier. + (ZONES): Include one less zone. + 2008-05-28 Neal H. Walfield <neal@gnu.org> * object.c (object_find_soft): Also claim the object if diff --git a/viengoos/as.c b/viengoos/as.c index 1f711e8..2c93c10 100644 --- a/viengoos/as.c +++ b/viengoos/as.c @@ -25,6 +25,7 @@ #include <hurd/cap.h> #include <hurd/stddef.h> #include <hurd/folio.h> +#include <hurd/exceptions.h> #include "as.h" #include "bits.h" @@ -42,9 +43,10 @@ ensure_stack(int i) lock, we deadlock. Ensure that we have some stack space and hope it is enough. (This can't be too much as we may be running on the exception handler's stack.) */ - volatile char space[1024 + 512]; - space[0] = 0; - space[sizeof (space) - 1] = 0; + volatile char space[EXCEPTION_STACK_SIZE - PAGESIZE]; + int j; + for (j = sizeof (space) - 1; j >= 0; j -= PAGESIZE) + space[j] = i; } # ifndef AS_LOCK diff --git a/viengoos/cap-lookup.c b/viengoos/cap-lookup.c index 6d24fef..69ea6da 100644 --- a/viengoos/cap-lookup.c +++ b/viengoos/cap-lookup.c @@ -44,18 +44,21 @@ enum lookup_mode #ifndef RM_INTERN +#include <hurd/exceptions.h> + pthread_rwlock_t as_lock = __PTHREAD_RWLOCK_INITIALIZER; static void __attribute__ ((noinline)) -ensure_stack(void) +ensure_stack (void) { /* XXX: If we fault on the stack while we have the address space lock, we deadlock. Ensure that we have some stack space and hope it is enough. (This can't be too much as we may be running on the exception handler's stack.) */ - volatile char space[1024 + 512]; - space[0] = 0; - space[sizeof (space) - 1] = 0; + volatile char space[EXCEPTION_STACK_SIZE - PAGESIZE]; + int j; + for (j = sizeof (space) - 1; j >= 0; j -= PAGESIZE) + space[j] = 0; } # define AS_LOCK \ diff --git a/viengoos/thread.c b/viengoos/thread.c index 02f2327..0c2cb71 100644 --- a/viengoos/thread.c +++ b/viengoos/thread.c @@ -455,12 +455,23 @@ thread_raise_exception (struct activity *activity, struct thread *thread, l4_msg_t *msg) { + l4_word_t ip = 0; + l4_word_t sp = 0; + { + l4_word_t c = _L4_XCHG_REGS_DELIVER; + l4_thread_id_t targ = thread->tid; + l4_word_t dummy = 0; + _L4_exchange_registers (&targ, &c, + &sp, &ip, &dummy, &dummy, &dummy); + } + struct object *page = cap_to_object (activity, &thread->exception_page); if (! page) { do_debug (3) as_dump_from (activity, &thread->aspace, ""); - debug (1, "Malformed thread (%x): no exception page", thread->tid); + debug (1, "Malformed thread (%x): no exception page (ip: %x, sp: %x)", + thread->tid, ip, sp); return; } @@ -476,14 +487,6 @@ thread_raise_exception (struct activity *activity, if (exception_page->activated_mode) { - l4_word_t c = _L4_XCHG_REGS_DELIVER; - l4_thread_id_t targ = thread->tid; - l4_word_t sp = 0; - l4_word_t ip = 0; - l4_word_t dummy = 0; - _L4_exchange_registers (&targ, &c, - &sp, &ip, &dummy, &dummy, &dummy); - debug (1, "Deferring exception delivery: thread in activated mode!" "(sp: %x, ip: %x)", sp, ip); @@ -509,8 +512,8 @@ thread_raise_exception (struct activity *activity, string, c); } l4_thread_id_t targ = thread->tid; - l4_word_t sp = 0; - l4_word_t ip = 0; + sp = 0; + ip = 0; l4_word_t dummy = 0; _L4_exchange_registers (&targ, &c, &sp, &ip, &dummy, &dummy, &dummy); @@ -541,7 +544,8 @@ thread_raise_exception (struct activity *activity, && ip < exception_page->exception_handler_end) /* Thread is transitioning. Don't save sp and ip. */ { - debug (1, "Fault while interrupt in transition!"); + debug (1, "Fault while interrupt in transition (ip: %x)!", + ip); exception_page->interrupt_in_transition = 1; } else diff --git a/viengoos/zalloc.c b/viengoos/zalloc.c index 40e97a6..e3f8e61 100644 --- a/viengoos/zalloc.c +++ b/viengoos/zalloc.c @@ -94,10 +94,10 @@ struct block /* Given a zone, return its size. */ -#define ZONE_SIZE(x) (1 << ((x) + PAGESIZE_LOG2)) +#define ZONE_SIZE(x) (1U << ((x) + PAGESIZE_LOG2)) /* Number of zones in the system. */ -#define ZONES (sizeof (uintptr_t) * 8 - PAGESIZE_LOG2) +#define ZONES (sizeof (uintptr_t) * 8 - PAGESIZE_LOG2 - 1) /* The zones. */ static struct block *zone[ZONES]; |