|
6 | 6 | #ifdef __cplusplus |
7 | 7 | #include <atomic> |
8 | 8 | #include <queue> |
| 9 | +#include <utility> |
9 | 10 | #else |
10 | 11 | #include <stdatomic.h> |
11 | 12 | #endif |
@@ -279,6 +280,8 @@ void CthFree(CthThread t); |
279 | 280 |
|
280 | 281 | void CthResume(CthThread t); |
281 | 282 |
|
| 283 | +int CthIsSuspendable(CthThread t); |
| 284 | + |
282 | 285 | void CthSuspend(void); |
283 | 286 |
|
284 | 287 | void CthAwaken(CthThread th); |
@@ -550,15 +553,25 @@ void CmiInitCPUTopology(char **argv); |
550 | 553 | void CmiInitCPUAffinity(char **argv); |
551 | 554 | int CmiOnCore(void); |
552 | 555 |
|
553 | | -void __CmiEnforceMsgHelper(const char *expr, const char *fileName, int lineNum, |
554 | | - const char *msg, ...); |
| 556 | +#define __CMK_STRING(x) #x |
| 557 | +#define __CMK_XSTRING(x) __CMK_STRING(x) |
555 | 558 |
|
556 | | -#define CmiEnforce(condition) \ |
557 | | - do { \ |
558 | | - if (!(condition)) { \ |
559 | | - __CmiEnforceMsgHelper(#condition, __FILE__, __LINE__, ""); \ |
560 | | - } \ |
561 | | - } while (0) |
| 559 | +void __CmiEnforceHelper(const char* expr, const char* fileName, const char* lineNum); |
| 560 | +void __CmiEnforceMsgHelper(const char* expr, const char* fileName, |
| 561 | + const char* lineNum, const char* msg, ...); |
| 562 | + |
| 563 | +#define CmiEnforce(expr) \ |
| 564 | + ((void)(CMI_LIKELY(expr) ? 0 \ |
| 565 | + : (__CmiEnforceHelper(__CMK_STRING(expr), __FILE__, \ |
| 566 | + __CMK_XSTRING(__LINE__)), \ |
| 567 | + 0))) |
| 568 | + |
| 569 | +#define CmiEnforceMsg(expr, ...) \ |
| 570 | + ((void)(CMI_LIKELY(expr) \ |
| 571 | + ? 0 \ |
| 572 | + : (__CmiEnforceMsgHelper(__CMK_STRING(expr), __FILE__, \ |
| 573 | + __CMK_XSTRING(__LINE__), __VA_ARGS__), \ |
| 574 | + 0))) |
562 | 575 |
|
563 | 576 | double getCurrentTime(void); |
564 | 577 | double CmiWallTimer(void); |
@@ -1200,4 +1213,109 @@ void CmiInterSyncNodeSendAndFreeFn(int destNode, int partition, int messageSize, |
1200 | 1213 |
|
1201 | 1214 | /* end of variables and functions for partition */ |
1202 | 1215 |
|
| 1216 | +#define CMI_IPC_CUTOFF_ARG "ipccutoff" |
| 1217 | +#define CMI_IPC_CUTOFF_DESC "max message size for cmi-shmem (in bytes)" |
| 1218 | +#define CMI_IPC_POOL_SIZE_ARG "ipcpoolsize" |
| 1219 | +#define CMI_IPC_POOL_SIZE_DESC "size of cmi-shmem pool (in bytes)" |
| 1220 | + |
| 1221 | +struct CmiIpcManager; |
| 1222 | + |
| 1223 | +#ifndef __cplusplus |
| 1224 | +typedef struct CmiIpcManager CmiIpcManager; |
| 1225 | +#endif |
| 1226 | + |
| 1227 | +#ifdef __cplusplus |
| 1228 | +namespace cmi { |
| 1229 | +namespace ipc { |
| 1230 | +// recommended cutoff for block sizes |
| 1231 | +CpvExtern(size_t, kRecommendedCutoff); |
| 1232 | +// used to represent an empty linked list |
| 1233 | +constexpr auto nil = uintptr_t(0); |
| 1234 | +// used to represent the tail of a linked list |
| 1235 | +constexpr auto max = UINTPTR_MAX; |
| 1236 | +// used to indicate a message bound for a node |
| 1237 | +constexpr auto nodeDatagram = UINT16_MAX; |
| 1238 | +// default number of attempts to alloc before timing out |
| 1239 | +constexpr auto defaultTimeout = 4; |
| 1240 | +} // namespace ipc |
| 1241 | +} // namespace cmi |
| 1242 | + |
| 1243 | +// alignas is used for padding here, rather than for alignment of the |
| 1244 | +// CmiIpcBlock itself. |
| 1245 | +struct alignas(ALIGN_BYTES) CmiIpcBlock { |
| 1246 | +public: |
| 1247 | + // "home" rank of the block |
| 1248 | + int src; |
| 1249 | + int dst; |
| 1250 | + uintptr_t orig; |
| 1251 | + uintptr_t next; |
| 1252 | + size_t size; |
| 1253 | + |
| 1254 | + CmiIpcBlock(size_t size_, uintptr_t orig_) |
| 1255 | + : orig(orig_), next(cmi::ipc::nil), size(size_) {} |
| 1256 | +}; |
| 1257 | + |
| 1258 | +enum CmiIpcAllocStatus { |
| 1259 | + CMI_IPC_OUT_OF_MEMORY, |
| 1260 | + CMI_IPC_REMOTE_DESTINATION, |
| 1261 | + CMI_IPC_SUCCESS, |
| 1262 | + CMI_IPC_TIMEOUT |
| 1263 | +}; |
| 1264 | + |
| 1265 | +// sets up ipc environment |
| 1266 | +void CmiIpcInit(char** argv); |
| 1267 | + |
| 1268 | +// creates an ipc manager, waking the thread when it's done |
| 1269 | +// ( this must be called in the same order on all pes! ) |
| 1270 | +CmiIpcManager* CmiMakeIpcManager(CthThread th); |
| 1271 | + |
| 1272 | +// push/pop blocks from the manager's send/recv queue |
| 1273 | +bool CmiPushIpcBlock(CmiIpcManager*, CmiIpcBlock*); |
| 1274 | +CmiIpcBlock* CmiPopIpcBlock(CmiIpcManager*); |
| 1275 | + |
| 1276 | +// tries to allocate a block, returning null if unsucessful |
| 1277 | +// (fails when other PEs are contending resources) |
| 1278 | +// second value of pair indicates failure cause |
| 1279 | +std::pair<CmiIpcBlock*, CmiIpcAllocStatus> CmiAllocIpcBlock(CmiIpcManager*, int node, std::size_t size); |
| 1280 | + |
| 1281 | +// frees a block -- enabling it to be used again |
| 1282 | +void CmiFreeIpcBlock(CmiIpcManager*, CmiIpcBlock*); |
| 1283 | + |
| 1284 | +// currently a no-op but may be eventually usable |
| 1285 | +// intended to "capture" blocks from remote pes |
| 1286 | +inline void CmiCacheIpcBlock(CmiIpcBlock*) { return; } |
| 1287 | + |
| 1288 | +// identifies whether a void* is the payload of a block |
| 1289 | +// belonging to the given node |
| 1290 | +CmiIpcBlock* CmiIsIpcBlock(CmiIpcManager*, void*, int node); |
| 1291 | + |
| 1292 | +// if (init) is true -- initializes the |
| 1293 | +// memory segment for use as a message |
| 1294 | +void* CmiIpcBlockToMsg(CmiIpcBlock*, bool init); |
| 1295 | + |
| 1296 | +// equivalent to calling above with (init = false) |
| 1297 | +inline void* CmiIpcBlockToMsg(CmiIpcBlock* block) { |
| 1298 | + auto res = (char*)block + sizeof(CmiIpcBlock) + sizeof(CmiChunkHeader); |
| 1299 | + return (void*)res; |
| 1300 | +} |
| 1301 | + |
| 1302 | +inline CmiIpcBlock* CmiMsgToIpcBlock(CmiIpcManager* manager, void* msg) { |
| 1303 | + return CmiIsIpcBlock(manager, (char*)msg - sizeof(CmiChunkHeader), CmiMyNode()); |
| 1304 | +} |
| 1305 | + |
| 1306 | +CmiIpcBlock* CmiMsgToIpcBlock(CmiIpcManager*, char* msg, std::size_t len, int node, |
| 1307 | + int rank = cmi::ipc::nodeDatagram, |
| 1308 | + int timeout = cmi::ipc::defaultTimeout); |
| 1309 | + |
| 1310 | +// deliver a block as a message |
| 1311 | +void CmiDeliverIpcBlockMsg(CmiIpcBlock*); |
| 1312 | + |
| 1313 | +inline const std::size_t& CmiRecommendedIpcBlockCutoff(void) { |
| 1314 | + using namespace cmi::ipc; |
| 1315 | + return CpvAccess(kRecommendedCutoff); |
| 1316 | +} |
| 1317 | +#endif /* __cplusplus */ |
| 1318 | + |
| 1319 | +CsvExtern(CmiIpcManager*, coreIpcManager_); |
| 1320 | + |
1203 | 1321 | #endif // CONVERSE_H |
0 commit comments