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