diff options
-rw-r--r-- | hurd/ChangeLog | 8 | ||||
-rw-r--r-- | hurd/folio.h | 15 | ||||
-rw-r--r-- | hurd/thread.h | 16 | ||||
-rw-r--r-- | libhurd-mm/ChangeLog | 7 | ||||
-rw-r--r-- | libhurd-mm/storage.c | 8 | ||||
-rw-r--r-- | ruth/ChangeLog | 5 | ||||
-rw-r--r-- | ruth/ruth.c | 55 | ||||
-rw-r--r-- | viengoos/ChangeLog | 21 | ||||
-rw-r--r-- | viengoos/object.c | 11 | ||||
-rw-r--r-- | viengoos/object.h | 28 | ||||
-rw-r--r-- | viengoos/server.c | 31 | ||||
-rw-r--r-- | viengoos/t-activity.c | 6 | ||||
-rw-r--r-- | viengoos/t-as.c | 2 | ||||
-rw-r--r-- | viengoos/thread.h | 19 | ||||
-rw-r--r-- | viengoos/viengoos.c | 2 |
15 files changed, 196 insertions, 38 deletions
diff --git a/hurd/ChangeLog b/hurd/ChangeLog index 4b785ce..d173930 100644 --- a/hurd/ChangeLog +++ b/hurd/ChangeLog @@ -1,5 +1,13 @@ 2008-01-16 Neal H. Walfield <neal@gnu.org> + * thread.h (RM_thread_wait_object_destroyed): New define. + (thread_wait_object_destroyed): New method. + + * folio.h (folio_object_alloc): Take additional parameter + return_code. + +2008-01-16 Neal H. Walfield <neal@gnu.org> + * futex.h: Include <hurd/startup.h>. (FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): New marcro. (struct futex_return): New structure. diff --git a/hurd/folio.h b/hurd/folio.h index 098a53e..1576fe4 100644 --- a/hurd/folio.h +++ b/hurd/folio.h @@ -179,13 +179,16 @@ RPC(folio_alloc, 3, 0, addr_t, principal, addr_t, folio, RPC(folio_free, 2, 0, addr_t, principal, addr_t, folio) /* Allocate INDEXth object in folio FOLIO as an object of type TYPE. - POLICY specifies the object's policy when accessed via the folio. - If OBJECT_SLOT is not ADDR_VOID, then stores a capability to the - allocated object in OBJECT_SLOT. If OBJECT_WEAK_SLOT is not - ADDR_VOID, stores a weaken reference to the created object. */ -RPC(folio_object_alloc, 7, 0, addr_t, principal, + (Passing cap_void as the value of type simply destroys any existing + object without allocating a new object.) POLICY specifies the + object's policy when accessed via the folio. If OBJECT_SLOT is not + ADDR_VOID, then stores a capability to the allocated object in + OBJECT_SLOT. If OBJECT_WEAK_SLOT is not ADDR_VOID, stores a weaken + reference to the created object. If an object is destroyed and + there are waiters, they are passed the return code RETURN_CODE. */ +RPC(folio_object_alloc, 8, 0, addr_t, principal, addr_t, folio, l4_word_t, index, l4_word_t, type, - struct object_policy, policy, + struct object_policy, policy, uintptr_t, return_code, addr_t, object_slot, addr_t, object_weak_slot) /* Flags for folio_policy. */ diff --git a/hurd/thread.h b/hurd/thread.h index c721044..fb4bbee 100644 --- a/hurd/thread.h +++ b/hurd/thread.h @@ -29,6 +29,7 @@ enum { RM_thread_exregs = 600, + RM_thread_wait_object_destroyed, }; struct exception_frame @@ -192,10 +193,6 @@ RPC (thread_exregs, 4, 1, /* Out: */ struct hurd_thread_exregs_out, out) -#undef RPC_STUB_PREFIX -#undef RPC_ID_PREFIX -#undef RPC_TARGET - static inline error_t thread_stop (addr_t thread) { @@ -207,4 +204,15 @@ thread_stop (addr_t thread) in, &out); } +/* Cause the caller to wait until OBJECT is destroyed. Returns the + object's return code in RETURN_CODE. */ +RPC(thread_wait_object_destroyed, 2, 1, + addr_t, principal, addr_t, object, + /* Out: */ + uintptr_t, return_code); + +#undef RPC_STUB_PREFIX +#undef RPC_ID_PREFIX +#undef RPC_TARGET + #endif diff --git a/libhurd-mm/ChangeLog b/libhurd-mm/ChangeLog index 95ef1ec..c655bbb 100644 --- a/libhurd-mm/ChangeLog +++ b/libhurd-mm/ChangeLog @@ -1,3 +1,10 @@ +2008-01-16 Neal H. Walfield <neal@gnu.org> + + * storage.c (shadow_setup): Update rm_folio_object_alloc use to + reflect API changes. + (storage_alloc_): Likewise. + (storage_free_): Likewise. + 2008-01-14 Neal H. Walfield <neal@gnu.org> * sbrk.c: New file. diff --git a/libhurd-mm/storage.c b/libhurd-mm/storage.c index 96e46d1..a66e552 100644 --- a/libhurd-mm/storage.c +++ b/libhurd-mm/storage.c @@ -1,5 +1,5 @@ /* storage.c - Storage allocation functions. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. Written by Neal H. Walfield <neal@gnu.org>. This file is part of the GNU Hurd. @@ -269,7 +269,7 @@ shadow_setup (struct cap *cap, struct storage_desc *storage) error_t err = rm_folio_object_alloc (meta_data_activity, storage->folio, idx, cap_page, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, ADDR_VOID, ADDR_VOID); assert (err == 0); shadow = ADDR_TO_PTR (addr_extend (addr_extend (storage->folio, @@ -518,7 +518,7 @@ storage_alloc_ (addr_t activity, error_t err = rm_folio_object_alloc (meta_data_activity, folio, idx, type, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, addr, ADDR_VOID); assert (! err); @@ -652,7 +652,7 @@ storage_free_ (addr_t object, bool unmap_now) error_t err = rm_folio_object_alloc (meta_data_activity, folio, idx, cap_void, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, ADDR_VOID, ADDR_VOID); assert (err == 0); diff --git a/ruth/ChangeLog b/ruth/ChangeLog index 05b5aa9..16c9f63 100644 --- a/ruth/ChangeLog +++ b/ruth/ChangeLog @@ -1,3 +1,8 @@ +2008-01-16 Neal H. Walfield <neal@gnu.org> + + * ruth.c (main): Update rm_folio_object_alloc use to reflect API + changes. Add test case for thread_wait_object_destroy. + 2008-01-15 Neal H. Walfield <neal@gnu.org> * ruth.c: Include <hurd/futex.h>. diff --git a/ruth/ruth.c b/ruth/ruth.c index d79ed1e..1b5e395 100644 --- a/ruth/ruth.c +++ b/ruth/ruth.c @@ -149,7 +149,7 @@ main (int argc, char *argv[]) panic ("capalloc"); err = rm_folio_object_alloc (activity, folio, i, cap_page, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, addr, ADDR_VOID); assert ((err == 0) == (0 <= i && i < FOLIO_OBJECTS)); @@ -438,7 +438,7 @@ main (int argc, char *argv[]) a[i].child = capalloc (); err = rm_folio_object_alloc (activity, folio, obj ++, cap_activity_control, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, a[i].child, ADDR_VOID); assert (err == 0); @@ -449,7 +449,7 @@ main (int argc, char *argv[]) a[i].page = capalloc (); err = rm_folio_object_alloc (a[i].child, a[i].folio, 0, cap_page, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, a[i].page, ADDR_VOID); assert (err == 0); @@ -480,7 +480,7 @@ main (int argc, char *argv[]) use the object. If this fails, we assume that the folio was destroyed. */ err = rm_folio_object_alloc (a[i].child, a[i].folio, 1, cap_page, - OBJECT_POLICY_DEFAULT, + OBJECT_POLICY_DEFAULT, 0, a[i].page, ADDR_VOID); assert (err); @@ -644,6 +644,53 @@ main (int argc, char *argv[]) } { + printf ("Checking thread_wait_object_destroy... "); + + struct storage storage = storage_alloc (activity, cap_page, + STORAGE_MEDIUM_LIVED, + ADDR_VOID); + assert (! ADDR_IS_VOID (storage.addr)); + + void *start (void *arg) + { + uintptr_t ret = 0; + error_t err; + err = rm_thread_wait_object_destroyed (ADDR_VOID, storage.addr, &ret); + debug (5, "object destroy returned: err: %d, ret: %d", err, ret); + assert (err == 0); + assert (ret == 10); + return 0; + } + + pthread_t tid; + error_t err = pthread_create (&tid, NULL, start, 0); + assert (err == 0); + + int i; + for (i = 0; i < 100; i ++) + l4_yield (); + + /* Deallocate the object. */ + debug (5, "Destroying object"); + rm_folio_object_alloc (ADDR_VOID, + addr_chop (storage.addr, FOLIO_OBJECTS_LOG2), + addr_extract (storage.addr, FOLIO_OBJECTS_LOG2), + cap_void, + OBJECT_POLICY_VOID, 10, ADDR_VOID, ADDR_VOID); + /* Release the memory. */ + storage_free (storage.addr, true); + + void *status; + err = pthread_join (tid, &status); + assert (err == 0); + debug (5, "Joined thread"); + + printf ("ok.\n"); + } + + { + printf ("Checking read-only pages... "); + addr_t addr = as_alloc (PAGESIZE_LOG2, 1, true); assert (! ADDR_IS_VOID (addr)); diff --git a/viengoos/ChangeLog b/viengoos/ChangeLog index ab6f23a..cef347c 100644 --- a/viengoos/ChangeLog +++ b/viengoos/ChangeLog @@ -1,3 +1,24 @@ +2008-01-16 Neal H. Walfield <neal@gnu.org> + + * thread.h (THREAD_WAIT_FUTEX): New define. + (THREAD_WAIT_DESTROY): Likewise. + (struct thread): Remove fields futex_block and futex_offset. Add + fields wait_reason and wait_reason_arg. Update users. + * object.h (folio_object_alloc): Take additional argument + return_code. Update users. + (folio_object_wait_queue_for_each): New macro. + * object.c: Include <hurd/thread.h>. + (folio_object_alloc): Take additional argument return_code. + Wake any threads blocked on the object being destroyed. + * server.c (server_loop): Update folio_object_alloc method + implementation to new API. Pass RETURN_CODE to the call to + folio_object_alloc. Implement the thread_wait_object_destroyed + method. + * t-activity.c (allocate_object): Update rm_folio_object_alloc use to + reflect API changes. + (test): Likewise. + * t-as.c (allocate_object): Likewise. + 2008-01-15 Neal H. Walfield <neal@gnu.org> * object.h (struct thread): New forward. diff --git a/viengoos/object.c b/viengoos/object.c index 8f6a44e..b724d0a 100644 --- a/viengoos/object.c +++ b/viengoos/object.c @@ -23,6 +23,7 @@ #include <hurd/stddef.h> #include <hurd/ihash.h> #include <hurd/folio.h> +#include <hurd/thread.h> #include <bit-array.h> #include "object.h" @@ -448,6 +449,7 @@ folio_object_alloc (struct activity *activity, int idx, enum cap_type type, struct object_policy policy, + uintptr_t return_code, struct object **objectp) { debug (4, "allocating %s at %d", cap_type_string (type), idx); @@ -488,6 +490,15 @@ folio_object_alloc (struct activity *activity, } } + /* Wake any thread's waiting on this object. We wake them even if + they are not waiting for this object's death. */ + struct thread *thread; + folio_object_wait_queue_for_each (activity, folio, idx, thread) + { + object_wait_queue_dequeue (activity, thread); + rm_thread_wait_object_destroyed_reply (thread->tid, return_code); + } + if (! object) object = object_find_soft (activity, oid, policy); if (object) diff --git a/viengoos/object.h b/viengoos/object.h index e341fbd..a5b75a6 100644 --- a/viengoos/object.h +++ b/viengoos/object.h @@ -373,13 +373,16 @@ extern void folio_free (struct activity *activity, struct folio *folio); /* Allocate an object of type TYPE using the PAGE page from the folio FOLIO. This implicitly destroys any existing object in that page. - If TYPE is cap_void, this is equivalent to calling - folio_object_free. If OBJECTP is not-NULL, then the in-memory - location of the object is returned in *OBJECTP. */ + If there were any waiters waiting for the descruction, they are + woken and passed RETURN_CODE. If TYPE is cap_void, this is + equivalent to calling folio_object_free. If OBJECTP is not-NULL, + then the in-memory location of the object is returned in + *OBJECTP. */ extern void folio_object_alloc (struct activity *activity, struct folio *folio, int page, enum cap_type type, struct object_policy policy, + uintptr_t return_code, struct object **objectp); /* Deallocate the object stored in page PAGE of folio FOLIO. */ @@ -388,7 +391,7 @@ folio_object_free (struct activity *activity, struct folio *folio, int page) { folio_object_alloc (activity, folio, page, cap_void, - OBJECT_POLICY_VOID, NULL); + OBJECT_POLICY_VOID, 0, NULL); } /* Return an object's position within its folio. */ @@ -456,8 +459,21 @@ extern void object_wait_queue_enqueue (struct activity *activity, extern void object_wait_queue_dequeue (struct activity *activity, struct thread *thread); -/* Iterate over each thread waiting on OBJECT. It is safe to call - object_wait_queue_dequeue. */ + +/* Iterate over each thread waiting on the object at IDX in FOLIO. It + is safe to call object_wait_queue_dequeue. */ +#define folio_object_wait_queue_for_each(__owqfe_activity, \ + __owqfe_folio, __owqfe_idx, \ + __owqfe_thread) \ + for (struct thread *__owqfe_next \ + = (struct thread *) \ + cap_to_object (__owqfe_activity, \ + &__owqfe_folio->objects[__owqfe_idx].wait_queue); \ + (__owqfe_thread = __owqfe_next) \ + && ((__owqfe_next = object_wait_queue_next (__owqfe_activity, \ + __owqfe_thread)) \ + || 1); /* do nothing. */) + #define object_wait_queue_for_each(__owqfe_activity, __owqfe_object, \ __owqfe_thread) \ for (struct thread *__owqfe_next \ diff --git a/viengoos/server.c b/viengoos/server.c index 2a3ca42..da2c517 100644 --- a/viengoos/server.c +++ b/viengoos/server.c @@ -396,12 +396,14 @@ server_loop (void) uint32_t idx; uint32_t type; struct object_policy policy; + uintptr_t return_code; addr_t object_addr; addr_t object_weak_addr; err = rm_folio_object_alloc_send_unmarshal (&msg, &principal_addr, &folio_addr, &idx, &type, &policy, + &return_code, &object_addr, &object_weak_addr); if (err) @@ -430,7 +432,8 @@ server_loop (void) addr_prefix (object_addr), addr_depth (object_addr)); struct object *object; - folio_object_alloc (principal, folio, idx, type, policy, + folio_object_alloc (principal, + folio, idx, type, policy, return_code, type == cap_void ? NULL : &object); if (type != cap_void) @@ -732,6 +735,23 @@ server_loop (void) break; } + case RM_thread_wait_object_destroyed: + { + addr_t addr; + err = rm_thread_wait_object_destroyed_send_unmarshal + (&msg, &principal_addr, &addr); + if (err) + REPLY (err); + + struct object *object = OBJECT (addr, -1, true); + + thread->wait_reason = THREAD_WAIT_DESTROY; + object_wait_queue_enqueue (principal, object, thread); + + do_reply = 0; + break; + } + case RM_activity_policy: { uintptr_t flags; @@ -811,7 +831,8 @@ server_loop (void) struct thread *t; object_wait_queue_for_each (principal, object1, t) - if (t->futex_block && t->futex_offset == offset1) + if (t->wait_reason == THREAD_WAIT_FUTEX + && t->wait_reason_arg == offset1) /* Got a match. */ { if (count < to_wake) @@ -833,7 +854,7 @@ server_loop (void) { object_wait_queue_dequeue (principal, t); - t->futex_offset = offset2; + t->wait_reason_arg = offset2; object_wait_queue_enqueue (principal, object2, t); count ++; @@ -886,8 +907,8 @@ server_loop (void) if (timeout) panic ("Timeouts not yet supported"); - thread->futex_block = 1; - thread->futex_offset = offset1; + thread->wait_reason = THREAD_WAIT_FUTEX; + thread->wait_reason_arg = offset1; object_wait_queue_enqueue (principal, object1, thread); diff --git a/viengoos/t-activity.c b/viengoos/t-activity.c index 15d7ad1..f04950a 100644 --- a/viengoos/t-activity.c +++ b/viengoos/t-activity.c @@ -27,7 +27,7 @@ allocate_object (enum cap_type type, addr_t addr) struct object *o; folio_object_alloc (root_activity, folio, object ++, - type, OBJECT_POLICY_DEFAULT, &o); + type, OBJECT_POLICY_DEFAULT, 0, &o); struct as_insert_rt rt; rt.cap = object_to_cap (o); @@ -79,7 +79,7 @@ test (void) /* Allocate a new activity. */ folio_object_alloc (activity, folio, obj ++, - cap_activity_control, OBJECT_POLICY_DEFAULT, + cap_activity_control, OBJECT_POLICY_DEFAULT, 0, &object); a[i].child = (struct activity *) object; @@ -88,7 +88,7 @@ test (void) assert (a[i].folio); folio_object_alloc (a[i].child, a[i].folio, 0, - cap_page, OBJECT_POLICY_DEFAULT, &a[i].page); + cap_page, OBJECT_POLICY_DEFAULT, 0, &a[i].page); assert (object_type (a[i].page) == cap_page); } diff --git a/viengoos/t-as.c b/viengoos/t-as.c index 9425c4d..df37c96 100644 --- a/viengoos/t-as.c +++ b/viengoos/t-as.c @@ -27,7 +27,7 @@ allocate_object (enum cap_type type, addr_t addr) struct object *o; folio_object_alloc (root_activity, folio, object ++, - type, OBJECT_POLICY_DEFAULT, &o); + type, OBJECT_POLICY_DEFAULT, 0, &o); struct as_insert_rt rt; rt.cap = object_to_cap (o); diff --git a/viengoos/thread.h b/viengoos/thread.h index b7ab288..3e0baf9 100644 --- a/viengoos/thread.h +++ b/viengoos/thread.h @@ -41,6 +41,17 @@ struct wait_queue_node struct cap prev; }; +enum + { + /* THREAD is blocked on an object wait for a futex. + WAIT_REASON_ARG holds the byte offset in the object on which it + is waiting. */ + THREAD_WAIT_FUTEX, + /* THREAD is blocked on an object waiting for the object to be + destroyed. */ + THREAD_WAIT_DESTROY, + }; + struct thread { /* User accessible fields. */ @@ -79,10 +90,10 @@ struct thread WAIT_QUEUE.NEXT designates the object. */ uint32_t wait_queue_tail : 1; - /* If waiting on a futex object. */ - uint32_t futex_block : 1; - /* The offset of the futex object. */ - uint32_t futex_offset : PAGESIZE_LOG2; + /* The event the thread is interested in. */ + uint32_t wait_reason : 28; + /* More information about the reason. */ + uint32_t wait_reason_arg; /* The object the thread is waiting on. */ struct wait_queue_node wait_queue; diff --git a/viengoos/viengoos.c b/viengoos/viengoos.c index e0e8ae1..e362287 100644 --- a/viengoos/viengoos.c +++ b/viengoos/viengoos.c @@ -261,7 +261,7 @@ system_task_load (void) struct object *object; int index = folio_index ++; folio_object_alloc (root_activity, folio, index, type, - OBJECT_POLICY_VOID, &object); + OBJECT_POLICY_VOID, 0, &object); if (! (desc_count < desc_max)) panic ("Initial task too large."); |