> 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); > >