上文分析了普通对象的申请过程,kmalloc。现在看一下针对专用对象的申请kmem_cache_alloc函数。
-
/**
-
* kmem_cache_alloc - Allocate an object
-
* @cachep: The cache to allocate from.
-
* @flags: See kmalloc().
-
*
-
* Allocate an object from this cache. The flags are only relevant
-
* if the cache has no available objects.
-
*/
-
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
-
{
/* __builtin_return_address是GCC内置函数,用于获取当前函数的返回地址 */
-
void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0));
-
-
trace_kmem_cache_alloc(_RET_IP_, ret,
-
obj_size(cachep), cachep->buffer_size, flags);
-
-
return ret;
-
}
-
__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller)
-
{
-
unsigned long save_flags;
-
void *objp;
-
-
flags &= gfp_allowed_mask;
-
-
lockdep_trace_alloc(flags);
-
-
if (slab_should_failslab(cachep, flags))
-
return NULL;
-
-
cache_alloc_debugcheck_before(cachep, flags);
-
local_irq_save(save_flags);
-
/* 在关硬中断的前提下,调用下面函数,完成实际的分配过程 */
-
objp = __do_cache_alloc(cachep, flags);
-
local_irq_restore(save_flags);
-
objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
-
kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags,
-
flags);
-
prefetchw(objp);
-
-
if (likely(objp))
-
kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep));
-
-
if (unlikely((flags & __GFP_ZERO) && objp))
-
memset(objp, 0, obj_size(cachep));
-
-
return objp;
-
}
__do_cache_alloc在开启NUMA和不开启NUMA时定义不同,简单起见,假设为UMA
-
static __always_inline void *
-
__do_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
-
{
-
return ____cache_alloc(cachep, flags);
-
}
-
static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
-
{
-
void *objp;
-
struct array_cache *ac;
-
-
check_irq_off();
-
/* 获取local cache, array_cache数组 */
-
ac = cpu_cache_get(cachep);
-
/* 有空闲对象 */
-
if (likely(ac->avail)) {
-
STATS_INC_ALLOCHIT(cachep);
-
/* 标示最近被访问 */
-
ac->touched = 1;
-
/* 分配一个对象,avail指向可用的空闲节点 */
-
objp = ac->entry[--ac->avail];
-
} else {
-
STATS_INC_ALLOCMISS(cachep);
-
/* local cache中无空闲对象,填充 */
-
objp = cache_alloc_refill(cachep, flags);
-
}
-
/*
-
* To avoid a false negative, if an object that is in one of the
-
* per-CPU caches is leaked, we need to make sure kmemleak doesn't
-
* treat the array pointers as a reference to the object.
-
*/
-
kmemleak_erase(&ac->entry[ac->avail]);
-
return objp;
-
}
以上整个过程与kmalloc实际上是相同的,只是对外提供了两种不同的API,cache_calloc_refill前面已经分析了,不再赘述。
阅读(4051) | 评论(0) | 转发(2) |