diff options
Diffstat (limited to 'sysdeps/l4/hurd/pt-thread-alloc.c')
-rw-r--r-- | sysdeps/l4/hurd/pt-thread-alloc.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/sysdeps/l4/hurd/pt-thread-alloc.c b/sysdeps/l4/hurd/pt-thread-alloc.c index daa13dba..6941e10e 100644 --- a/sysdeps/l4/hurd/pt-thread-alloc.c +++ b/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; |