Back to Taskflow

Taskflow: A General

docs/os_8hpp_source.html

4.1.010.1 KB
Original Source

| | Taskflow: A General-purpose Task-parallel Programming System |

Loading...

Searching...

No Matches

os.hpp

1#pragma once

2

3#include <cstdlib>

4#include <cstdio>

5#include <string>

6#include <thread>

7#include <new>

8

9#define TF_OS_LINUX 0

10#define TF_OS_DRAGONFLY 0

11#define TF_OS_FREEBSD 0

12#define TF_OS_NETBSD 0

13#define TF_OS_OPENBSD 0

14#define TF_OS_DARWIN 0

15#define TF_OS_WINDOWS 0

16#define TF_OS_CNK 0

17#define TF_OS_HURD 0

18#define TF_OS_SOLARIS 0

19#define TF_OS_UNIX 0

20

21#ifdef _WIN32

22#undef TF_OS_WINDOWS

23#define TF_OS_WINDOWS 1

24#endif

25

26#ifdef __CYGWIN__

27#undef TF_OS_WINDOWS

28#define TF_OS_WINDOWS 1

29#endif

30

31#if (defined __APPLE__ && defined __MACH__)

32#undef TF_OS_DARWIN

33#define TF_OS_DARWIN 1

34#endif

35

36// in some ppc64 linux installations, only the second condition is met

37#if (defined __linux)

38#undef TF_OS_LINUX

39#define TF_OS_LINUX 1

40#elif (defined __linux__)

41#undef TF_OS_LINUX

42#define TF_OS_LINUX 1

43#else

44#endif

45

46#if (defined __DragonFly__)

47#undef TF_OS_DRAGONFLY

48#define TF_OS_DRAGONFLY 1

49#endif

50

51#if (defined __FreeBSD__)

52#undef TF_OS_FREEBSD

53#define TF_OS_FREEBSD 1

54#endif

55

56#if (defined __NetBSD__)

57#undef TF_OS_NETBSD

58#define TF_OS_NETBSD 1

59#endif

60

61#if (defined __OpenBSD__)

62#undef TF_OS_OPENBSD

63#define TF_OS_OPENBSD 1

64#endif

65

66#if (defined __bgq__)

67#undef TF_OS_CNK

68#define TF_OS_CNK 1

69#endif

70

71#if (defined __GNU__)

72#undef TF_OS_HURD

73#define TF_OS_HURD 1

74#endif

75

76#if (defined __sun)

77#undef TF_OS_SOLARIS

78#define TF_OS_SOLARIS 1

79#endif

80

81#if (1 != \

82 TF_OS_LINUX + TF_OS_DRAGONFLY + TF_OS_FREEBSD + TF_OS_NETBSD + \

83 TF_OS_OPENBSD + TF_OS_DARWIN + TF_OS_WINDOWS + TF_OS_HURD + \

84 TF_OS_SOLARIS)

85#define TF_OS_UNKNOWN 1

86#endif

87

88#if TF_OS_LINUX || TF_OS_DRAGONFLY || TF_OS_FREEBSD || TF_OS_NETBSD || \

89 TF_OS_OPENBSD || TF_OS_DARWIN || TF_OS_HURD || TF_OS_SOLARIS

90#undef TF_OS_UNIX

91#define TF_OS_UNIX 1

92#endif

93

94// ------------------------------------------------------------------------------------------------

95// Number of bits used by the OS for user-space virtual addresses

96// Used as the default PtrBits for TaggedHead64 to leave the remaining

97// high bits free for the ABA version counter.

98// ------------------------------------------------------------------------------------------------

99//

100// No standard C++ mechanism exposes the VA width; we derive it from

101// architecture-specific predefined macros. Override by defining

102// TF_POINTER_BITS before including this header if your environment

103// differs (e.g. x86-64 with LA57 5-level paging uses 57 bits).

104

105#if defined(TF_POINTER_BITS)

106// user-defined override — accepted as-is

107

108#elif defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)

109// 4-level paging: 48 bits. If your kernel enables LA57 (5-level paging,

110// 57-bit VA), compile with -DTF_POINTER_BITS=57. Note that only 7 bits

111// remain for the ABA tag in that case; TaggedHead128 is a better choice.

112 #define TF_POINTER_BITS 48

113

114#elif defined(__aarch64__) || defined(_M_ARM64)

115 #define TF_POINTER_BITS 48 // ARMv8 48-bit VA (TTBR0 range)

116

117#elif defined(__riscv) && __riscv_xlen == 64

118 #define TF_POINTER_BITS 48 // SV48 worst case; SV39 gives 25 free bits

119

120#else

121 #define TF_POINTER_BITS (sizeof(void*) * CHAR_BIT) // 32-bit or unknown

122#endif

123

124

125// ------------------------------------------------------------------------------------------------

126// Cache line size detection.

127//

128// Underestimating causes false sharing (hurts performance).

129// Overestimating wastes memory.

130// 64B is correct for the vast majority of modern server/desktop CPUs.

131// ------------------------------------------------------------------------------------------------

132

133#if defined(__i386__) || defined(__x86_64__) || \

134 defined(_M_IX86) || defined(_M_AMD64)

135// All modern x86/x86_64 CPUs (Intel, AMD) since Pentium 4.

136 #define TF_CACHELINE_SIZE 64

137

138#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)

139// 64-bit ARM: Apple Silicon (M1/M2/M3), AWS Graviton, Qualcomm Oryon, etc.

140 #define TF_CACHELINE_SIZE 64

141

142#elif defined(__arm__) || defined(_M_ARM)

143// 32-bit ARM — cache line size depends on the ARM architecture revision.

144 #if defined(__ARM_ARCH_5T__) || \

145 defined(__ARM_ARCH_5TE__) || \

146 defined(__ARM_ARCH_6__)

147 #define TF_CACHELINE_SIZE 32

148 #else

149// ARMv7-A (Cortex-A5/A7/A8/A9/A15) and later 32-bit ARM.

150 #define TF_CACHELINE_SIZE 64

151 #endif

152

153#elif defined(__powerpc64__) || defined(__ppc64__)

154// IBM POWER7/8/9/10 and PowerPC64 (e.g., original Xbox 360-era G5).

155 #define TF_CACHELINE_SIZE 128

156

157#elif defined(__powerpc__) || defined(__ppc__)

158// Older 32-bit PowerPC (G3/G4 era embedded systems).

159 #define TF_CACHELINE_SIZE 32

160

161#elif defined(__s390x__) || defined(__zarch__)

162// IBM Z (z13 and later). Unusually large at 256B.

163 #define TF_CACHELINE_SIZE 256

164

165#elif defined(__riscv)

166// RISC-V: SiFive U74, Alibaba T-Head, etc.

167 #define TF_CACHELINE_SIZE 64

168

169#elif defined(__mips__) || defined(__mips64)

170// MIPS32/MIPS64 (embedded and networking SoCs).

171 #define TF_CACHELINE_SIZE 64

172

173#elif defined(__sparc__) || defined(__sparc64__)

174// Oracle/Fujitsu SPARC.

175 #define TF_CACHELINE_SIZE 64

176

177#elif defined(__loongarch64)

178// LoongArch (Loongson 3A5000 and later).

179 #define TF_CACHELINE_SIZE 64

180

181#elif defined(__alpha__)

182// DEC/Compaq Alpha.

183 #define TF_CACHELINE_SIZE 64

184

185#endif

186

187#ifndef TF_CACHELINE_SIZE

188// Conservative fallback. If we land here, the architecture is unknown.

189// 64B is correct for virtually all modern CPUs. Overestimating wastes

190// a small amount of space; underestimating causes false sharing.

191 #define TF_CACHELINE_SIZE 64

192#endif

193

194namespace tf {

195

218template <typename T>

219class CachelineAligned {

220public:

224alignas (TF_CACHELINE_SIZE) T data;

225

239 T& get() { return data; }

240

254const T& get() const { return data; }

255};

256

274inline std::string get_env(const std::string& str) {

275#ifdef _MSC_VER

276char *ptr = nullptr;

277size_t len = 0;

278

279if(_dupenv_s(&ptr, &len, str.c_str()) == 0 && ptr != nullptr) {

280 std::string res(ptr, len);

281 std::free(ptr);

282return res;

283 }

284return "";

285

286#else

287auto ptr = std::getenv(str.c_str());

288return ptr ? ptr : "";

289#endif

290}

291

310inline bool has_env(const std::string& str) {

311#ifdef _MSC_VER

312char *ptr = nullptr;

313size_t len = 0;

314

315if(_dupenv_s(&ptr, &len, str.c_str()) == 0 && ptr != nullptr) {

316 std::string res(ptr, len);

317 std::free(ptr);

318return true;

319 }

320return false;

321

322#else

323auto ptr = std::getenv(str.c_str());

324return ptr ? true : false;

325#endif

326}

327

328

329} // end of namespace tf -----------------------------------------------------

330

331

332

333

334

335

336

337

338

tf::CachelineAligned

class to ensure cacheline-aligned storage for an object.

Definition os.hpp:219

tf::CachelineAligned::get

T & get()

accesses the underlying object

Definition os.hpp:239

tf::CachelineAligned::get

const T & get() const

accesses the underlying object as a constant reference

Definition os.hpp:254

tf::CachelineAligned::data

T data

The stored object, aligned to twice the cacheline size.

Definition os.hpp:224

tf

taskflow namespace

Definition small_vector.hpp:20

tf::get_env

std::string get_env(const std::string &str)

retrieves the value of an environment variable

Definition os.hpp:274

tf::has_env

bool has_env(const std::string &str)

checks whether an environment variable is defined

Definition os.hpp:310