*参照元 [#pa89e1c3] #backlinks *説明 [#rb64599a] -パス: [[linux-2.6.33/mm/vmalloc.c]] -FIXME: これは何? --説明 **引数 [#k66244e4] -unsigned long size -- -unsigned long align -- -unsigned long vstar -- -unsigned long vend -- -int node -- -gfp_t gfp_mask -- --[[linux-2.6.33/gfp_t]] **返り値 [#x2834ea4] -struct vmap_area * -- --[[linux-2.6.33/vmap_area]] **参考 [#y379bfea] *実装 [#w52d8916] /* * Allocate a region of KVA of the specified size and alignment, within the * vstart and vend. */ static struct vmap_area *alloc_vmap_area(unsigned long size, unsigned long align, unsigned long vstart, unsigned long vend, int node, gfp_t gfp_mask) { struct vmap_area *va; struct rb_node *n; unsigned long addr; int purged = 0; - --[[linux-2.6.33/rb_node]] BUG_ON(!size); BUG_ON(size & ~PAGE_MASK); -サイズが 0 だったり、ページサイズの境界に合っていない場合はバグ --[[linux-2.6.33/BUG_ON()]] - --[[linux-2.6.33/PAGE_MASK]] va = kmalloc_node(sizeof(struct vmap_area), gfp_mask & GFP_RECLAIM_MASK, node); - --[[linux-2.6.33/kmalloc_node()]] - --[[linux-2.6.33/GFP_RECLAIM_MASK]] if (unlikely(!va)) return ERR_PTR(-ENOMEM); - --[[linux-2.6.33/unlikely()]] - --[[linux-2.6.33/ERR_PTR()]] - --[[linux-2.6.33/ENOMEM]] retry: addr = ALIGN(vstart, align); - --[[linux-2.6.33/ALIGN()]] spin_lock(&vmap_area_lock); - --[[linux-2.6.33/spin_lock()]] - --[[linux-2.6.33/vmap_area_lock(global)]] if (addr + size - 1 < addr) goto overflow; /* XXX: could have a last_hole cache */ n = vmap_area_root.rb_node; - --[[linux-2.6.33/vmap_area_root(global)]] if (n) { struct vmap_area *first = NULL; do { struct vmap_area *tmp; tmp = rb_entry(n, struct vmap_area, rb_node); - --[[linux-2.6.33/rb_entry()]] if (tmp->va_end >= addr) { if (!first && tmp->va_start < addr + size) first = tmp; n = n->rb_left; } else { first = tmp; n = n->rb_right; } } while (n); if (!first) goto found; if (first->va_end < addr) { n = rb_next(&first->rb_node); if (n) first = rb_entry(n, struct vmap_area, rb_node); else goto found; - --[[linux-2.6.33/rb_next()]] } while (addr + size > first->va_start && addr + size <= vend) { addr = ALIGN(first->va_end + PAGE_SIZE, align); if (addr + size - 1 < addr) goto overflow; n = rb_next(&first->rb_node); if (n) first = rb_entry(n, struct vmap_area, rb_node); else goto found; } } found: if (addr + size > vend) { overflow: spin_unlock(&vmap_area_lock); - --[[linux-2.6.33/spin_unlock()]] if (!purged) { purge_vmap_area_lazy(); purged = 1; goto retry; - --[[linux-2.6.33/purge_vmap_area_lazy()]] } if (printk_ratelimit()) printk(KERN_WARNING "vmap allocation for size %lu failed: " "use vmalloc=<size> to increase size.\n", size); - --[[linux-2.6.33/printk_ratelimit()]] - --[[linux-2.6.33/printk()]] - --[[linux-2.6.33/KERN_WARNING]] kfree(va); return ERR_PTR(-EBUSY); - --[[linux-2.6.33/kfree()]] } BUG_ON(addr & (align-1)); va->va_start = addr; va->va_end = addr + size; va->flags = 0; __insert_vmap_area(va); spin_unlock(&vmap_area_lock); - --[[linux-2.6.33/__insert_vmap_area()]] return va; } *コメント [#se35ce5f]