当前位置: 首页 > 工具软件 > mempool > 使用案例 >

内存管理API之mempool_alloc

甄阳朔
2023-12-01
void *mempool_alloc(mempool_t *pool, gfp_t gfp_mask)从形参pool中申请内存
其源码分析如下:
void *mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
{
	void *element;
	unsigned long flags;
	wait_queue_entry_t wait;
	gfp_t gfp_temp;

	#形参gfp_mast 中不能包含__GFP_ZERO 标志
	VM_WARN_ON_ONCE(gfp_mask & __GFP_ZERO);
	#如果包含__GFP_DIRECT_RECLAIM 的话,可能会导致sleep,这些就会打印callstack
	might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM);
	#添加上这三个flag
	gfp_mask |= __GFP_NOMEMALLOC;	/* don't allocate emergency reserves */
	gfp_mask |= __GFP_NORETRY;	/* don't loop in __alloc_pages */
	gfp_mask |= __GFP_NOWARN;	/* failures are OK */

	gfp_temp = gfp_mask & ~(__GFP_DIRECT_RECLAIM|__GFP_IO);

repeat_alloc:
	#通过形参pool 来申请memory,正常情况下不会返归NULL
	element = pool->alloc(gfp_temp, pool->pool_data);
	if (likely(element != NULL))
		return element;

	spin_lock_irqsave(&pool->lock, flags);
	if (likely(pool->curr_nr)) {
		#如果pool->curr_nr 不为null的话,则肯定可以从pool中申请到memory。
		element = remove_element(pool, gfp_temp);
		spin_unlock_irqrestore(&pool->lock, flags);
		/* paired with rmb in mempool_free(), read comment there */
		smp_wmb();
		/*
		 * Update the allocation stack trace as this is more useful
		 * for debugging.
		 */
		 #由于这里肯定可以申请到内存,所以这里不检查element 是否为null,所以这里直接返回
		kmemleak_update_trace(element);
		return element;
	}

	/*
	 * We use gfp mask w/o direct reclaim or IO for the first round.  If
	 * alloc failed with that and @pool was empty, retry immediately.
	 */
	 #如果修改后的gfp_temp不等于形参gfp_mask,则用形参gfp_mask 赋值
	if (gfp_temp != gfp_mask) {
		spin_unlock_irqrestore(&pool->lock, flags);
		gfp_temp = gfp_mask;
		goto repeat_alloc;
	}

	/* We must not sleep if !__GFP_DIRECT_RECLAIM */
	if (!(gfp_mask & __GFP_DIRECT_RECLAIM)) {
		spin_unlock_irqrestore(&pool->lock, flags);
		return NULL;
	}
	#如果跑到这里的话,确实是没有内存申请,这里先sleep 5s后再继续尝试
	/* Let's wait for someone else to return an element to @pool */
	#初始化等待队列
	init_wait(&wait);
	#准备开始等待
	prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);

	spin_unlock_irqrestore(&pool->lock, flags);

	/*
	 * FIXME: this should be io_schedule().  The timeout is there as a
	 * workaround for some DM problems in 2.6.18.
	 */
	#睡眠5s
	io_schedule_timeout(5*HZ);
	#完成等待
	finish_wait(&pool->wait, &wait);
	goto repeat_alloc;
}

 类似资料: