> Date: Sun, 15 Jan 2017 15:06:50 +0100
> From: Stefan Kempf <sisnk...@gmail.com>
> 
> 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?

No objection from me.

> 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