*参照元 [#f00eb941] #backlinks *説明 [#o9ec7af5] -パス: [[linux-2.6.33/mm/slob.c]] -FIXME: これは何? --説明 **引数 [#o80c21e2] -size_t size -- -gfp_t gfp -- --[[linux-2.6.33/gfp_t]] -int align -- -int node -- **返り値 [#d2fc2bb6] -void * -- **参考 [#l8ac7820] *実装 [#k224e9fe] /* * slob_alloc: entry point into the slob allocator. */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { struct slob_page *sp; struct list_head *prev; struct list_head *slob_list; slob_t *b = NULL; unsigned long flags; - --[[linux-2.6.33/slob_page]] - --[[linux-2.6.33/list_head]] - --[[linux-2.6.33/slob_t]] if (size < SLOB_BREAK1) slob_list = &free_slob_small; else if (size < SLOB_BREAK2) slob_list = &free_slob_medium; else slob_list = &free_slob_large; -256バイト、1024バイトを境界として、 使用する SLOB のリストを選択する size < 256 : small リスト 256 <= size < 1024 : medium リスト 1024 <= size : large リスト --[[linux-2.6.33/SLOB_BREAK1]] --[[linux-2.6.33/SLOB_BREAK2]] --[[linux-2.6.33/free_slob_small(global)]] --[[linux-2.6.33/free_slob_medium(global)]] --[[linux-2.6.33/free_slob_large(global)]] spin_lock_irqsave(&slob_lock, flags); -SLOB のロックを取得する。 --[[linux-2.6.33/spin_lock_irqsave()]] --[[linux-2.6.33/slob_lock(global)]] /* Iterate through each partially free page, try to find room */ list_for_each_entry(sp, slob_list, list) { - --[[linux-2.6.33/list_for_each_entry()]] #ifdef CONFIG_NUMA - --[[linux-2.6.33/CONFIG_NUMA]] /* * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ if (node != -1 && page_to_nid(&sp->page) != node) continue; - --[[linux-2.6.33/page_to_nid()]] #endif /* Enough room on this page? */ if (sp->units < SLOB_UNITS(size)) continue; - --[[linux-2.6.33/SLOB_UNITS()]] /* Attempt to alloc */ prev = sp->list.prev; b = slob_page_alloc(sp, size, align); if (!b) continue; - --[[linux-2.6.33/slob_page_alloc()]] /* Improve fragment distribution and reduce our average * search time by starting our next search here. (see * Knuth vol 1, sec 2.5, pg 449) */ if (prev != slob_list->prev && slob_list->next != prev->next) list_move_tail(slob_list, prev->next); - --[[linux-2.6.33/list_move_tail()]] break; } spin_unlock_irqrestore(&slob_lock, flags); -SLOB のロックを解放する。 --[[linux-2.6.33/spin_unlock_irqrestore()]] /* Not enough space: must allocate a new page */ if (!b) { b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; - --[[linux-2.6.33/slob_new_pages()]] - --[[linux-2.6.33/__GFP_ZERO]] sp = slob_page(b); set_slob_page(sp); - --[[linux-2.6.33/slob_page()]] - --[[linux-2.6.33/set_slob_page()]] spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); sp->free = b; INIT_LIST_HEAD(&sp->list); - --[[linux-2.6.33/INIT_LIST_HEAD()]] set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); b = slob_page_alloc(sp, size, align); BUG_ON(!b); - --[[linux-2.6.33/set_slob()]] - --[[linux-2.6.33/set_slob_page_free()]] - --[[linux-2.6.33/slob_page_alloc()]] spin_unlock_irqrestore(&slob_lock, flags); } if (unlikely((gfp & __GFP_ZERO) && b)) memset(b, 0, size); - --[[linux-2.6.33/unlikely()]] - --[[linux-2.6.33/memset()]] return b; } *コメント [#tfdc8ad7]