CPU_SET, CPU_CLR, CPU_ISSET, CPU_ZERO, CPU_COUNT, CPU_AND, CPU_OR, CPU_XOR,
CPU_EQUAL, CPU_ALLOC, CPU_ALLOC_SIZE, CPU_FREE, CPU_SET_S, CPU_CLR_S,
CPU_ISSET_S, CPU_ZERO_S, CPU_COUNT_S, CPU_AND_S, CPU_OR_S, CPU_XOR_S,
CPU_EQUAL_S - CPU
集合を操作するためのマクロ
#define _GNU_SOURCE /* feature_test_macros(7) 参照 */
#include <sched.h>
void CPU_ZERO(cpu_set_t *set);
void CPU_SET(int cpu, cpu_set_t *set);
void CPU_CLR(int cpu, cpu_set_t *set);
int CPU_ISSET(int cpu, cpu_set_t *set);
int CPU_COUNT(cpu_set_t *set);
void CPU_AND(cpu_set_t *destset,
cpu_set_t *srcset1, cpu_set_t *srcset2);
void CPU_OR(cpu_set_t *destset,
cpu_set_t *srcset1, cpu_set_t *srcset2);
void CPU_XOR(cpu_set_t *destset,
cpu_set_t *srcset1, cpu_set_t *srcset2);
int CPU_EQUAL(cpu_set_t *set1, cpu_set_t *set2);
cpu_set_t *CPU_ALLOC(int num_cpus);
void CPU_FREE(cpu_set_t *set);
size_t CPU_ALLOC_SIZE(int num_cpus);
void CPU_ZERO_S(size_t setsize, cpu_set_t *set);
void CPU_SET_S(int cpu, size_t setsize, cpu_set_t *set);
void CPU_CLR_S(int cpu, size_t setsize, cpu_set_t *set);
int CPU_ISSET_S(int cpu, size_t setsize, cpu_set_t *set);
int CPU_COUNT_S(size_t setsize, cpu_set_t *set);
void CPU_AND_S(size_t setsize, cpu_set_t *destset,
cpu_set_t *srcset1, cpu_set_t *srcset2);
void CPU_OR_S(size_t setsize, cpu_set_t *destset,
cpu_set_t *srcset1, cpu_set_t *srcset2);
void CPU_XOR_S(size_t setsize, cpu_set_t *destset,
cpu_set_t *srcset1, cpu_set_t *srcset2);
int CPU_EQUAL_S(size_t setsize, cpu_set_t *set1, cpu_set_t *set2);
cpu_set_t データ構造体は CPU
集合を表現している。
CPU 集合は
sched_setaffinity(2)
や同様のインタフェースで使用されている。
cpu_set_t
データ型はビット集合として実装されている。
しかし、
データ構造体はその実装を意識せずに扱うものとされており、
CPU
集合のすべての操作は、
このページで説明されているマクロを通して行うべきである。
以下のマクロが CPU 集合
set
を操作するために提供されている。
- CPU_ZERO()
- set をクリアする。
集合には何も CPU
が含まれない状態となる。
- CPU_SET()
- set に cpu
を追加する。
- CPU_CLR()
- set から cpu
を削除する。
- CPU_ISSET()
- CPU cpu が set
のメンバーであるかを検査する。
- CPU_COUNT()
- set に含まれる CPU
数を返す。
cpu
引き数が指定する場合、
その引き数は副作用を伴うべきではない。
上記のマクロは引き数を複数回評価する可能性があるからである。
そのシステムで利用可能な最初の
CPU が
cpu 値 0 に対応し、
次の CPU が
cpu 値 1
に対応し、
以降も同様である。
定数
CPU_SETSIZE
(現在のところ 1024) は
cpu_set_t
に格納できる最大 CPU
数よりも大きな値である。
以下のマクロは CPU
集合どうしの論理操作を行う。
- CPU_AND()
- 集合 srcset1 と srcset2
の積集合を destset
に格納する
(元の集合のいずれかが
destset
として使用される場合もある)。
- CPU_OR()
- 集合 srcset1 と srcset2
の和集合を destset
に格納する
(元の集合のいずれかが
destset
として使用される場合もある)。
- CPU_XOR()
- 集合 srcset1 と srcset2 の XOR
を destset に格納する
(元の集合のいずれかが
destset
として使用される場合もある)。
XOR とは、 srcset1 か srcset2
のいずれかに含まれるが、両方には含まれない集合のことである。
- CPU_EQUAL()
- 二つの CPU
集合が全く同じ CPU
を含んでいるかを検査する。
動的に大きさが決まる CPU 集合¶
いくつかのアプリケーションでは
CPU
集合の大きさを動的に決める能力
(例えば、 標準の
cpu_set_t
データ型で定義されたよりも大きい集合を割り当てるなど)
が必要となることがあるため、
現在 glibc
はこれに対応するためにいくつかのマクロを提供している。
以下のマクロを使うと
CPU
集合の割り当てと解放ができる。
- CPU_ALLOC()
- 0 から num_cpus-1
までの範囲の CPU
を保持するのに十分な大きさの
CPU
集合を割り当てる。
- CPU_ALLOC_SIZE()
- 0 から num_cpus-1
までの範囲の CPU
を保持するのに必要な
CPU
集合の大きさをバイト数で返す。
このマクロが返す値は、
後述の CPU_*_S() マクロの
setsize
引き数として使用できる。
- CPU_FREE()
- 以前に CPU_ALLOC()
で割り当てられた CPU
集合を解放する。
名前が "_S"
で終わるマクロは
"_S"
なしの同じ名前のマクロと同等である。
これらのマクロは
"_S"
なしのものと同じ動作をするが、
動的に割り当てられた、
大きさが
setsize
バイトの CPU
集合に対して操作を行う点が異なる。
返り値¶
CPU_ISSET() と
CPU_ISSET_S() は、
cpu
が
set
に含まれていれば 0
以外を返し、含まれない場合
0 を返す。
CPU_COUNT() と
CPU_COUNT_S() は
set
に含まれる CPU
数を返す。
CPU_EQUAL() と
CPU_EQUAL_S() は、
二つの CPU
集合が等しければ 0
以外を返し、
等しくない場合 0
を返す。
CPU_ALLOC()
は成功するとポインタを返し、
失敗すると NULL を返す
(エラーは
malloc(3)
と同じである)。
CPU_ALLOC_SIZE()
は指定された大きさの
CPU
集合を格納するのに必要なバイト数を返す。
他の関数は値を返さない。
バージョン¶
マクロ
CPU_ZERO(),
CPU_SET(),
CPU_CLR(),
CPU_ISSET() は glibc 2.3.3
で追加された。
CPU_COUNT() は glibc 2.6
で初めて登場した。
CPU_AND(),
CPU_OR(),
CPU_XOR(),
CPU_EQUAL(),
CPU_ALLOC(),
CPU_ALLOC_SIZE(),
CPU_FREE(),
CPU_ZERO_S(),
CPU_SET_S(),
CPU_CLR_S(),
CPU_ISSET_S(),
CPU_AND_S(),
CPU_OR_S(),
CPU_XOR_S(),
CPU_EQUAL_S() は glibc 2.7
で初めて登場した。
これらのインタフェースは
Linux 固有である。
CPU
集合を複製するには、
memcpy(3) を使用する。
CPU
集合はロングワード単位に割り当てられるビット集合なので、
動的に割り当てられた
CPU 集合の実際の CPU 数は
sizeof(unsigned long)
の次の倍数に切り上げられることになる。
アプリケーションは、
これらの余分なビットの内容は不定と考えるべきである。
名前は似ているが、
定数
CPU_SETSIZE は
cpu_set_t
データ型に含まれる CPU
数
(つまり、事実上ビット集合内のビットカウント)
を示すのに対して、
マクロ
CPU_*_S() の
setsize
引き数はバイト単位のサイズである点に注意すること。
「書式」に書かれている引き数と返り値のデータ型は、それぞれの場合でどんな型が期待されるかのヒントである。
しかしながら、
これらのインタフェースはマクロとして実装されているため、
このヒントを守らなかった場合に、
コンパイラが必ずしも全ての型エラーを捕捉できるとは限らない。
glibc 2.8 以前の 32
ビットプラットフォームでは、
CPU_ALLOC()
は必要な空間の割り当てを二度行い、
CPU_ALLOC_SIZE()
は本来あるべき値の二倍の値を返す。
このバグはプログラムの動作には影響を与えないはずだが、
無駄にメモリを消費し、
動的に割り当てられた
CPU
集合に対して操作を行うマクロの動作の効率が下がる結果となる。
これらのバグは glibc 2.9
で修正された。
以下のプログラムは、動的に割り当てた
CPU
集合に対していくつかのマクロを使用する例を示している。
#define _GNU_SOURCE
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
int
main(int argc, char *argv[])
{
cpu_set_t *cpusetp;
size_t size;
int num_cpus, cpu;
if (argc < 2) {
fprintf(stderr, "Usage: %s <num-cpus>\n", argv[0]);
exit(EXIT_FAILURE);
}
num_cpus = atoi(argv[1]);
cpusetp = CPU_ALLOC(num_cpus);
if (cpusetp == NULL) {
perror("CPU_ALLOC");
exit(EXIT_FAILURE);
}
size = CPU_ALLOC_SIZE(num_cpus);
CPU_ZERO_S(size, cpusetp);
for (cpu = 0; cpu < num_cpus; cpu += 2)
CPU_SET_S(cpu, size, cpusetp);
printf("CPU_COUNT() of set: %d\n", CPU_COUNT_S(size, cpusetp));
CPU_FREE(cpusetp);
exit(EXIT_SUCCESS);
}
関連項目¶
sched_setaffinity(2),
pthread_attr_setaffinity_np(3),
pthread_setaffinity_np(3),
cpuset(7)
この文書について¶
この man ページは Linux
man-pages
プロジェクトのリリース
3.65 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。