userland can ask for an array of a processes memory mappings via
sysctl, starting from a specified point. currently that starting
point is found by iterating over the mappings from start to finish,
but because the mappings are in an RBT we can do a binary search
instead.

ok?

Index: uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.231
diff -u -p -r1.231 uvm_map.c
--- uvm_map.c   17 May 2017 08:13:33 -0000      1.231
+++ uvm_map.c   20 Jun 2017 00:35:50 -0000
@@ -5211,7 +5211,7 @@ int
 uvm_map_fill_vmmap(struct vm_map *map, struct kinfo_vmentry *kve,
     size_t *lenp)
 {
-       struct vm_map_entry *entry;
+       struct vm_map_entry *entry = NULL, *tmp;
        vaddr_t start;
        int cnt, maxcnt, error = 0;
 
@@ -5229,13 +5229,21 @@ uvm_map_fill_vmmap(struct vm_map *map, s
        start = (vaddr_t)kve[0].kve_start;
 
        vm_map_lock(map);
-       RBT_FOREACH(entry, uvm_map_addr, &map->addr) {
-               if (cnt == maxcnt) {
-                       error = ENOMEM;
+       /* look for the starting address by doing nfind (by hand) */
+       tmp = RBT_ROOT(uvm_map_addr, &map->addr);
+       while (tmp != NULL) {
+               if (start < tmp->start) {
+                       entry = tmp;
+                       tmp = RBT_LEFT(uvm_map_addr, tmp);
+               } else if (start > tmp->start) {
+                       tmp = RBT_RIGHT(uvm_map_addr, tmp);
+               } else { /* exact match */
+                       entry = tmp;
                        break;
                }
-               if (start != 0 && entry->start < start)
-                       continue;
+       }
+
+       while (entry != NULL) {
                kve->kve_start = entry->start;
                kve->kve_end = entry->end;
                kve->kve_guard = entry->guard;
@@ -5249,8 +5257,14 @@ uvm_map_fill_vmmap(struct vm_map *map, s
                kve->kve_advice = entry->advice;
                kve->kve_inheritance = entry->inheritance;
                kve->kve_flags = entry->flags;
+
+               if (++cnt == maxcnt) {
+                       error = ENOMEM;
+                       break;
+               }
+
                kve++;
-               cnt++;
+               entry = RBT_NEXT(uvm_map_addr, entry);
        }
        vm_map_unlock(map);
 

Reply via email to