summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2008-12-18 22:54:15 +0100
committerNeal H. Walfield <neal@gnu.org>2008-12-18 22:54:15 +0100
commit207770cea7fece43bf5517fec7abd88a3a7d6146 (patch)
tree6f41abd1dc4782f34b339b00da956d0c778ef1b7
parentf5cfa7cbb8a2fff68cf87a3a685428507ce977b4 (diff)
Support batching requests for object_discarded_clear.
libviengoos/ 2008-12-18 Neal H. Walfield <neal@gnu.org> * viengoos/cap.h (object_discarded_clear): Take additional parameter count. Take multiple object addresses. viengoos/ 2008-12-18 Neal H. Walfield <neal@gnu.org> * server.c (server_loop): Handle multiple objects in object_discarded_clear. libhurd-mm/ 2008-12-18 Neal H. Walfield <neal@gnu.org> * anonymous.c (fault): Batch object discard requests.
-rw-r--r--libhurd-mm/ChangeLog4
-rw-r--r--libhurd-mm/anonymous.c66
-rw-r--r--libviengoos/ChangeLog5
-rw-r--r--libviengoos/viengoos/cap.h17
-rw-r--r--viengoos/ChangeLog5
-rw-r--r--viengoos/server.c114
6 files changed, 148 insertions, 63 deletions
diff --git a/libhurd-mm/ChangeLog b/libhurd-mm/ChangeLog
index a74f7d7..3a9a35b 100644
--- a/libhurd-mm/ChangeLog
+++ b/libhurd-mm/ChangeLog
@@ -1,5 +1,9 @@
2008-12-18 Neal H. Walfield <neal@gnu.org>
+ * anonymous.c (fault): Batch object discard requests.
+
+2008-12-18 Neal H. Walfield <neal@gnu.org>
+
* exceptions.c (hurd_activation_state_alloc): Cast UTCB to a void *.
2008-12-18 Neal H. Walfield <neal@gnu.org>
diff --git a/libhurd-mm/anonymous.c b/libhurd-mm/anonymous.c
index dac8309..a653ae2 100644
--- a/libhurd-mm/anonymous.c
+++ b/libhurd-mm/anonymous.c
@@ -229,6 +229,59 @@ fault (struct pager *pager, uintptr_t offset, int count, bool read_only,
hurd_btree_storage_desc_t *storage_descs;
storage_descs = (hurd_btree_storage_desc_t *) &anon->storage;
+ struct hurd_message_buffer *mb = NULL;
+ int discards = 0;
+ void queue_clear (vg_addr_t addr)
+ {
+ if (mb
+ && (VG_ADDR_IS_VOID (addr)
+ || vg_message_space (mb->request) < sizeof (vg_addr_t)))
+ {
+ hurd_activation_message_register (mb);
+ error_t err = vg_ipc (VG_IPC_RECEIVE | VG_IPC_SEND
+ | VG_IPC_RECEIVE_ACTIVATE
+ | VG_IPC_SEND_SET_THREAD_TO_CALLER
+ | VG_IPC_SEND_SET_ASROOT_TO_CALLERS
+ | VG_IPC_RECEIVE_SET_THREAD_TO_CALLER
+ | VG_IPC_RECEIVE_SET_ASROOT_TO_CALLERS,
+ VG_ADDR_VOID,
+ mb->receiver_strong, VG_ADDR_VOID,
+ VG_ADDR_VOID, VG_ADDR_VOID,
+ mb->sender, VG_ADDR_VOID);
+ if (err)
+ hurd_activation_message_unregister (mb);
+ else
+ {
+ int i;
+ err = vg_object_discarded_clear_reply_unmarshal (mb->reply, &i);
+ assert (! err);
+ assert (i == discards);
+ }
+
+ hurd_message_buffer_free (mb);
+ mb = NULL;
+ discards = 0;
+ }
+
+ if (VG_ADDR_IS_VOID (addr))
+ return;
+
+ if (! mb)
+ {
+ mb = hurd_message_buffer_alloc ();
+
+ vg_object_discarded_clear_receive_marshal (mb->reply);
+ vg_object_discarded_clear_send_marshal (mb->request, addr,
+ mb->receiver);
+ discards = 1;
+ }
+ else
+ {
+ vg_message_append_data (mb->request, sizeof (addr), (void *) &addr);
+ discards ++;
+ }
+ }
+
int i;
for (i = 0; i < count; i ++)
{
@@ -248,14 +301,11 @@ fault (struct pager *pager, uintptr_t offset, int count, bool read_only,
assert (storage_desc);
assert (anon->policy.discardable);
- error_t err;
/* We pass the fault address and not the underlying
storage address as object_discarded_clear also
returns a mapping and we are likely to access the
data at the fault address. */
- err = vg_object_discarded_clear (VG_ADDR_VOID, VG_ADDR_VOID,
- storage_desc->storage);
- assertx (err == 0, "%d", err);
+ queue_clear (storage_desc->storage);
debug (5, "Clearing discarded bit for %p / " VG_ADDR_FMT,
(void *) fault_addr + i * PAGESIZE,
@@ -300,8 +350,9 @@ fault (struct pager *pager, uintptr_t offset, int count, bool read_only,
page.type = vg_cap_page;
VG_CAP_POLICY_SET (&page, anon->policy);
- vg_addr_t addr = vg_addr_chop (VG_PTR_TO_ADDR (fault_addr + i * PAGESIZE),
- PAGESIZE_LOG2);
+ vg_addr_t addr
+ = vg_addr_chop (VG_PTR_TO_ADDR (fault_addr + i * PAGESIZE),
+ PAGESIZE_LOG2);
as_ensure_use
(addr,
@@ -323,6 +374,9 @@ fault (struct pager *pager, uintptr_t offset, int count, bool read_only,
0, PAGESIZE_LOG2));
}
+ /* Flush any pending discards. */
+ queue_clear (VG_ADDR_VOID);
+
#if 0
int faulted;
for (i = 0; i < count; i += faulted)
diff --git a/libviengoos/ChangeLog b/libviengoos/ChangeLog
index 3006d73..180a7a4 100644
--- a/libviengoos/ChangeLog
+++ b/libviengoos/ChangeLog
@@ -1,5 +1,10 @@
2008-12-18 Neal H. Walfield <neal@gnu.org>
+ * viengoos/cap.h (object_discarded_clear): Take additional
+ parameter count. Take multiple object addresses.
+
+2008-12-18 Neal H. Walfield <neal@gnu.org>
+
* viengoos/misc.h (vg_method_id_string): Handle VG_messenger_id.
2008-12-18 Neal H. Walfield <neal@gnu.org>
diff --git a/libviengoos/viengoos/cap.h b/libviengoos/viengoos/cap.h
index b456d34..50562d9 100644
--- a/libviengoos/viengoos/cap.h
+++ b/libviengoos/viengoos/cap.h
@@ -417,7 +417,7 @@ enum
VG_CAP_COPY_PRIORITY_SET = 1 << 5,
};
-/* Copy the capability in capability slot SOURCE to the slot at VG_ADDR
+/* Copy the capability in capability slot SOURCE to the slot at ADDR
in the object OBJECT. If OBJECT is VG_ADDR_VOID, then the calling
thread's address space root is used.
@@ -445,21 +445,26 @@ RPC(cap_copy, 5, 0, 0,
cap_t, source_object, vg_addr_t, source_addr,
uintptr_t, flags, struct vg_cap_properties, properties)
-/* Overwrite the capability slot at VG_ADDR in the object OBJECT with a
+/* Overwrite the capability slot at ADDR in the object OBJECT with a
void capability. */
RPC(cap_rubout, 1, 0, 0,
/* cap_t activity, cap_t object, */ vg_addr_t, addr)
-/* Returns the public bits of the capability at address VG_ADDR in OBJECT
+/* Returns the public bits of the capability at address ADDR in OBJECT
in TYPE and VG_CAP_PROPERTIES. */
RPC(cap_read, 1, 2, 0,
/* cap_t activity, cap_t object, */ vg_addr_t, addr,
/* Out: */
uintptr_t, type, struct vg_cap_properties, properties)
-/* Clear the discarded bit of the object at VG_ADDR in object OBJECT. */
-RPC(object_discarded_clear, 1, 0, 0,
- /* cap_t activity, cap_t object, */ vg_addr_t, addr)
+/* Clear the discarded bit of the objects at ADDR in object OBJECT.
+ Note: this function takes multiple addresses. Add further
+ addresses manually using vg_message_add. COUNT indicates the
+ number of objects successfully discarded. Stops after the first
+ error. */
+RPC(object_discarded_clear, 1, 1, 0,
+ /* cap_t activity, cap_t object, */ vg_addr_t, addr,
+ int, count)
/* If the object designated by OBJECT is in memory, discard it.
OBJECT must have write authority. This does not set the object's
diff --git a/viengoos/ChangeLog b/viengoos/ChangeLog
index d30da99..bc19cff 100644
--- a/viengoos/ChangeLog
+++ b/viengoos/ChangeLog
@@ -1,5 +1,10 @@
2008-12-18 Neal H. Walfield <neal@gnu.org>
+ * server.c (server_loop): Handle multiple objects in
+ object_discarded_clear.
+
+2008-12-18 Neal H. Walfield <neal@gnu.org>
+
* server.c (server_loop): Set SLOT to 0, not TARGET.
2008-12-18 Neal H. Walfield <neal@gnu.org>
diff --git a/viengoos/server.c b/viengoos/server.c
index c1cdb90..e423c14 100644
--- a/viengoos/server.c
+++ b/viengoos/server.c
@@ -1449,71 +1449,83 @@ server_loop (void)
DEBUG (4, VG_ADDR_FMT, VG_ADDR_PRINTF (object_addr));
- /* We can't look up the object use OBJECT as object_lookup
- returns NULL if the object's discardable bit is set!
- Instead, we lookup the capability, find the object's
- folio and then clear its discarded bit. */
- struct vg_cap cap = CAP (&thread->aspace, object_addr, -1, true);
- if (cap.type == vg_cap_void)
- REPLY (ENOENT);
- if (vg_cap_type_weak_p (cap.type))
- REPLY (EPERM);
-
- int idx = (cap.oid % (1 + VG_FOLIO_OBJECTS)) - 1;
- vg_oid_t foid = cap.oid - idx - 1;
+ vg_addr_t *addr = (void *) vg_message_data (message)
+ + sizeof (uintptr_t);
+ int count = ((vg_message_data_count (message) - sizeof (uintptr_t))
+ / sizeof (vg_addr_t));
+ int i;
+ for (i = 0; i < count; i ++)
+ {
+ /* We can't look up the object use OBJECT as object_lookup
+ returns NULL if the object's discardable bit is set!
+ Instead, we lookup the capability, find the object's
+ folio and then clear its discarded bit. */
+ struct vg_cap cap = CAP (target_root, addr[i], -1, true);
+ if (cap.type == vg_cap_void)
+ REPLY (ENOENT);
+ if (vg_cap_type_weak_p (cap.type))
+ REPLY (EPERM);
- struct vg_folio *folio = (struct vg_folio *)
- object_find (activity, foid, VG_OBJECT_POLICY_VOID);
+ int idx = (cap.oid % (1 + VG_FOLIO_OBJECTS)) - 1;
+ vg_oid_t foid = cap.oid - idx - 1;
- if (folio_object_version (folio, idx) != cap.version)
- REPLY (ENOENT);
+ struct vg_folio *folio = (struct vg_folio *)
+ object_find (activity, foid, VG_OBJECT_POLICY_VOID);
- bool was_discarded = folio_object_discarded (folio, idx);
- folio_object_discarded_set (folio, idx, false);
+ if (folio_object_version (folio, idx) != cap.version)
+ REPLY (ENOENT);
- vg_object_discarded_clear_reply (activity, reply);
+ bool was_discarded = folio_object_discarded (folio, idx);
+ folio_object_discarded_set (folio, idx, false);
#if 0
- /* XXX: Surprisingly, it appears that this may be more
- expensive than just faulting the pages normally. This
- needs more investivation. */
- if (was_discarded
- && cap.type == vg_cap_page
- && VG_CAP_GUARD_BITS (&cap) == 0
- && (vg_addr_depth (object_addr) == VG_ADDR_BITS - PAGESIZE_LOG2))
- /* The target object was discarded, appears to be a page
- and seems to be installed at a point where it would
- appear in the hardware address space. If this is
- really the case, then we can map it now and save a
- fault later. */
- {
- profile_region ("object_discard-prefault");
-
- struct vg_object *page = vg_cap_to_object (principal, &cap);
- if (page)
+ /* XXX: Surprisingly, it appears that this may be more
+ expensive than just faulting the pages normally. This
+ needs more investigation. */
+ if (target == thread
+ && was_discarded
+ && cap.type == vg_cap_page
+ && VG_CAP_GUARD_BITS (&cap) == 0
+ && (vg_addr_depth (object_addr)
+ == VG_ADDR_BITS - PAGESIZE_LOG2))
+ /* The target object was discarded, appears to be a page
+ and seems to be installed at a point where it would
+ appear in the hardware address space. If this is
+ really the case, then we can map it now and save a
+ fault later. */
{
- object_to_object_desc (page)->mapped = true;
+ profile_region ("object_discard-prefault");
- l4_fpage_t fpage = l4_fpage ((uintptr_t) page, PAGESIZE);
- fpage = l4_fpage_add_rights (fpage,
- L4_FPAGE_READABLE
- | L4_FPAGE_WRITABLE);
+ struct vg_object *page = vg_cap_to_object (principal, &cap);
+ if (page)
+ {
+ object_to_object_desc (page)->mapped = true;
- uintptr_t page_addr = vg_addr_prefix (object_addr);
+ l4_fpage_t fpage = l4_fpage ((uintptr_t) page,
+ PAGESIZE);
+ fpage = l4_fpage_add_rights (fpage,
+ L4_FPAGE_READABLE
+ | L4_FPAGE_WRITABLE);
- l4_map_item_t map_item = l4_map_item (fpage, page_addr);
+ uintptr_t page_addr = vg_addr_prefix (object_addr);
- l4_msg_append_map_item (msg, map_item);
+ l4_map_item_t map_item = l4_map_item (fpage, page_addr);
- DEBUG (4, "Prefaulting "VG_ADDR_FMT"(%x) <- %p (%x/%x/%x)",
- VG_ADDR_PRINTF (object_addr), page_addr,
- page, l4_address (fpage), l4_size (fpage),
- l4_rights (fpage));
- }
+ l4_msg_append_map_item (msg, map_item);
- profile_region_end ();
- }
+ DEBUG (4, "Prefaulting "VG_ADDR_FMT
+ "(%x) <- %p (%x/%x/%x)",
+ VG_ADDR_PRINTF (object_addr), page_addr,
+ page, l4_address (fpage), l4_size (fpage),
+ l4_rights (fpage));
+ }
+
+ profile_region_end ();
+ }
#endif
+ }
+
+ vg_object_discarded_clear_reply (activity, reply, i);
break;
}