2009年10月9日金曜日

find_next_best_node

前回見ていた「build_zonelists」の中から今回は「find_next_best_node」を見てみます。
ゾーンリストに追加するノードを検索する関数で実体は「mm/page_alloc.c」にあります。

==========
static int find_next_best_node(int node, nodemask_t *used_node_mask)
{
int n, val;
int min_val = INT_MAX;
int best_node = -1;
node_to_cpumask_ptr(tmp, 0);

/* nodeが未使用状態であるならnodeをそのまま返す */
if (!node_isset(node, *used_node_mask)) {
/* nodeが使用中であるというbitをused_node_maskに立ててやる */
node_set(node, *used_node_mask);
return node;
}

/* nodeの数だけ繰り返す */
for_each_node_state(n, N_HIGH_MEMORY) {

/* 既にチェック済みのノードは飛ばす */
if (node_isset(n, *used_node_mask))
continue;

/* nodeとnが同じかどうか */
val = node_distance(node, n);

/* nodeより小さいノードへペナルティをかけてやる */
val += (n < node);

/* 先頭ではなくて未使用のノードを優先する */
node_to_cpumask_ptr_next(tmp, n);
/* CPUを持っているノードにはペナルティ */
if (!cpus_empty(*tmp))
val += PENALTY_FOR_NODE_WITH_CPUS;

/* Slight preference for less loaded node */
val *= (MAX_NODE_LOAD*MAX_NUMNODES);
val += node_load[n];

/* valがこれまでの最小値より小さければ最適ノードを入れ替え *//*
if (val < min_val) {
min_val = val;
best_node = n;
}
}

/* 次の検索にひっかからないようにビットを立ててやる */
if (best_node >= 0)
node_set(best_node, *used_node_mask);

return best_node;
}

==========

ゾーンリストに追加したくない条件についてはペナルティをかけてやって、そのノードが選ばれないようにしています。後半に出てくる「node_load」というのは、前回見たuild_zonelistsで値をセットしていて新たに選ばれたノードが格納されています。
既に選ばれたノードについてはfind_next_best_nodeの「val += node_load[n]」という部分でペナルティがかかるため、ページの割り当てが局所化しないようになっているのです。

0 件のコメント:

コメントを投稿