- 论坛徽章:
- 0
|
本帖最后由 hshopeful 于 2012-09-04 10:13 编辑
- static struct page *
- get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
- struct zonelist *zonelist, int alloc_flags)
- {
- struct zone **z;//管理区结构体
- struct page *page = NULL;
- int classzone_idx = zone_idx(zonelist->zones[0]);//#define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones) 获取管理区的编号
- struct zone *zone;
- nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */
- int zlc_active = 0; /* set if using zonelist_cache */
- int did_zlc_setup = 0; /* just call zlc_setup() one time */
- enum zone_type highest_zoneidx = -1; /* Gets set for policy zonelists */
- zonelist_scan:
- /*
- * Scan zonelist, looking for a zone with enough free.
- * See also cpuset_zone_allowed() comment in kernel/cpuset.c.
- */
- z = zonelist->zones;//让z指向第一个管理区
- // 在允许的节点中,遍历满足要求的管理区
- do {
- /*
- * In NUMA, this could be a policy zonelist which contains
- * zones that may not be allowed by the current gfp_mask.
- * Check the zone is allowed by the current flags
- */
- if (unlikely(alloc_should_filter_zonelist(zonelist))) {//根据zonelist->zlcache_ptr来确定是否需要过滤掉此内存区链表,关于过滤的条件还不是很清楚,请指教
- if (highest_zoneidx == -1)
- highest_zoneidx = gfp_zone(gfp_mask);//gfp_zone用于指定分配内存的内存域
- if (zone_idx(*z) > highest_zoneidx)//首先考虑利用上面指定的内存域,对于一些分配代价高于指定内存域的内存域先不考虑
- continue;
- }
- if (NUMA_BUILD && zlc_active &&//是第一遍分配,在其他管理区中分配页面时需要考虑其页面是否充足
- !zlc_zone_worth_trying(zonelist, z, allowednodes))//该管理区页面不是很充足,考虑下一个管理区
- continue;
- zone = *z;
- if ((alloc_flags & ALLOC_CPUSET) &&
- !cpuset_zone_allowed_softwall(zone, gfp_mask))//当前分配标志不允许在该管理区中分配页面
- goto try_next_zone;
- if (!(alloc_flags & ALLOC_NO_WATERMARKS)) {//分配时需要考虑watermark
- unsigned long mark;//根据分配标志,确定使用哪一个watermark
- if (alloc_flags & ALLOC_WMARK_MIN)
- mark = zone->pages_min;
- else if (alloc_flags & ALLOC_WMARK_LOW)
- mark = zone->pages_low;
- else
- mark = zone->pages_high;
- if (!zone_watermark_ok(zone, order, mark,
- classzone_idx, alloc_flags)) {//该管理区的可用内存不可以满足本次分配的要求
- if (!zone_reclaim_mode ||//但不满足分配要求时,如果此内存域不能回收内存或者是回收不到可用内存时,就会跳转到this_zone_full
- !zone_reclaim(zone, gfp_mask, order))
- goto this_zone_full;
- }
- }
- page = buffered_rmqueue(zonelist, zone, order, gfp_mask);//调用伙伴系统的分配函数
- if (page)// 从伙伴系统分配成功,退出
- break;
- this_zone_full:
- if (NUMA_BUILD)
- zlc_mark_zone_full(zonelist, z);//标记该管理区空间不足,下次分配时将略过本管理区,避免浪费太多时间
- try_next_zone:
- if (NUMA_BUILD && !did_zlc_setup) {//当前管理区内存不足,需要加大在其他区中的分配力度
- /* we do zlc_setup after the first zone is tried */
- allowednodes = zlc_setup(zonelist, alloc_flags);
- zlc_active = 1;
- did_zlc_setup = 1;
- }
- } while (*(++z) != NULL);
- if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) {// 第一遍分配不成功,则取消zlc_active,这样会尽量从其他节点中分配内存
- /* Disable zlc cache for second zonelist scan */
- zlc_active = 0;
- goto zonelist_scan;
- }
- return page;
- }
复制代码 关于上面一段代码中zlc_active的作用不明白,还望理解的人指点一下。不甚感激!- struct zonelist {
- struct zonelist_cache *zlcache_ptr; // NULL or &zlcache
- struct zone *zones[MAX_ZONES_PER_ZONELIST + 1]; // NULL delimited
- #ifdef CONFIG_NUMA
- struct zonelist_cache zlcache; // optional ...
- #endif
- };
复制代码- struct zonelist_cache {
- unsigned short z_to_n[MAX_ZONES_PER_ZONELIST]; /* zone->nid */
- DECLARE_BITMAP(fullzones, MAX_ZONES_PER_ZONELIST); /* zone full? */
- unsigned long last_full_zap; /* when last zap'd (jiffies) */
- };
复制代码 |
|