|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1.1.3 root 7: //
1.1 root 8: // pthread の OS ごとに違う部分を吸収する
1.1.1.3 root 9: //
1.1 root 10:
11: #include "mythread.h"
12: #include <pthread.h>
13: #if defined(HAVE_PTHREAD_NP_H)
14: #include <pthread_np.h>
15: #endif
16:
1.1.1.4 ! root 17: #if defined(HAVE_PTHREAD_SETAFFINITY_NP)
! 18: // pthread_setaffinity_np は今のところどの OS でもだいたい同じだが
! 19: // <pthread_np.h> が必要な関係でこっちに置いておく。
! 20: int
! 21: PTHREAD_SETAFFINITY(pthread_t thread, const MICPUSet& m)
! 22: {
! 23: return pthread_setaffinity_np(thread, m.Count(), m.Get());
! 24: }
! 25: #endif
! 26:
1.1 root 27: // pthread_set{,_}name_np() のプロトタイプは OS によってみんなフリーダムなので
28: // (というか _np は Non Portable か Non Posix のことらしい?)、
29: // ここで吸収する。
30: //
31: // MacOSX は void pthread_setname_np(name)
32: // Linux は int pthread_setname_np(threadID, name)
33: // NetBSD は int pthread_setname_np(threadID, name, arg)
34: // OpenBSD は void pthread_set_name_np(threadID, name)
35: // FreeBSD は void pthread_set_name_np(threadID, name)
36: // (2020/06 以降は pthread_setname_np(threadID, name) も追加)
1.1.1.3 root 37: //
38: // 戻り値を返す Linux と NetBSD は、いずれも正常なら 0、失敗ならエラーコード
39: // を返す、としているので、ここでもそれを返す。
40: int
1.1 root 41: PTHREAD_SETNAME(const char *name)
42: {
1.1.1.2 root 43: #if defined(__linux__)
44: // Linux (Ubuntu 20.04) の top はスレッド名があればそれだけ表示するらしい。
45: // スレッド名 "Main" がプロセス名なしに表示されても何のことか分からないので
46: // プロセス名を入れておきたい。
47: // 一方 NetBSD の top ではプロセス名とスレッド名は欄が別なので(そして狭い)
48: // ここにプロセス名は入れたくない。ので、Linux の時だけに分離する。
49: // 他の OS はしらん。
1.1.1.3 root 50: // Linux の setname は '\0' 込みで 16バイト。
51: char buf[16];
1.1.1.2 root 52:
53: snprintf(buf, sizeof(buf), "nono:%s", name);
54: name = buf;
55: #endif
56:
1.1 root 57: #if defined(HAVE_PTHREAD_SETNAME_NP_name)
58: pthread_setname_np(name);
59:
60: #elif defined(HAVE_PTHREAD_SETNAME_NP_th_name)
1.1.1.3 root 61: # if defined(__linux__)
62: // Linux には戻り値がある
63: return pthread_setname_np(pthread_self(), name);
64: # else
1.1 root 65: pthread_setname_np(pthread_self(), name);
1.1.1.3 root 66: # endif
1.1 root 67:
68: #elif defined(HAVE_PTHREAD_SETNAME_NP_th_name_arg)
1.1.1.3 root 69: # if defined(__NetBSD__)
70: // NetBSD には戻り値がある
71: return pthread_setname_np(pthread_self(), name, NULL);
72: # else
1.1 root 73: pthread_setname_np(pthread_self(), name, NULL);
1.1.1.3 root 74: # endif
1.1 root 75:
76: #elif defined(HAVE_PTHREAD_SET_NAME_NP_th_name)
77: pthread_set_name_np(pthread_self(), name);
78:
79: #else
80: // デバッガとかでスレッドに名前がついてると嬉しいという程度なので、
81: // なければ気にしない。
82: #endif
1.1.1.3 root 83:
84: return 0;
85: }
86:
87: // pthread_get{,_}name_np() の OS ごとの違いを吸収して、
88: // 指定のスレッドの名前を std::string で返す。
89: std::string
90: PTHREAD_GETNAME(pthread_t thread)
91: {
92: char name[32];
93:
94: name[0] = '\0';
95:
96: #if defined(HAVE_PTHREAD_GETNAME_NP)
97: pthread_getname_np(thread, name, sizeof(name));
98:
99: #elif defined(HAVE_PTHREAD_GET_NAME_NP)
100: pthread_get_name_np(thread, name, sizeof(name));
101:
102: #else
103: // なければ気にしない
104: #endif
105:
106: return std::string(name);
1.1 root 107: }
1.1.1.4 ! root 108:
! 109:
! 110: //
! 111: // cpu{,_}set_t とその関数群の違いを吸収するクラス。
! 112: //
! 113:
! 114: // NetBSD の cpuset_t は opaque 型なので alloc/free が必要。
! 115: // Linux には alloc/free もあるが実体を用意して使ってもよさげ(*1)。
! 116: // FreeBSD は実体を用意しておく方式のみ。
! 117: // うーんこの。
! 118: // OpenBSD などこの機能がない OS では気にせず無視する。
! 119: //
! 120: // NetBSD Linux FreeBSD
! 121: // ------ ----- -------
! 122: // cpuset_t * cpu_set_t cpuset_t
! 123: // cpuset_create() *1 -
! 124: // cpuset_destroy() *1 -
! 125: // cpuset_zero(s) CPU_ZERO(&s) CPU_ZERO(&s)
! 126: // cpuset_set(n,s) CPU_SET(n,&s) CPU_SET(n,&s)
! 127: // cpuset_size(s) CPU_COUNT(&s) sizeof(s)
! 128: //
! 129: // HAVE_CPUSET_T=no HAVE_CPUSET_T=yes
! 130: // HAVE_CPUSET_T_P=yes HAVE_CPUSET_T_P=yes
! 131:
! 132: #if defined(HAVE_MICPUSET)
! 133:
! 134: // コンストラクタ
! 135: MICPUSet::MICPUSet()
! 136: {
! 137: #if defined(HAVE_CPUSET_CREATE)
! 138: // NetBSD の cpuset_t は opaque 型なので実体を持てない。
! 139: set = cpuset_create();
! 140: cpuset_zero(set);
! 141: #elif defined(HAVE_CPU_ZERO)
! 142: // 実体を持てる。
! 143: set = &entity;
! 144: CPU_ZERO(set);
! 145: #endif
! 146: }
! 147:
! 148: // デストラクタ
! 149: MICPUSet::~MICPUSet()
! 150: {
! 151: #if defined(HAVE_CPUSET_CREATE)
! 152: if (set != NULL) {
! 153: cpuset_destroy(set);
! 154: set = NULL;
! 155: }
! 156: #else
! 157: // メンバが実体なので放置でよい。
! 158: #endif
! 159: }
! 160:
! 161: // ビットをセットする
! 162: void
! 163: MICPUSet::Set(uint n)
! 164: {
! 165: #if defined(HAVE_CPUSET_SET)
! 166: cpuset_set(n, set);
! 167: #elif defined(HAVE_CPU_SET)
! 168: CPU_SET(n, set);
! 169: #endif
! 170: }
! 171:
! 172: // ビットの状態を取得する
! 173: bool
! 174: MICPUSet::Get(uint n) const
! 175: {
! 176: #if defined(HAVE_CPUSET_ISSET)
! 177: return cpuset_isset(n, set);
! 178: #elif defined(HAVE_CPU_ISSET)
! 179: return CPU_ISSET(n, set);
! 180: #else
! 181: return false;
! 182: #endif
! 183: }
! 184:
! 185: // サイズを返す
! 186: size_t
! 187: MICPUSet::Count() const
! 188: {
! 189: #if defined(HAVE_CPUSET_SIZE)
! 190: return cpuset_size(set);
! 191: #elif defined(HAVE_CPU_COUNT)
! 192: return (size_t)CPU_COUNT(set);
! 193: #else
! 194: return sizeof(entity);
! 195: #endif
! 196: }
! 197:
! 198: #endif // HAVE_MICPUSET
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.