この節では、この章で説明した API を使ったタスクを実行するコーディング例を示します。
次のコーディング例では、addr で指定されたアドレスから addr+len で指定されるアドレスまでの範囲のメモリーを、 MADV_ACCESS_LWP で指定されるスレッドに移動します。
#include <sys/mman.h>
#include <sys/types.h>
/*
* スレッドへのメモリーの移動
*/
mem_to_thread(caddr_t addr, size_t len)
{
if (madvise(addr, len, MADV_ACCESS_LWP) < 0)
perror("madvise");
}
このコーディング例では、meminfo() 関数を使用して指定されたメモリーページの lgroup を取得し、lgrp_affinity_set function() 関数によって、該当する lgroup への指定されたスレッドのアフィニティーを上げます。
#include <sys/lgrp_user.h>
#include <sys/mman.h>
#include <sys/types.h>
/*
* メモリーへのスレッドの移動
*/
int
thread_to_memory(caddr_t va)
{
uint64_t addr;
ulong_t count;
lgrp_id_t home;
uint64_t lgrp;
uint_t request;
uint_t valid;
addr = (uint64_t)va;
count = 1;
request = MEMINFO_VLGRP;
if (meminfo(&addr, 1, &request, 1, &lgrp, &valid) != 0) {
perror("meminfo");
return (1);
}
if (lgrp_affinity_set(P_LWPID, P_MYID, lgrp, LGRP_AFF_STRONG) != 0) {
perror("lgrp_affinity_set");
return (2);
}
home = lgrp_home(P_LWPID, P_MYID);
if (home == -1) {
perror ("lgrp_home");
return (3);
}
if (home != lgrp)
return (-1);
return (0);
}
次のコーディング例では、lgroup 階層を巡回し、出力します。
#include <stdlib.h>
#include <sys/lgrp_user.h>
#include <sys/types.h>
/*
* 指定された lgroup からそのすべての下位ノードを巡回し、
* lgroup 階層を出力
*/
int
lgrp_walk(lgrp_cookie_t cookie, lgrp_id_t lgrp, lgrp_content_t content)
{
lgrp_affinity_t aff;
lgrp_id_t *children;
processorid_t *cpuids;
int i;
int ncpus;
int nchildren;
int nparents;
lgrp_id_t *parents;
lgrp_mem_size_t size;
/*
* 指定された lgroup、呼び出しプロセスの lgroup へのアフィニティー、
* および目的とする内容情報の出力
*/
printf("LGROUP #%d:\n", lgrp);
aff = lgrp_affinity_get(P_MYID, P_MYID, lgrp);
if (aff == -1)
perror ("lgrp_affinity_get");
printf("\tAFFINITY: %d\n", aff);
printf("CONTENT %d:\n", content);
/*
* CPU 情報を取得する
*/
ncpus = lgrp_cpus(cookie, lgrp, NULL, 0, content);
printf("\t%d CPUS: ", ncpus);
if (ncpus == -1) {
perror("lgrp_cpus");
return (-1);
} else if (ncpus> 0) {
cpuids = malloc(ncpus * sizeof (processorid_t));
ncpus = lgrp_cpus(cookie, lgrp, cpuids, ncpus, content);
if (ncpus == -1) {
free(cpuids);
perror("lgrp_cpus");
return (-1);
}
for (i = 0; i < ncpus; i++)
printf("%d ", cpuids[i]);
free(cpuids);
}
printf("\n");
/*
* メモリーサイズを取得する
*/
printf("\tMEMORY: ");
size = lgrp_mem_size(cookie, lgrp, LGRP_MEM_SZ_INSTALLED, content);
if (size == -1) {
perror("lgrp_mem_size");
return (-1);
}
printf("installed bytes 0x%llx, ", size);
size = lgrp_mem_size(cookie, lgrp, LGRP_MEM_SZ_FREE, content);
if (size == -1) {
perror("lgrp_mem_size");
return (-1);
}
printf("free bytes 0x%llx\n", size);
/*
* 親 lgroup を取得する
*/
nparents = lgrp_parents(cookie, lgrp, NULL, 0);
printf("\t%d PARENTS: ", nparents);
if (nparents == -1) {
perror("lgrp_parents");
return (-1);
} else if (nparents> 0) {
parents = malloc(nparents * sizeof (lgrp_id_t));
nparents = lgrp_parents(cookie, lgrp, parents, nparents);
if (nparents == -1) {
free(parents);
perror("lgrp_parents");
return (-1);
}
for (i = 0; i < nparents; i++)
printf("%d ", parents[i]);
free(parents);
}
printf("\n");
/*
* 子 lgroup を取得する
*/
nchildren = lgrp_children(cookie, lgrp, NULL, 0);
printf("\t%d CHILDREN: ", nchildren);
if (nchildren == -1) {
perror("lgrp_children");
return (-1);
} else if (nchildren> 0) {
children = malloc(nchildren * sizeof (lgrp_id_t));
nchildren = lgrp_children(cookie, lgrp, children, nchildren);
if (nchildren == -1) {
free(children);
perror("lgrp_children");
return (-1);
}
printf("Children: ");
for (i = 0; i < nchildren; i++)
printf("%d ", children[i]);
printf("\n");
for (i = 0; i < nchildren; i++)
lgrp_walk(cookie, children[i], content);
free(children);
}
printf("\n");
return (0);
}
#include <stdlib.h>
#include <sys/lgrp_user.h>
#include <sys/types.h>
#define INT_MAX 2147483647
/*
* 指定された lgroup 以外で利用可能なメモリーを持つ、次に最も近い lgroup の検索
*/
lgrp_id_t
lgrp_next_nearest(lgrp_cookie_t cookie, lgrp_id_t from)
{
lgrp_id_t closest;
int i;
int latency;
int lowest;
int nparents;
lgrp_id_t *parents;
lgrp_mem_size_t size;
/*
* 親 lgroup の数を取得する
*/
nparents = lgrp_parents(cookie, from, NULL, 0);
if (nparents == -1) {
perror("lgrp_parents");
return (LGRP_NONE);
}
/*
* 親 lgroup がない場合は現在の lgroup が最も近い
*/
if (nparents == 0) {
return (from);
}
/*
* 親 lgroup を取得する
*/
parents = malloc(nparents * sizeof (lgrp_id_t));
nparents = lgrp_parents(cookie, from, parents, nparents);
if (nparents == -1) {
perror("lgrp_parents");
free(parents);
return (LGRP_NONE);
}
/*
* 最も近い位置の親 lgroup を検索 (最も低い応答時間を持つ親 lgroup など)
*/
closest = LGRP_NONE;
lowest = INT_MAX;
for (i = 0; i < nparents; i++) {
lgrp_id_t lgrp;
/*
* 空きメモリー領域を持つ親 lgroup を調べる
*/
size = lgrp_mem_size(cookie, parents[i], LGRP_MEM_SZ_FREE,
LGRP_CONTENT_HIERARCHY);
if (size> 0)
lgrp = parents[i];
else {
if (size == -1)
perror("lgrp_mem_size");
/*
* 親 lgroup にメモリーがないときは、
* 最も近い上位ノードを検索する
*/
lgrp = lgrp_next_nearest(cookie, parents[i]);
if (lgrp == LGRP_NONE)
continue;
}
/*
* 親 lgroup の応答時間を取得する
*/
latency = lgrp_latency(lgrp, lgrp);
if (latency == -1) {
perror("lgrp_latency");
continue;
}
/*
* 最も低い応答時間の lgroup を記憶する
*/
if (latency < lowest) {
closest = lgrp;
lowest = latency;
}
}
free(parents);
return (closest);
}
/*
* 現在のスレッドのホーム lgroup に最も近い、メモリーのある lgroup を検索する
*/
lgrp_id_t
lgrp_nearest(lgrp_cookie_t cookie)
{
lgrp_id_t home;
longlong_t size;
/*
* ホーム lgroup を取得する
*/
home = lgrp_home(P_LWPID, P_MYID);
/*
* ホーム lgroup が自分の階層に利用可能なメモリーを持っているかどうかを調べる
*/
size = lgrp_mem_size(cookie, home, LGRP_MEM_SZ_FREE,
LGRP_CONTENT_HIERARCHY);
if (size == -1)
perror("lgrp_mem_size");
/*
* ホーム lgroup が利用可能なメモリーを持っていればこのホーム lgroup を返す
*/
if (size> 0)
return (home);
/*
* そうでなければ次に近いホーム lgroup 以外の lgroup を検索する
*/
return (lgrp_next_nearest(cookie, home));
}
このコーディング例では、指定されたスレッドのホーム lgroup に最も近い、空きメモリー領域を持つ lgroup を検索します。
#include <stdlib.h>
#include <sys/lgrp_user.h>
#include <sys/types.h>
#define INT_MAX 2147483647
/*
* 指定された lgroup 以外で、利用可能なメモリーを持つ次に最も近い lgroup の検索
*/
lgrp_id_t
lgrp_next_nearest(lgrp_cookie_t cookie, lgrp_id_t from)
{
lgrp_id_t closest;
int i;
int latency;
int lowest;
int nparents;
lgrp_id_t *parents;
lgrp_mem_size_t size;
/*
* 親 lgroup の数を取得する
*/
nparents = lgrp_parents(cookie, from, NULL, 0);
if (nparents == -1) {
perror("lgrp_parents");
return (LGRP_NONE);
}
/*
* 親 lgroup がない場合は、現在の lgroup が最も近い
*/
if (nparents == 0) {
return (from);
}
/*
* 親 lgroup を取得する
*/
parents = malloc(nparents * sizeof (lgrp_id_t));
nparents = lgrp_parents(cookie, from, parents, nparents);
if (nparents == -1) {
perror("lgrp_parents");
free(parents);
return (LGRP_NONE);
}
/*
* 最も近い親 lgroup を検索する (最も低い応答時間を持つ)
*/
closest = LGRP_NONE;
lowest = INT_MAX;
for (i = 0; i < nparents; i++) {
lgrp_id_t lgrp;
/*
* 親 lgroup が空きメモリーを持っているかどうか調べる
*/
size = lgrp_mem_size(cookie, parents[i], LGRP_MEM_SZ_FREE,
LGRP_CONTENT_HIERARCHY);
if (size> 0)
lgrp = parents[i];
else {
if (size == -1)
perror("lgrp_mem_size");
/*
* 親 lgroup がメモリーを持たない場合は、
* 最も近い上位ノードを検索する
*/
lgrp = lgrp_next_nearest(cookie, parents[i]);
if (lgrp == LGRP_NONE)
continue;
}
/*
* 親 lgroup の応答時間を取得する
*/
latency = lgrp_latency(lgrp, lgrp);
if (latency == -1) {
perror("lgrp_latency");
continue;
}
/*
* 最も低い応答時間を持つ lgroup を記憶する
*/
if (latency < lowest) {
closest = lgrp;
lowest = latency;
}
}
free(parents);
return (closest);
}
/*
* 現在のスレッドのホーム lgroup に最も近い、メモリーを持つ lgroup を検索する
*/
lgrp_id_t
lgrp_nearest(lgrp_cookie_t cookie)
{
lgrp_id_t home;
longlong_t size;
/*
* ホーム lgroup を取得する
*/
home = lgrp_home(P_LWPID, P_MYID);
/*
* ホーム lgroup が自分の階層に利用可能なメモリーを持っているかどうかを調べる
*/
size = lgrp_mem_size(cookie, home, LGRP_MEM_SZ_FREE,
LGRP_CONTENT_HIERARCHY);
if (size == -1)
perror("lgrp_mem_size");
/*
* ホーム lgroup が利用可能なメモリーを持っていればこのホーム lgroup を返す
*/
if (size> 0)
return (home);
/*
* そうでなければ次に近いホーム lgroup 以外の lgroup を調べる
*/
return (lgrp_next_nearest(cookie, home));
}