この節では、この章で説明した API を使用するタスクのコーディング例を示します。
次のコーディング例では、addr と addr+len のアドレス範囲にあるメモリーを、その範囲に次回アクセスするスレッド付近に移動します。
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
/*
* Move memory to thread
*/
void
mem_to_thread(caddr_t addr, size_t len)
{
if (madvise(addr, len, MADV_ACCESS_LWP) < 0)
perror("madvise");
}
このコーディング例では、meminfo() 関数を使用して、指定されたアドレスで仮想ページにバックアップする物理メモリーの lgroup を判定します。次にこの例では、現在のスレッドをそのメモリー付近に移動するために、その lgroup に強いアフィニティーを設定します。
#include <stdio.h>
#include <sys/lgrp_user.h>
#include <sys/mman.h>
#include <sys/types.h>
/*
* Move a thread to memory
*/
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 <stdio.h>
#include <stdlib.h>
#include <sys/lgrp_user.h>
#include <sys/types.h>
/*
* Walk and print lgroup hierarchy from given lgroup
* through all its descendants
*/
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;
/*
* Print given lgroup, caller's affinity for lgroup,
* and desired content specified
*/
printf("LGROUP #%d:\n", lgrp);
aff = lgrp_affinity_get(P_LWPID, P_MYID, lgrp);
if (aff == -1)
perror ("lgrp_affinity_get");
printf("\tAFFINITY: %d\n", aff);
printf("CONTENT %d:\n", content);
/*
* Get CPUs
*/
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");
/*
* Get memory size
*/
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);
/*
* Get parents
*/
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");
/*
* Get children
*/
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 <stdio.h>
#include <stdlib.h>
#include <sys/lgrp_user.h>
#include <sys/types.h>
#define INT_MAX 2147483647
/*
* Find next closest lgroup outside given one with available memory
*/
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;
/*
* Get number of parents
*/
nparents = lgrp_parents(cookie, from, NULL, 0);
if (nparents == -1) {
perror("lgrp_parents");
return (LGRP_NONE);
}
/*
* No parents, so current lgroup is next nearest
*/
if (nparents == 0) {
return (from);
}
/*
* Get parents
*/
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);
}
/*
* Find closest parent (ie. the one with lowest latency)
*/
closest = LGRP_NONE;
lowest = INT_MAX;
for (i = 0; i < nparents; i++) {
lgrp_id_t lgrp;
/*
* See whether parent has any free memory
*/
size = lgrp_mem_size(cookie, parents[i], LGRP_MEM_SZ_FREE,
LGRP_CONTENT_ALL);
if (size > 0)
lgrp = parents[i];
else {
if (size == -1)
perror("lgrp_mem_size");
/*
* Find nearest ancestor if parent doesn't
* have any memory
*/
lgrp = lgrp_next_nearest(cookie, parents[i]);
if (lgrp == LGRP_NONE)
continue;
}
/*
* Get latency within parent lgroup
*/
latency = lgrp_latency_cookie(lgrp, lgrp);
if (latency == -1) {
perror("lgrp_latency_cookie");
continue;
}
/*
* Remember lgroup with lowest latency
*/
if (latency < lowest) {
closest = lgrp;
lowest = latency;
}
}
free(parents);
return (closest);
}
/*
* Find lgroup with memory nearest home lgroup of current thread
*/
lgrp_id_t
lgrp_nearest(lgrp_cookie_t cookie)
{
lgrp_id_t home;
longlong_t size;
/*
* Get home lgroup
*/
home = lgrp_home(P_LWPID, P_MYID);
/*
* See whether home lgroup has any memory available in its hierarchy
*/
size = lgrp_mem_size(cookie, home, LGRP_MEM_SZ_FREE,
LGRP_CONTENT_ALL);
if (size == -1)
perror("lgrp_mem_size");
/*
* It does, so return the home lgroup.
*/
if (size > 0)
return (home);
/*
* Otherwise, find next nearest lgroup outside of the home.
*/
return (lgrp_next_nearest(cookie, home));
}
このコーディング例では、指定されたスレッドのホーム lgroup にもっとも近い、空きメモリー領域を持つ lgroup を検索します。
lgrp_id_t
lgrp_nearest(lgrp_cookie_t cookie)
{
lgrp_id_t home;
longlong_t size;
/*
* Get home lgroup
*/
home = lgrp_home();
/*
* See whether home lgroup has any memory available in its hierarchy
*/
if (lgrp_mem_size(cookie, lgrp, LGRP_MEM_SZ_FREE,
LGRP_CONTENT_ALL, &size) == -1)
perror("lgrp_mem_size");
/*
* It does, so return the home lgroup.
*/
if (size > 0)
return (home);
/*
* Otherwise, find next nearest lgroup outside of the home.
*/
return (lgrp_next_nearest(cookie, home));
}