この節では、この章で説明した 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)); }