When uvm pivots are enabled, allocations
with an address hint provided by the user program are
handled by the uaddr_hint selector.

I'd like to remove the uaddr_hint selector. The uaddr_rnd selector
already deals with hinted allocations correctly, so why not use
it for hinted allocations in the pivot selector?

This diff is a part of making pivots work.
Getting rid of the hint selectors makes the code simpler.
I'd to commit this part first, to make the actual pivot
diffs smaller.

ok?

Some more details:

If you have multiple selectors per address space that manage
overlapping address ranges, some selectors have priority
over others. E.g. only the brk selector is allowed to make
allocations within the brk area. The rnd selector
gets all these checks right, but the hint selector does
not, which causes panics when you use pivots and try to
do a hinted allocation within the brk area.

So better use the code which is known to work for hinted
allocations. Once pivots are enabled, maybe the parts of the
rnd allocator that deal with hinted allocations can be factored
out into a common function.

Index: uvm/uvm_addr.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_addr.c,v
retrieving revision 1.22
diff -u -p -r1.22 uvm_addr.c
--- uvm/uvm_addr.c      16 Sep 2016 02:50:54 -0000      1.22
+++ uvm/uvm_addr.c      14 Jan 2017 05:53:17 -0000
@@ -46,17 +46,10 @@
 
 /* Pool with uvm_addr_state structures. */
 struct pool uaddr_pool;
-struct pool uaddr_hint_pool;
 struct pool uaddr_bestfit_pool;
 struct pool uaddr_pivot_pool;
 struct pool uaddr_rnd_pool;
 
-/* uvm_addr state for hint based selector. */
-struct uaddr_hint_state {
-       struct uvm_addr_state            uaddr;
-       vsize_t                          max_dist;
-};
-
 /* uvm_addr state for bestfit selector. */
 struct uaddr_bestfit_state {
        struct uvm_addr_state            ubf_uaddr;
@@ -118,7 +111,6 @@ void                         uaddr_kremove(struct vm_map *,
 void                    uaddr_kbootstrapdestroy(struct uvm_addr_state *);
 
 void                    uaddr_destroy(struct uvm_addr_state *);
-void                    uaddr_hint_destroy(struct uvm_addr_state *);
 void                    uaddr_kbootstrap_destroy(struct uvm_addr_state *);
 void                    uaddr_rnd_destroy(struct uvm_addr_state *);
 void                    uaddr_bestfit_destroy(struct uvm_addr_state *);
@@ -138,10 +130,6 @@ int                         uaddr_rnd_select(struct vm_map 
*,
                            struct uvm_addr_state *, struct vm_map_entry **,
                            vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t,
                            vaddr_t);
-int                     uaddr_hint_select(struct vm_map *,
-                           struct uvm_addr_state*, struct vm_map_entry **,
-                           vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t,
-                           vaddr_t);
 int                     uaddr_bestfit_select(struct vm_map *,
                            struct uvm_addr_state*, struct vm_map_entry **,
                            vaddr_t *, vsize_t, vaddr_t, vaddr_t, vm_prot_t,
@@ -290,8 +278,6 @@ uvm_addr_init(void)
 {
        pool_init(&uaddr_pool, sizeof(struct uvm_addr_state), 0,
            IPL_VM, PR_WAITOK, "uaddr", NULL);
-       pool_init(&uaddr_hint_pool, sizeof(struct uaddr_hint_state), 0,
-           IPL_VM, PR_WAITOK, "uaddrhint", NULL);
        pool_init(&uaddr_bestfit_pool, sizeof(struct uaddr_bestfit_state), 0,
            IPL_VM, PR_WAITOK, "uaddrbest", NULL);
        pool_init(&uaddr_pivot_pool, sizeof(struct uaddr_pivot_state), 0,
@@ -740,116 +726,6 @@ uaddr_rnd_print(struct uvm_addr_state *u
 #endif
 
 /*
- * An allocator that selects an address within distance of the hint.
- *
- * If no hint is given, the allocator refuses to allocate.
- */
-const struct uvm_addr_functions uaddr_hint_functions = {
-       .uaddr_select = &uaddr_hint_select,
-       .uaddr_destroy = &uaddr_hint_destroy,
-       .uaddr_name = "uaddr_hint"
-};
-
-/*
- * Create uaddr_hint state.
- */
-struct uvm_addr_state *
-uaddr_hint_create(vaddr_t minaddr, vaddr_t maxaddr, vsize_t max_dist)
-{
-       struct uaddr_hint_state *ua_hint;
-
-       KASSERT(uaddr_hint_pool.pr_size == sizeof(*ua_hint));
-
-       ua_hint = pool_get(&uaddr_hint_pool, PR_WAITOK);
-       ua_hint->uaddr.uaddr_minaddr = minaddr;
-       ua_hint->uaddr.uaddr_maxaddr = maxaddr;
-       ua_hint->uaddr.uaddr_functions = &uaddr_hint_functions;
-       ua_hint->max_dist = max_dist;
-       return &ua_hint->uaddr;
-}
-
-/*
- * Destroy uaddr_hint state.
- */
-void
-uaddr_hint_destroy(struct uvm_addr_state *uaddr)
-{
-       pool_put(&uaddr_hint_pool, uaddr);
-}
-
-/*
- * Hint selector.
- *
- * Attempts to find an address that is within max_dist of the hint.
- */
-int
-uaddr_hint_select(struct vm_map *map, struct uvm_addr_state *uaddr_param,
-    struct vm_map_entry **entry_out, vaddr_t *addr_out,
-    vsize_t sz, vaddr_t align, vaddr_t offset,
-    vm_prot_t prot, vaddr_t hint)
-{
-       struct uaddr_hint_state *uaddr =
-           (struct uaddr_hint_state *)uaddr_param;
-       vsize_t                  before_gap, after_gap;
-       vaddr_t                  low, high;
-       int                      dir;
-
-       if (hint == 0)
-               return ENOMEM;
-
-       /* Calculate upper and lower bound for selected address. */
-       high = hint + uaddr->max_dist;
-       if (high < hint)        /* overflow */
-               high = map->max_offset;
-       high = MIN(high, uaddr->uaddr.uaddr_maxaddr);
-       if (high < sz)
-               return ENOMEM;  /* Protect against underflow. */
-       high -= sz;
-
-       /* Calculate lower bound for selected address. */
-       low = hint - uaddr->max_dist;
-       if (low > hint)         /* underflow */
-               low = map->min_offset;
-       low = MAX(low, uaddr->uaddr.uaddr_minaddr);
-
-       /* Search strategy setup. */
-       before_gap = PAGE_SIZE +
-           (arc4random_uniform(UADDR_HINT_MAXGAP) & ~(vaddr_t)PAGE_MASK);
-       after_gap = PAGE_SIZE +
-           (arc4random_uniform(UADDR_HINT_MAXGAP) & ~(vaddr_t)PAGE_MASK);
-       dir = (arc4random() & 0x01) ? 1 : -1;
-
-       /*
-        * Try to search:
-        * - forward,  with gap
-        * - backward, with gap
-        * - forward,  without gap
-        * - backward, without gap
-        * (Where forward is in the direction specified by dir and
-        * backward is in the direction specified by -dir).
-        */
-       if (uvm_addr_linsearch(map, uaddr_param,
-           entry_out, addr_out, hint, sz, align, offset,
-           dir, low, high, before_gap, after_gap) == 0)
-               return 0;
-       if (uvm_addr_linsearch(map, uaddr_param,
-           entry_out, addr_out, hint, sz, align, offset,
-           -dir, low, high, before_gap, after_gap) == 0)
-               return 0;
-
-       if (uvm_addr_linsearch(map, uaddr_param,
-           entry_out, addr_out, hint, sz, align, offset,
-           dir, low, high, 0, 0) == 0)
-               return 0;
-       if (uvm_addr_linsearch(map, uaddr_param,
-           entry_out, addr_out, hint, sz, align, offset,
-           -dir, low, high, 0, 0) == 0)
-               return 0;
-
-       return ENOMEM;
-}
-
-/*
  * Kernel allocation bootstrap logic.
  */
 const struct uvm_addr_functions uaddr_kernel_functions = {
@@ -1242,9 +1118,16 @@ uaddr_pivot_select(struct vm_map *map, s
        vsize_t                          before_gap, after_gap;
        int                              err;
 
-       /* Hint must be handled by dedicated hint allocator. */
-       if (hint != 0)
-               return EINVAL;
+       /*
+        * When we have a hint, use the rnd allocator that finds the
+        * area that is closest to the hint, if there is such an area.
+        */
+       if (hint != 0) {
+               if (uaddr_rnd_select(map, uaddr_p, entry_out, addr_out,
+                   sz, align, offset, prot, hint) == 0)
+                       return 0;
+               return ENOMEM;
+       }
 
        /*
         * Select a random pivot and a random gap sizes around the allocation.
Index: uvm/uvm_addr.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_addr.h,v
retrieving revision 1.6
diff -u -p -r1.6 uvm_addr.h
--- uvm/uvm_addr.h      16 Sep 2016 01:51:40 -0000      1.6
+++ uvm/uvm_addr.h      14 Jan 2017 05:53:17 -0000
@@ -90,7 +90,6 @@ int                    uvm_addr_invoke(struct vm_map *,
 struct uvm_addr_state  *uaddr_lin_create(vaddr_t, vaddr_t);
 #endif
 struct uvm_addr_state  *uaddr_rnd_create(vaddr_t, vaddr_t);
-struct uvm_addr_state  *uaddr_hint_create(vaddr_t, vaddr_t, vsize_t);
 #ifndef SMALL_KERNEL
 struct uvm_addr_state  *uaddr_bestfit_create(vaddr_t, vaddr_t);
 struct uvm_addr_state  *uaddr_pivot_create(vaddr_t, vaddr_t);
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.226
diff -u -p -r1.226 uvm_map.c
--- uvm/uvm_map.c       7 Nov 2016 00:26:33 -0000       1.226
+++ uvm/uvm_map.c       14 Jan 2017 05:53:18 -0000
@@ -5291,9 +5291,6 @@ uvm_map_setup_md(struct vm_map *map)
                min = VMMAP_MIN_ADDR;
 
 #if 0  /* Cool stuff, not yet */
-       /* Hinted allocations. */
-       map->uaddr_any[1] = uaddr_hint_create(min, max, 1024 * 1024 * 1024);
-
        /* Executable code is special. */
        map->uaddr_exe = uaddr_rnd_create(min, I386_MAX_EXE_ADDR);
        /* Place normal allocations beyond executable mappings. */
@@ -5323,13 +5320,6 @@ uvm_map_setup_md(struct vm_map *map)
                min = VMMAP_MIN_ADDR;
 
 #if 0  /* Cool stuff, not yet */
-       /* Hinted allocations above 4GB */
-       map->uaddr_any[0] =
-           uaddr_hint_create(0x100000000ULL, max, 1024 * 1024 * 1024);
-       /* Hinted allocations below 4GB */
-       map->uaddr_any[1] = uaddr_hint_create(min, 0x100000000ULL,
-           1024 * 1024 * 1024);
-       /* Normal allocations, always above 4GB */
        map->uaddr_any[3] = uaddr_pivot_create(MAX(min, 0x100000000ULL), max);
 #else  /* Crappy stuff, for now */
        map->uaddr_any[0] = uaddr_rnd_create(min, max);
@@ -5356,9 +5346,6 @@ uvm_map_setup_md(struct vm_map *map)
                min = VMMAP_MIN_ADDR;
 
 #if 0  /* Cool stuff, not yet */
-       /* Hinted allocations. */
-       map->uaddr_any[1] = uaddr_hint_create(min, max, 1024 * 1024 * 1024);
-       /* Normal allocations. */
        map->uaddr_any[3] = uaddr_pivot_create(min, max);
 #else  /* Crappy stuff, for now */
        map->uaddr_any[0] = uaddr_rnd_create(min, max);

Reply via email to