summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2009-03-17 20:13:19 +0100
committerNeal H. Walfield <neal@gnu.org>2009-03-17 20:13:19 +0100
commit091da994d2839262a996c897de7df066dd48c843 (patch)
tree628356fdc4485a1902c5c5d48a091602efd9ac61
parentbe604c4968e84a622fa7b57b68f6ee45ea0715f2 (diff)
Batch object discardds.
-rw-r--r--libhurd-mm/anonymous.c70
-rw-r--r--libviengoos/viengoos/cap.h6
-rw-r--r--viengoos/server.c46
3 files changed, 106 insertions, 16 deletions
diff --git a/libhurd-mm/anonymous.c b/libhurd-mm/anonymous.c
index 0fa3289..f020315 100644
--- a/libhurd-mm/anonymous.c
+++ b/libhurd-mm/anonymous.c
@@ -465,7 +465,7 @@ mdestroy (struct map *map)
{
next = hurd_btree_storage_desc_next (node);
- storage_free (node->storage, false);
+ storage_free (node->storage, true);
#ifndef NDEBUG
/* When reallocating, we expect that the node field is 0.
@@ -508,7 +508,7 @@ mdestroy (struct map *map)
> map->offset + map->region.length - 1))
break;
- storage_free (storage_desc->storage, false);
+ storage_free (storage_desc->storage, true);
hurd_btree_storage_desc_detach (storage_descs, storage_desc);
#ifndef NDEBUG
@@ -573,6 +573,62 @@ advise (struct pager *pager,
{
case pager_advice_dontneed:
{
+ profile_region ("madvise(dontneed)");
+
+ 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_discard_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_discard_receive_marshal (mb->reply);
+ vg_object_discard_send_marshal (mb->request, false, addr,
+ mb->receiver);
+ discards = 1;
+ }
+ else
+ {
+ vg_message_append_data (mb->request,
+ sizeof (addr), (void *) &addr);
+ discards ++;
+ }
+ }
+
uintptr_t offset[2];
offset[0] = start | 1;
offset[1] = length;
@@ -598,14 +654,14 @@ advise (struct pager *pager,
|| storage_desc->offset >= start + length)
break;
- error_t err;
- err = vg_object_discard (anon->activity,
- storage_desc->storage);
- if (err)
- panic ("err: %d", err);
+ queue_clear (storage_desc->storage);
}
}
+ queue_clear (VG_ADDR_VOID);
+
+ profile_region_end ();
+
break;
}
diff --git a/libviengoos/viengoos/cap.h b/libviengoos/viengoos/cap.h
index 1e23eab..7d5a5b2 100644
--- a/libviengoos/viengoos/cap.h
+++ b/libviengoos/viengoos/cap.h
@@ -472,8 +472,10 @@ RPC(object_discarded_clear, 1, 1, 0,
OBJECT must have write authority. This does not set the object's
discarded bit and thus does not result in a fault. Instead, the
next access will see, e.g., zero-filled memory. */
-RPC(object_discard, 0, 0, 0
- /* cap_t activity, cap_t object, */)
+RPC(object_discard, 2, 1, 0
+ /* cap_t activity, cap_t object, */,
+ bool, mark_discarded, vg_addr_t/*[]*/, addr,
+ int, count)
enum
{
diff --git a/viengoos/server.c b/viengoos/server.c
index 2c74018..c5497a6 100644
--- a/viengoos/server.c
+++ b/viengoos/server.c
@@ -898,6 +898,9 @@ dispatcher (uintptr_t flags,
else
thread_suspend (thread);
+ do_debug (1)
+ profile_start (label, vg_method_id_string (label), NULL);
+
error_t err;
switch (label)
{
@@ -1449,20 +1452,46 @@ dispatcher (uintptr_t flags,
case VG_object_discard:
{
- err = vg_object_discard_send_unmarshal (message, NULL);
+ bool mark_discarded;
+ vg_addr_t first;
+ err = vg_object_discard_send_unmarshal (message,
+ &mark_discarded, &first,
+ NULL);
if (err)
REPLY (err);
DEBUG (4, VG_ADDR_FMT, VG_ADDR_PRINTF (target_messenger));
- struct vg_folio *folio = objects_folio (principal, target);
+ vg_addr_t *addr = (void *) vg_message_data (message)
+ + 2 * sizeof (uintptr_t);
+ assert (VG_ADDR_EQ (*addr, first));
+
+ int count = ((vg_message_data_count (message) - 2 * sizeof (uintptr_t))
+ / sizeof (vg_addr_t));
+ int i;
+ for (i = 0; i < count; i ++)
+ {
+ struct vg_cap cap = CAP (target_root, addr[i], -1, true);
+ if (cap.type == vg_cap_void)
+ /* It may already be discarded. */
+ continue;
+ if (vg_cap_type_weak_p (cap.type))
+ REPLY (EPERM);
+
+ struct vg_object *object = vg_cap_to_object (principal, &cap);
+ struct vg_folio *folio = objects_folio (principal, object);
+ int offset = objects_folio_offset (object);
- folio_object_content_set (folio,
- objects_folio_offset (target), false);
- memory_object_destroy (principal, target);
- memory_frame_free ((uintptr_t) target);
+ folio_object_content_set (folio, offset, false);
- vg_object_discard_reply (activity, reply);
+ memory_object_destroy (principal, object);
+ memory_frame_free ((uintptr_t) object);
+
+ if (mark_discarded)
+ folio_object_discarded_set (folio, offset, true);
+ }
+
+ vg_object_discard_reply (activity, reply, i);
break;
}
@@ -2070,6 +2099,9 @@ dispatcher (uintptr_t flags,
DEBUG (1, "Didn't handle message with label %"PRIdPTR, label);
break;
}
+
+ do_debug (1)
+ profile_end (label);
}