diff options
author | Neal H. Walfield <neal@gnu.org> | 2009-03-17 20:13:19 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2009-03-17 20:13:19 +0100 |
commit | 091da994d2839262a996c897de7df066dd48c843 (patch) | |
tree | 628356fdc4485a1902c5c5d48a091602efd9ac61 | |
parent | be604c4968e84a622fa7b57b68f6ee45ea0715f2 (diff) |
Batch object discardds.
-rw-r--r-- | libhurd-mm/anonymous.c | 70 | ||||
-rw-r--r-- | libviengoos/viengoos/cap.h | 6 | ||||
-rw-r--r-- | viengoos/server.c | 46 |
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); } |