--- nono/lib/mythread.cpp 2026/04/29 17:04:34 1.1 +++ nono/lib/mythread.cpp 2026/04/29 17:05:26 1.1.1.4 @@ -4,7 +4,9 @@ // Licensed under nono-license.txt // +// // pthread の OS ごとに違う部分を吸収する +// #include "mythread.h" #include @@ -12,6 +14,16 @@ #include #endif +#if defined(HAVE_PTHREAD_SETAFFINITY_NP) +// pthread_setaffinity_np は今のところどの OS でもだいたい同じだが +// が必要な関係でこっちに置いておく。 +int +PTHREAD_SETAFFINITY(pthread_t thread, const MICPUSet& m) +{ + return pthread_setaffinity_np(thread, m.Count(), m.Get()); +} +#endif + // pthread_set{,_}name_np() のプロトタイプは OS によってみんなフリーダムなので // (というか _np は Non Portable か Non Posix のことらしい?)、 // ここで吸収する。 @@ -22,17 +34,44 @@ // OpenBSD は void pthread_set_name_np(threadID, name) // FreeBSD は void pthread_set_name_np(threadID, name) // (2020/06 以降は pthread_setname_np(threadID, name) も追加) -void +// +// 戻り値を返す Linux と NetBSD は、いずれも正常なら 0、失敗ならエラーコード +// を返す、としているので、ここでもそれを返す。 +int PTHREAD_SETNAME(const char *name) { +#if defined(__linux__) + // Linux (Ubuntu 20.04) の top はスレッド名があればそれだけ表示するらしい。 + // スレッド名 "Main" がプロセス名なしに表示されても何のことか分からないので + // プロセス名を入れておきたい。 + // 一方 NetBSD の top ではプロセス名とスレッド名は欄が別なので(そして狭い) + // ここにプロセス名は入れたくない。ので、Linux の時だけに分離する。 + // 他の OS はしらん。 + // Linux の setname は '\0' 込みで 16バイト。 + char buf[16]; + + snprintf(buf, sizeof(buf), "nono:%s", name); + name = buf; +#endif + #if defined(HAVE_PTHREAD_SETNAME_NP_name) pthread_setname_np(name); #elif defined(HAVE_PTHREAD_SETNAME_NP_th_name) +# if defined(__linux__) + // Linux には戻り値がある + return pthread_setname_np(pthread_self(), name); +# else pthread_setname_np(pthread_self(), name); +# endif #elif defined(HAVE_PTHREAD_SETNAME_NP_th_name_arg) +# if defined(__NetBSD__) + // NetBSD には戻り値がある + return pthread_setname_np(pthread_self(), name, NULL); +# else pthread_setname_np(pthread_self(), name, NULL); +# endif #elif defined(HAVE_PTHREAD_SET_NAME_NP_th_name) pthread_set_name_np(pthread_self(), name); @@ -41,4 +80,119 @@ PTHREAD_SETNAME(const char *name) // デバッガとかでスレッドに名前がついてると嬉しいという程度なので、 // なければ気にしない。 #endif + + return 0; +} + +// pthread_get{,_}name_np() の OS ごとの違いを吸収して、 +// 指定のスレッドの名前を std::string で返す。 +std::string +PTHREAD_GETNAME(pthread_t thread) +{ + char name[32]; + + name[0] = '\0'; + +#if defined(HAVE_PTHREAD_GETNAME_NP) + pthread_getname_np(thread, name, sizeof(name)); + +#elif defined(HAVE_PTHREAD_GET_NAME_NP) + pthread_get_name_np(thread, name, sizeof(name)); + +#else + // なければ気にしない +#endif + + return std::string(name); } + + +// +// cpu{,_}set_t とその関数群の違いを吸収するクラス。 +// + +// NetBSD の cpuset_t は opaque 型なので alloc/free が必要。 +// Linux には alloc/free もあるが実体を用意して使ってもよさげ(*1)。 +// FreeBSD は実体を用意しておく方式のみ。 +// うーんこの。 +// OpenBSD などこの機能がない OS では気にせず無視する。 +// +// NetBSD Linux FreeBSD +// ------ ----- ------- +// cpuset_t * cpu_set_t cpuset_t +// cpuset_create() *1 - +// cpuset_destroy() *1 - +// cpuset_zero(s) CPU_ZERO(&s) CPU_ZERO(&s) +// cpuset_set(n,s) CPU_SET(n,&s) CPU_SET(n,&s) +// cpuset_size(s) CPU_COUNT(&s) sizeof(s) +// +// HAVE_CPUSET_T=no HAVE_CPUSET_T=yes +// HAVE_CPUSET_T_P=yes HAVE_CPUSET_T_P=yes + +#if defined(HAVE_MICPUSET) + +// コンストラクタ +MICPUSet::MICPUSet() +{ +#if defined(HAVE_CPUSET_CREATE) + // NetBSD の cpuset_t は opaque 型なので実体を持てない。 + set = cpuset_create(); + cpuset_zero(set); +#elif defined(HAVE_CPU_ZERO) + // 実体を持てる。 + set = &entity; + CPU_ZERO(set); +#endif +} + +// デストラクタ +MICPUSet::~MICPUSet() +{ +#if defined(HAVE_CPUSET_CREATE) + if (set != NULL) { + cpuset_destroy(set); + set = NULL; + } +#else + // メンバが実体なので放置でよい。 +#endif +} + +// ビットをセットする +void +MICPUSet::Set(uint n) +{ +#if defined(HAVE_CPUSET_SET) + cpuset_set(n, set); +#elif defined(HAVE_CPU_SET) + CPU_SET(n, set); +#endif +} + +// ビットの状態を取得する +bool +MICPUSet::Get(uint n) const +{ +#if defined(HAVE_CPUSET_ISSET) + return cpuset_isset(n, set); +#elif defined(HAVE_CPU_ISSET) + return CPU_ISSET(n, set); +#else + return false; +#endif +} + +// サイズを返す +size_t +MICPUSet::Count() const +{ +#if defined(HAVE_CPUSET_SIZE) + return cpuset_size(set); +#elif defined(HAVE_CPU_COUNT) + return (size_t)CPU_COUNT(set); +#else + return sizeof(entity); +#endif +} + +#endif // HAVE_MICPUSET