2011/4/5 Anton Maksimenkov <anton...@gmail.com>:
> I have some idea related to allocator for (! __HAVE_PMAP_DIRECT) case.
...
> My idea is how to resolve that loop by another way.
> We must keep track the number of free kentries. And when we see, in
> uvm_mapent_alloc(), that there is only 1 kentry remains then we must
> allocate more entries immediately. This last kentry may be used by
> uvm_map. So, when it will be done we'll have a page, divide it to new
> fresh entries, and now we safe.
> Then we can proceed further.

Sorry, I missed the main trick.
There are must be some flag which tells the uvm_mapent_alloc() that it
was called recursively, so in that case it must use and return last
free kentry and not call km_alloc() again.
Furthermore, I think that it must check that if it is called
recursively then splvm() was already done.

>  struct vm_map_entry *
>  uvm_mapent_alloc(struct vm_map *map, int flags)
>  {
> -       struct vm_map_entry *me, *ne;
> +       struct vm_map_entry *me;
...
if ("recursion flag") {
    me = uvm.kentry_free;
    if (me == NULL)
        panic("uvm_mapent_alloc: uvm.kentry_free is NULL in recursive call");
    uvm.kentry_free = me->next; // NULL
    uvm.numof_free_kentries--; // 0
    uvmexp.kmapent++;
    me->flags = UVM_MAP_STATIC;
} else if (map->flags & VM_MAP_INTRSAFE || cold) {
> +               /*
> +                * If there is only one kentry remains we MUST
> +                * allocate more (page of) entries.
> +                * Because uvm_km_kmemalloc (called by uvm_km_alloc)
> +                * may use that last kentry when it tries to uvm_map new
> +                * physical page.
> +                * Then this virtual address of that mapped physpage
> +                * will be returned to us (by uvm_km_alloc) so we can
> +                * allocate more kentries from it and proceed
> +                */
> +               if (uvm.numof_free_kentries == 1 || cold) {
> +                       me = km_alloc(PAGE_SIZE, &kv_page, &kp_dirty,

here setup and pass the "recursion flag" into km_alloc() and it must
pass it into uvm_map() and it must pass it into the
uvm_mapent_alloc().

>                            &kd_nowait);

And, as it was pointed by art@, in the km_alloc() the kmem_map must be
used instead of kernel_map.

Again, excuse me for ugly style of my "diffs"...
--
antonvm

Reply via email to