summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hurd/ChangeLog8
-rw-r--r--hurd/folio.h15
-rw-r--r--hurd/thread.h16
-rw-r--r--libhurd-mm/ChangeLog7
-rw-r--r--libhurd-mm/storage.c8
-rw-r--r--ruth/ChangeLog5
-rw-r--r--ruth/ruth.c55
-rw-r--r--viengoos/ChangeLog21
-rw-r--r--viengoos/object.c11
-rw-r--r--viengoos/object.h28
-rw-r--r--viengoos/server.c31
-rw-r--r--viengoos/t-activity.c6
-rw-r--r--viengoos/t-as.c2
-rw-r--r--viengoos/thread.h19
-rw-r--r--viengoos/viengoos.c2
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.");