プログラミングインタフェース

API の使用例

この節では、この章で説明した API を使ったタスクを実行するコーディング例を示します。


例 4–7 スレッドへのメモリーの移動

次のコーディング例では、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");
}


例 4–8 メモリーへのスレッドの移動

このコーディング例では、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);
}


例 4–9 lgroup 階層の巡回

次のコーディング例では、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);
}


例 4–10 指定された 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 を検索 (最も低い応答時間を持つ親 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));
}


例 4–11 空きメモリー領域を持つ最も近い lgroup の検索

このコーディング例では、指定されたスレッドのホーム 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));
}