@@ -280,7 +280,7 @@ _Static_assert(sizeof(EhFrameHeader) == 20, "EhFrameHeader layout mismatch");
280280 */
281281typedef struct {
282282 FILE * perf_map ; // File handle for the jitdump file
283- PyThread_type_lock map_lock ; // Thread synchronization lock
283+ PyMutex map_lock ; // Thread synchronization lock
284284 void * mapped_buffer ; // Memory-mapped region (signals perf we're active)
285285 size_t mapped_size ; // Size of the mapped region
286286 uint32_t code_id ; // Counter for unique code region identifiers
@@ -413,6 +413,12 @@ static void perf_map_jit_write_header(int pid, FILE* out_file) {
413413 * Returns: Pointer to initialized state, or NULL on failure
414414 */
415415static void * perf_map_jit_init (void ) {
416+ PyMutex_Lock (& perf_jit_map_state .map_lock );
417+ if (perf_jit_map_state .perf_map != NULL ) {
418+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
419+ return & perf_jit_map_state ;
420+ }
421+
416422 char filename [100 ];
417423 int pid = getpid ();
418424
@@ -422,13 +428,15 @@ static void* perf_map_jit_init(void) {
422428 /* Create/open the jitdump file with appropriate permissions */
423429 const int fd = open (filename , O_CREAT | O_TRUNC | O_RDWR , 0666 );
424430 if (fd == -1 ) {
431+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
425432 return NULL ; // Failed to create file
426433 }
427434
428435 /* Get system page size for memory mapping */
429436 const long page_size = sysconf (_SC_PAGESIZE );
430437 if (page_size == -1 ) {
431438 close (fd );
439+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
432440 return NULL ; // Failed to get page size
433441 }
434442
@@ -457,6 +465,7 @@ static void* perf_map_jit_init(void) {
457465 if (perf_jit_map_state .mapped_buffer == MAP_FAILED ) {
458466 perf_jit_map_state .mapped_buffer = NULL ;
459467 close (fd );
468+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
460469 return NULL ; // Memory mapping failed
461470 }
462471 (void )_PyAnnotateMemoryMap (perf_jit_map_state .mapped_buffer , page_size ,
@@ -469,6 +478,7 @@ static void* perf_map_jit_init(void) {
469478 perf_jit_map_state .perf_map = fdopen (fd , "w+" );
470479 if (perf_jit_map_state .perf_map == NULL ) {
471480 close (fd );
481+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
472482 return NULL ; // Failed to create FILE*
473483 }
474484
@@ -484,19 +494,6 @@ static void* perf_map_jit_init(void) {
484494 /* Write the jitdump file header */
485495 perf_map_jit_write_header (pid , perf_jit_map_state .perf_map );
486496
487- /*
488- * Initialize thread synchronization lock
489- *
490- * Multiple threads may attempt to write to the jitdump file
491- * simultaneously. This lock ensures thread-safe access to the
492- * global jitdump state.
493- */
494- perf_jit_map_state .map_lock = PyThread_allocate_lock ();
495- if (perf_jit_map_state .map_lock == NULL ) {
496- fclose (perf_jit_map_state .perf_map );
497- return NULL ; // Failed to create lock
498- }
499-
500497 /* Initialize code ID counter */
501498 perf_jit_map_state .code_id = 0 ;
502499 perf_jit_map_state .build_id_salt =
@@ -508,6 +505,7 @@ static void* perf_map_jit_init(void) {
508505 trampoline_api .code_padding = _Py_SIZE_ROUND_UP (unwind_data_size , 16 );
509506 trampoline_api .code_alignment = 32 ;
510507
508+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
511509 return & perf_jit_map_state ;
512510}
513511
@@ -531,11 +529,9 @@ static void perf_map_jit_write_entry_with_name(
531529)
532530{
533531 /* Initialize jitdump system on first use */
534- if (perf_jit_map_state .perf_map == NULL ) {
535- void * ret = perf_map_jit_init ();
536- if (ret == NULL ){
537- return ; // Initialization failed, silently abort
538- }
532+ void * ret = perf_map_jit_init ();
533+ if (ret == NULL ) {
534+ return ; // Initialization failed, silently abort
539535 }
540536
541537 if (entry == NULL ) {
@@ -583,7 +579,7 @@ static void perf_map_jit_write_entry_with_name(
583579 * a process-global code_id. Serialize the whole sequence so concurrent JIT
584580 * compilation cannot interleave records or reuse an ID.
585581 */
586- PyThread_acquire_lock ( perf_jit_map_state .map_lock , 1 );
582+ PyMutex_Lock ( & perf_jit_map_state .map_lock );
587583
588584 /*
589585 * Write Code Unwinding Information Event
@@ -699,7 +695,7 @@ static void perf_map_jit_write_entry_with_name(
699695 }
700696
701697 /* Clean up allocated memory */
702- PyThread_release_lock ( perf_jit_map_state .map_lock );
698+ PyMutex_Unlock ( & perf_jit_map_state .map_lock );
703699 PyMem_RawFree (perf_map_entry );
704700}
705701
@@ -778,15 +774,12 @@ static int perf_map_jit_fini(void* state) {
778774 * writing to the file when we close it. This prevents corruption
779775 * and ensures all data is properly flushed.
780776 */
777+ PyMutex_Lock (& perf_jit_map_state .map_lock );
781778 if (perf_jit_map_state .perf_map != NULL ) {
782- PyThread_acquire_lock (perf_jit_map_state .map_lock , 1 );
783779 fclose (perf_jit_map_state .perf_map ); // This also flushes buffers
784- PyThread_release_lock (perf_jit_map_state .map_lock );
785-
786- /* Clean up synchronization primitive */
787- PyThread_free_lock (perf_jit_map_state .map_lock );
788780 perf_jit_map_state .perf_map = NULL ;
789781 }
782+ PyMutex_Unlock (& perf_jit_map_state .map_lock );
790783
791784 /*
792785 * Unmap the memory region
0 commit comments