@@ -145,9 +145,6 @@ struct timespec offset_tp_mono;
145145struct timespec offset_tp_real;
146146#endif
147147
148- // MPI
149- int api_mpi_init_used = 0 ;
150-
151148/* ***************************************************************/
152149/* ********************* SHADOW STACK ****************************/
153150/* Used by 'sieve' to associate mallocs to the code they */
@@ -183,93 +180,88 @@ class StackRecord {
183180
184181std::vector<std::vector<StackRecord> > arielStack; // Per-thread stacks
185182
183+
184+
185+ // Returns true iff "libmpi.so" or "libmpi_cray.so" is found
186+ // in the call stack, indicating that the calling thread is
187+ // currently inside an MPI library. We use this information
188+ // to remap the mpi thread ids to come after the app threads.
186189static const UINT32 MAX_FRAMES = 64 ;
187190bool is_mpi_thread (CONTEXT* ctxt) {
188- void *buf[256 ];
191+ void *buf[2048 ];
189192
190193 // PIN_Backtrace fills the trace array with return addresses.
191194 // numFrames holds the number of captured frames.
192195 UINT32 numFrames = PIN_Backtrace (ctxt, buf, sizeof (buf) / sizeof (buf[0 ]));
193- // std::cout << "numFrames: " << numFrames << std::endl;
194196
195- for (UINT32 i = 0 ; i < numFrames; i++)
196- {
197+ for (UINT32 i = 0 ; i < numFrames; i++) {
197198 // Get the image (module) that contains the current address.
198199 IMG img = IMG_FindByAddress ((ADDRINT)buf[i]);
199- if (IMG_Valid (img))
200- {
201- // Retrieve the image name as a std::string.
200+
201+ if (IMG_Valid (img)) {
202202 std::string imgName = IMG_Name (img);
203- // std::cout << "imgName: " << imgName << std::endl;
203+
204204 // Check if "libmpi.so" appears in the module name.
205- if (imgName.find (" libmpi.so" ) != std::string::npos)
206- {
205+ // Also check for libmpi_cray.so, just in case
206+ if ((imgName.find (" libmpi.so" ) != std::string::npos) ||
207+ (imgName.find (" libmpi_cray.so" ) != std::string::npos)) {
207208 return true ;
208209 }
209210 }
210211 }
211212 return false ;
212213}
213214
214- UINT32 num_threads;
215215
216- // Used for synchronizing access to the thread id map
216+ // Would be more efficient to implement as a TLS_KEY,
217+ // but it is rarely written so false sharing should not
218+ // be an issue
217219std::unordered_map<THREADID, THREADID> remap_id;
218220
219- TLS_KEY syscall_id;
220- TLS_KEY clone_is_mpi;
221- TLS_KEY _os_tid;
222- VOID ThreadStart (THREADID tid, CONTEXT *ctxt, INT32 flags, VOID* v) {
223- // Initialize data for storing syscall number as it is only availble on Entry, not Exit
224- PIN_SetThreadData (syscall_id, new ADDRINT (0 ), tid);
225- PIN_SetThreadData (clone_is_mpi, new bool (false ), tid);
226-
227- // PIN_SetThreadData(_os_tid, new ADDRINT(0), tid);
228- }
229- /*
230- VOID ThreadFini(THREADID tid, CONTEXT *ctxt, INT32 flags, VOID* v) {
231- // Delete thread local storage
232- ADDRINT *syscallNum = static_cast<ADDRINT *>(PIN_GetThreadData(tlsKey, threadId));
233- delete syscallNum;
221+ std::atomic<UINT32> next_app_thread{0 };
222+ std::atomic<UINT32> next_mpi_thread{0 };
223+ std::atomic<UINT32> num_threads{0 };
224+
225+ // Initialize data used for remapping thread IDs
226+ VOID init_remapping_data (UINT32 core_count) {
227+ remap_id[0 ] = 0 ;
228+ next_app_thread = 1 ;
229+ next_mpi_thread = core_count;
230+ num_threads = 1 ;
234231}
235- */
236- UINT32 next_app_thread;
237- UINT32 next_mpi_thread;
238232
239- VOID SyscallEntry (THREADID threadid , CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
233+ VOID SyscallEntry (THREADID tid , CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v)
240234{
241- // Retrieve the system call number.
242235 PIN_LockClient ();
243236 ADDRINT scNo = PIN_GetSyscallNumber (ctxt, std);
244- ADDRINT *syscall_id_ptr = static_cast <ADDRINT *>(PIN_GetThreadData (syscall_id, threadid));
245- *syscall_id_ptr = scNo;
246-
247-
248- bool is_mpi = false ;
249- if (scNo == SYS_clone || scNo == __NR_clone)
250- {
251- PIN_GetLock (&mainLock, threadid);
252- UINT32 next_thread = num_threads;
253- num_threads++;
254-
255- bool is_mpi = is_mpi_thread (ctxt);
256- std::cout << " next_thread is " << next_thread << std::endl;
257- if (is_mpi) {
258- remap_id[next_thread] = next_mpi_thread++;
259- } else {
260- remap_id[next_thread] = next_app_thread++;
261- }
262- PIN_ReleaseLock (&mainLock);
263-
264- std::cout << " --------------\n " ;
265- for (const auto & pair : remap_id) {
266- std::cout << " --> " << pair.first << " -- " << pair.second << std::endl;
267- }
268- std::cout << " --------------\n " ;
269237
238+ if (scNo == SYS_clone || scNo == __NR_clone) {
239+ PIN_GetLock (&mainLock, tid);
240+
241+ // Get the next thread id
242+ UINT32 next_thread = num_threads.fetch_add (1 );
243+
244+ bool is_mpi = is_mpi_thread (ctxt);
245+
246+ // App threads will be numbered 0..num_cores-1
247+ // MPI library threads will be numbered num_cores..
248+ if (is_mpi) {
249+ remap_id[next_thread] = next_mpi_thread.fetch_add (1 );
250+ } else {
251+ remap_id[next_thread] = next_app_thread.fetch_add (1 );
252+ }
253+ PIN_ReleaseLock (&mainLock);
254+
255+ #ifdef ARIEL_DEBUG
256+ fprintf (stderr, " Caught clone syscall. Launching thread %d (MPI?: %d). Current thread map is:\n " , next_thread, is_mpi);
257+ for (const auto & pair : remap_id) {
258+
259+ std::cout << " [ " << pair.first << " -> " << pair.second << " ]\n " ;
260+ }
261+ #endif
270262 }
271- bool *clone_is_mpi_ptr = static_cast < bool *>( PIN_GetThreadData (clone_is_mpi, threadid));
272- *clone_is_mpi_ptr = is_mpi;
263+
264+
273265 PIN_UnlockClient ();
274266}
275267
@@ -439,7 +431,7 @@ VOID WriteFlushInstructionMarker(UINT32 thr, ADDRINT ip, ADDRINT vaddr)
439431 ac.instPtr = (uint64_t ) ip;
440432 ac.flushline .vaddr = (uint32_t ) vaddr;
441433
442- tunnel->writeMessage (thr, ac);
434+ tunnel->writeMessage (remap_id[ thr] , ac);
443435}
444436
445437VOID WriteFenceInstructionMarker (UINT32 thr, ADDRINT ip)
@@ -448,7 +440,7 @@ VOID WriteFenceInstructionMarker(UINT32 thr, ADDRINT ip)
448440 ac.command = ARIEL_FENCE_INSTRUCTION;
449441 ac.instPtr = (uint64_t ) ip;
450442
451- tunnel->writeMessage (thr, ac);
443+ tunnel->writeMessage (remap_id[ thr] , ac);
452444}
453445
454446VOID WriteInstructionRead (ADDRINT* address, UINT32 readSize, THREADID thr, ADDRINT ip,
@@ -466,7 +458,7 @@ VOID WriteInstructionRead(ADDRINT* address, UINT32 readSize, THREADID thr, ADDRI
466458 ac.inst .instClass = instClass;
467459 ac.inst .simdElemCount = simdOpWidth;
468460
469- tunnel->writeMessage (thr, ac);
461+ tunnel->writeMessage (remap_id[ thr] , ac);
470462}
471463
472464VOID WriteInstructionWrite (ADDRINT* address, UINT32 writeSize, THREADID thr, ADDRINT ip,
@@ -498,7 +490,7 @@ VOID WriteInstructionWrite(ADDRINT* address, UINT32 writeSize, THREADID thr, ADD
498490 }
499491 printf("\n");
500492*/
501- tunnel->writeMessage (thr, ac);
493+ tunnel->writeMessage (remap_id[ thr] , ac);
502494}
503495
504496VOID WriteStartInstructionMarker (UINT32 thr, ADDRINT ip, UINT32 instClass, UINT32 simdOpWidth)
@@ -508,15 +500,15 @@ VOID WriteStartInstructionMarker(UINT32 thr, ADDRINT ip, UINT32 instClass, UINT3
508500 ac.instPtr = (uint64_t ) ip;
509501 ac.inst .simdElemCount = simdOpWidth;
510502 ac.inst .instClass = instClass;
511- tunnel->writeMessage (thr, ac);
503+ tunnel->writeMessage (remap_id[ thr] , ac);
512504}
513505
514506VOID WriteEndInstructionMarker (UINT32 thr, ADDRINT ip)
515507{
516508 ArielCommand ac;
517509 ac.command = ARIEL_END_INSTRUCTION;
518510 ac.instPtr = (uint64_t ) ip;
519- tunnel->writeMessage (thr, ac);
511+ tunnel->writeMessage (remap_id[ thr] , ac);
520512}
521513
522514VOID WriteInstructionReadWrite (THREADID thr, ADDRINT* readAddr, UINT32 readSize,
@@ -557,7 +549,7 @@ VOID WriteNoOp(THREADID thr, ADDRINT ip)
557549 ArielCommand ac;
558550 ac.command = ARIEL_NOOP;
559551 ac.instPtr = (uint64_t ) ip;
560- tunnel->writeMessage (thr, ac);
552+ tunnel->writeMessage (remap_id[ thr] , ac);
561553 }
562554 }
563555}
@@ -894,7 +886,7 @@ void mapped_ariel_output_stats()
894886 ArielCommand ac;
895887 ac.command = ARIEL_OUTPUT_STATS;
896888 ac.instPtr = (uint64_t ) 0 ;
897- tunnel->writeMessage (thr, ac);
889+ tunnel->writeMessage (remap_id[ thr] , ac);
898890}
899891
900892// same effect as mapped_ariel_output_stats(), but it also sends a user-defined reference number back
@@ -904,7 +896,7 @@ void mapped_ariel_output_stats_buoy(uint64_t marker)
904896 ArielCommand ac;
905897 ac.command = ARIEL_OUTPUT_STATS;
906898 ac.instPtr = (uint64_t ) marker; // user the instruction pointer slot to send the marker number
907- tunnel->writeMessage (thr, ac);
899+ tunnel->writeMessage (remap_id[ thr] , ac);
908900}
909901
910902void mapped_ariel_flushline (void *virtualAddress)
@@ -926,22 +918,6 @@ void mapped_ariel_fence(void *virtualAddress)
926918 WriteFenceInstructionMarker (thr, ip);
927919}
928920
929- /*
930- void mapped_api_mpi_init() {
931- api_mpi_init_used = 1;
932- }
933- */
934-
935- /*
936- int check_for_api_mpi_init() {
937- if (!api_mpi_init_used && !getenv("ARIEL_DISABLE_MPI_INIT_CHECK")) {
938- fprintf(stderr, "Error: fesimple.cc: The Ariel API verion of MPI_Init_{thread} was not used, which can result in errors when used in conjunction with OpenMP. Please link against the Ariel API (included in this distribution at src/sst/elements/ariel/api) or disable this message by setting the environment variable `ARIEL_DISABLE_MPI_INIT_CHECK`\n");
939- exit(1);
940- }
941- return 0;
942- }
943- */
944-
945921int ariel_mlm_memcpy (void * dest, void * source, size_t size) {
946922#ifdef ARIEL_DEBUG
947923 fprintf (stderr, " Perform a mlm_memcpy from Ariel from %p to %p length %llu\n " ,
@@ -974,7 +950,7 @@ int ariel_mlm_memcpy(void* dest, void* source, size_t size) {
974950 ac.dma_start .dest = ariel_dest;
975951 ac.dma_start .len = length;
976952
977- tunnel->writeMessage (thr, ac);
953+ tunnel->writeMessage (remap_id[ thr] , ac);
978954
979955#ifdef ARIEL_DEBUG
980956 fprintf (stderr, " Done with ariel memcpy.\n " );
@@ -1002,7 +978,7 @@ void ariel_mlm_set_pool(int new_pool)
1002978 ArielCommand ac;
1003979 ac.command = ARIEL_SWITCH_POOL;
1004980 ac.switchPool .pool = newDefaultPool;
1005- tunnel->writeMessage (thr, ac);
981+ tunnel->writeMessage (remap_id[ thr] , ac);
1006982
1007983 // Keep track of the default pool
1008984 default_pool = (UINT32) new_pool;
@@ -1054,7 +1030,7 @@ void* ariel_mmap_mlm(int fileID, size_t size, int level)
10541030 std::cout<<" File ID at FESIMPLE IS : " <<ac.mlm_mmap .fileID <<std::endl;
10551031 std::cout<<" After ******" <<std::endl;
10561032
1057- tunnel->writeMessage (thr, ac);
1033+ tunnel->writeMessage (remap_id[ thr] , ac);
10581034
10591035#ifdef ARIEL_DEBUG
10601036 fprintf (stderr, " %u: Ariel mmap_mlm call allocates data at address: 0x%llx\n " ,
@@ -1109,7 +1085,7 @@ void* ariel_mlm_malloc(size_t size, int level) {
11091085 ac.mlm_map .alloc_level = allocationLevel;
11101086 }
11111087
1112- tunnel->writeMessage (thr, ac);
1088+ tunnel->writeMessage (remap_id[ thr] , ac);
11131089
11141090#ifdef ARIEL_DEBUG
11151091 fprintf (stderr, " %u: Ariel mlm_malloc call allocates data at address: 0x%llx\n " ,
@@ -1154,7 +1130,7 @@ void ariel_mlm_free(void* ptr)
11541130 ArielCommand ac;
11551131 ac.command = ARIEL_ISSUE_TLM_FREE;
11561132 ac.mlm_free .vaddr = virtAddr;
1157- tunnel->writeMessage (thr, ac);
1133+ tunnel->writeMessage (remap_id[ thr] , ac);
11581134
11591135 } else {
11601136 fprintf (stderr, " ARIEL: Call to free in Ariel did not find a matching local allocation, this memory will be leaked.\n " );
@@ -1206,14 +1182,14 @@ VOID ariel_postmalloc_instrument(ADDRINT allocLocation)
12061182 if (toFast[thr].count == 0 ) {
12071183 toFast[thr].valid = false ;
12081184 }
1209- tunnel->writeMessage (thr, ac);
1185+ tunnel->writeMessage (remap_id[ thr] , ac);
12101186 }
12111187 } else if (shouldOverride) {
12121188 ac.mlm_map .alloc_level = overridePool;
1213- tunnel->writeMessage (thr, ac);
1189+ tunnel->writeMessage (remap_id[ thr] , ac);
12141190 } else if (InterceptMemAllocations.Value ()) {
12151191 ac.mlm_map .alloc_level = allocationLevel;
1216- tunnel->writeMessage (thr, ac);
1192+ tunnel->writeMessage (remap_id[ thr] , ac);
12171193 }
12181194
12191195 /* printf("ARIEL: Created a malloc of size: %" PRIu64 " in Ariel\n",
@@ -1231,7 +1207,7 @@ VOID ariel_postfree_instrument(ADDRINT allocLocation)
12311207 ArielCommand ac;
12321208 ac.command = ARIEL_ISSUE_TLM_FREE;
12331209 ac.mlm_free .vaddr = virtAddr;
1234- tunnel->writeMessage (thr, ac);
1210+ tunnel->writeMessage (remap_id[ thr] , ac);
12351211}
12361212
12371213void mapped_ariel_malloc_flag_fortran (int * mallocLocId, int * count, int * level)
@@ -1278,7 +1254,7 @@ void ariel_start_RTL_sim(RTL_shmem_info* rtl_shmem) {
12781254
12791255 THREADID thr = PIN_ThreadId ();
12801256 const uint32_t thrID = (uint32_t ) thr;
1281- tunnel->writeMessage (thrID, acRtl);
1257+ tunnel->writeMessage (remap_id[ thrID] , acRtl);
12821258 #ifdef ARIEL_DEBUG
12831259 fprintf (stderr, " \n Message to add RTL Event into Ariel Event Queue successfully delivered via ArielTunnel" );
12841260 #endif
@@ -1299,7 +1275,7 @@ void ariel_update_RTL_signals(RTL_shmem_info* rtl_shmem) {
12991275
13001276 THREADID thr = PIN_ThreadId ();
13011277 const uint32_t thrID = (uint32_t ) thr;
1302- tunnel->writeMessage (thrID, acRtl);
1278+ tunnel->writeMessage (remap_id[ thrID] , acRtl);
13031279 #ifdef ARIEL_DEBUG
13041280 fprintf (stderr, " \n Message to add RTL Event into Ariel Event Queue to update RTL signals successfully delivered via ArielTunnel" );
13051281 #endif
@@ -1496,29 +1472,12 @@ int main(int argc, char *argv[])
14961472{
14971473 if (PIN_Init (argc, argv)) return Usage ();
14981474
1499- syscall_id = PIN_CreateThreadDataKey (nullptr );
1500- if (syscall_id == INVALID_TLS_KEY) {
1501- std::cerr << " Failed to create thread-local storage key!" << std::endl;
1502- return 1 ;
1503- }
1504- clone_is_mpi = PIN_CreateThreadDataKey (nullptr );
1505- if (clone_is_mpi == INVALID_TLS_KEY) {
1506- std::cerr << " Failed to create thread-local storage key!" << std::endl;
1507- return 1 ;
1508- }
1509- _os_tid = PIN_CreateThreadDataKey (nullptr );
1510- if (_os_tid == INVALID_TLS_KEY) {
1511- std::cerr << " Failed to create thread-local storage key!" << std::endl;
1512- return 1 ;
1513- }
1514- num_threads = 1 ;
15151475
15161476
15171477 // Load the symbols ready for us to mangle functions.
15181478 // PIN_InitSymbolsAlt(IFUNC_SYMBOLS);
15191479 PIN_InitSymbols ();
15201480 PIN_AddFiniFunction (Fini, 0 );
1521- PIN_AddThreadStartFunction (ThreadStart, nullptr );
15221481 PIN_AddSyscallEntryFunction (SyscallEntry, 0 );
15231482
15241483 PIN_InitLock (&mainLock);
@@ -1560,9 +1519,7 @@ int main(int argc, char *argv[])
15601519
15611520 core_count = MaxCoreCount.Value ();
15621521
1563- remap_id[0 ] = 0 ;
1564- next_app_thread = 1 ;
1565- next_mpi_thread = core_count;
1522+ init_remapping_data (core_count);
15661523
15671524 instrument_instructions = InstrumentInstructions.Value ();
15681525
0 commit comments