File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / mythread.cpp
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:26 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, v024, v023, v022, v021, v020, HEAD
nono 1.0.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

//
// pthread の OS ごとに違う部分を吸収する
//

#include "mythread.h"
#include <pthread.h>
#if defined(HAVE_PTHREAD_NP_H)
#include <pthread_np.h>
#endif

#if defined(HAVE_PTHREAD_SETAFFINITY_NP)
// pthread_setaffinity_np は今のところどの OS でもだいたい同じだが
// <pthread_np.h> が必要な関係でこっちに置いておく。
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 のことらしい?)、
// ここで吸収する。
//
// MacOSX  は void pthread_setname_np(name)
// Linux   は int  pthread_setname_np(threadID, name)
// NetBSD  は int  pthread_setname_np(threadID, name, arg)
// OpenBSD は void pthread_set_name_np(threadID, name)
// FreeBSD は void pthread_set_name_np(threadID, name)
// (2020/06 以降は pthread_setname_np(threadID, name) も追加)
//
// 戻り値を返す 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);

#else
	// デバッガとかでスレッドに名前がついてると嬉しいという程度なので、
	// なければ気にしない。
#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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.