@@ -439,7 +439,7 @@ traceback_new(void)
439439}
440440
441441static int
442- tracemalloc_log_alloc (void * ptr , size_t size )
442+ tracemalloc_add_trace (void * ptr , size_t size )
443443{
444444 traceback_t * traceback ;
445445 trace_t trace ;
@@ -470,7 +470,7 @@ tracemalloc_log_alloc(void *ptr, size_t size)
470470}
471471
472472static void
473- tracemalloc_log_free (void * ptr )
473+ tracemalloc_remove_trace (void * ptr )
474474{
475475 trace_t trace ;
476476
@@ -483,118 +483,57 @@ tracemalloc_log_free(void *ptr)
483483}
484484
485485static void *
486- tracemalloc_malloc (void * ctx , size_t size , int gil_held )
486+ tracemalloc_malloc (void * ctx , size_t size )
487487{
488488 PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
489- #if defined(TRACE_RAW_MALLOC ) && defined(WITH_THREAD )
490- PyGILState_STATE gil_state ;
491- #endif
492489 void * ptr ;
493490
494- if (get_reentrant ()) {
495- return alloc -> malloc (alloc -> ctx , size );
496- }
497-
498- /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc()
499- for allocations larger than 512 bytes. PyGILState_Ensure() may call
500- PyMem_RawMalloc() indirectly which would call PyGILState_Ensure() if
501- reentrant are not disabled. */
502- set_reentrant (1 );
503- #ifdef WITH_THREAD
504- #ifdef TRACE_RAW_MALLOC
505- if (!gil_held )
506- gil_state = PyGILState_Ensure ();
507- #else
508- assert (gil_held );
509- #endif
510- #endif
511491 ptr = alloc -> malloc (alloc -> ctx , size );
492+ if (ptr == NULL )
493+ return NULL ;
512494
513- if (ptr != NULL ) {
514- if (tracemalloc_log_alloc (ptr , size ) < 0 ) {
515- /* Memory allocation failed */
516- alloc -> free (alloc -> ctx , ptr );
517- ptr = NULL ;
518- }
495+ if (tracemalloc_add_trace (ptr , size ) < 0 ) {
496+ /* Failed to allocate a trace for the new memory block */
497+ alloc -> free (alloc -> ctx , ptr );
498+ return NULL ;
519499 }
520- set_reentrant (0 );
521-
522- #if defined(TRACE_RAW_MALLOC ) && defined(WITH_THREAD )
523- if (!gil_held )
524- PyGILState_Release (gil_state );
525- #endif
526-
527500 return ptr ;
528501}
529502
530503static void *
531- tracemalloc_realloc (void * ctx , void * ptr , size_t new_size , int gil_held )
504+ tracemalloc_realloc (void * ctx , void * ptr , size_t new_size )
532505{
533506 PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
534- #if defined(TRACE_RAW_MALLOC ) && defined(WITH_THREAD )
535- PyGILState_STATE gil_state ;
536- #endif
537507 void * ptr2 ;
538508
539- if (get_reentrant ()) {
540- /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
541- Example: PyMem_RawRealloc() is called internally by pymalloc
542- (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
543- arena (new_arena()). */
544- ptr2 = alloc -> realloc (alloc -> ctx , ptr , new_size );
545-
546- if (ptr2 != NULL && ptr != NULL )
547- tracemalloc_log_free (ptr );
548-
549- return ptr2 ;
550- }
551-
552- /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
553- allocations larger than 512 bytes. PyGILState_Ensure() may call
554- PyMem_RawMalloc() indirectly which would call PyGILState_Ensure() if
555- reentrant are not disabled. */
556- set_reentrant (1 );
557- #ifdef WITH_THREAD
558- #ifdef TRACE_RAW_MALLOC
559- if (!gil_held )
560- gil_state = PyGILState_Ensure ();
561- #else
562- assert (gil_held );
563- #endif
564- #endif
565509 ptr2 = alloc -> realloc (alloc -> ctx , ptr , new_size );
510+ if (ptr2 == NULL )
511+ return NULL ;
566512
567- if (ptr2 != NULL ) {
568- if (ptr != NULL ) {
569- /* resize */
570- tracemalloc_log_free (ptr );
513+ if (ptr != NULL ) {
514+ /* an existing memory block has been resized */
571515
572- if (tracemalloc_log_alloc (ptr2 , new_size ) < 0 ) {
573- /* Memory allocation failed. The error cannot be reported to
574- the caller, because realloc() may already have shrinked the
575- memory block and so removed bytes.
516+ tracemalloc_remove_trace (ptr );
576517
577- This case is very unlikely since we just released an hash
578- entry, so we have enough free bytes to allocate the new
579- entry. */
580- }
581- }
582- else {
583- /* new allocation */
584- if (tracemalloc_log_alloc (ptr2 , new_size ) < 0 ) {
585- /* Memory allocation failed */
586- alloc -> free (alloc -> ctx , ptr2 );
587- ptr2 = NULL ;
588- }
518+ if (tracemalloc_add_trace (ptr2 , new_size ) < 0 ) {
519+ /* Memory allocation failed. The error cannot be reported to
520+ the caller, because realloc() may already have shrinked the
521+ memory block and so removed bytes.
522+
523+ This case is very unlikely since we just released an hash
524+ entry, so we have enough free bytes to allocate the new
525+ entry. */
589526 }
590527 }
591- set_reentrant (0 );
592-
593- #if defined(TRACE_RAW_MALLOC ) && defined(WITH_THREAD )
594- if (!gil_held )
595- PyGILState_Release (gil_state );
596- #endif
528+ else {
529+ /* new allocation */
597530
531+ if (tracemalloc_add_trace (ptr2 , new_size ) < 0 ) {
532+ /* Failed to allocate a trace for the new memory block */
533+ alloc -> free (alloc -> ctx , ptr2 );
534+ return NULL ;
535+ }
536+ }
598537 return ptr2 ;
599538}
600539
@@ -610,34 +549,126 @@ tracemalloc_free(void *ctx, void *ptr)
610549 a deadlock in PyThreadState_DeleteCurrent(). */
611550
612551 alloc -> free (alloc -> ctx , ptr );
613- tracemalloc_log_free (ptr );
552+ tracemalloc_remove_trace (ptr );
614553}
615554
616555static void *
617556tracemalloc_malloc_gil (void * ctx , size_t size )
618557{
619- return tracemalloc_malloc (ctx , size , 1 );
558+ void * ptr ;
559+
560+ if (get_reentrant ()) {
561+ PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
562+ return alloc -> malloc (alloc -> ctx , size );
563+ }
564+
565+ /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
566+ allocations larger than 512 bytes, don't trace the same memory
567+ allocation twice. */
568+ set_reentrant (1 );
569+
570+ ptr = tracemalloc_malloc (ctx , size );
571+
572+ set_reentrant (0 );
573+ return ptr ;
620574}
621575
622576static void *
623577tracemalloc_realloc_gil (void * ctx , void * ptr , size_t new_size )
624578{
625- return tracemalloc_realloc (ctx , ptr , new_size , 1 );
579+ void * ptr2 ;
580+
581+ if (get_reentrant ()) {
582+ /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
583+ Example: PyMem_RawRealloc() is called internally by pymalloc
584+ (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
585+ arena (new_arena()). */
586+ PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
587+
588+ ptr2 = alloc -> realloc (alloc -> ctx , ptr , new_size );
589+ if (ptr2 != NULL && ptr != NULL )
590+ tracemalloc_remove_trace (ptr );
591+ return ptr2 ;
592+ }
593+
594+ /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
595+ allocations larger than 512 bytes. Don't trace the same memory
596+ allocation twice. */
597+ set_reentrant (1 );
598+
599+ ptr2 = tracemalloc_realloc (ctx , ptr , new_size );
600+
601+ set_reentrant (0 );
602+ return ptr2 ;
626603}
627604
628605#ifdef TRACE_RAW_MALLOC
629606static void *
630607tracemalloc_raw_malloc (void * ctx , size_t size )
631608{
632- return tracemalloc_malloc (ctx , size , 0 );
609+ #ifdef WITH_THREAD
610+ PyGILState_STATE gil_state ;
611+ #endif
612+ void * ptr ;
613+
614+ if (get_reentrant ()) {
615+ PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
616+ return alloc -> malloc (alloc -> ctx , size );
617+ }
618+
619+ /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
620+ indirectly which would call PyGILState_Ensure() if reentrant are not
621+ disabled. */
622+ set_reentrant (1 );
623+
624+ #ifdef WITH_THREAD
625+ gil_state = PyGILState_Ensure ();
626+ ptr = tracemalloc_malloc (ctx , size );
627+ PyGILState_Release (gil_state );
628+ #else
629+ ptr = tracemalloc_malloc (ctx , size );
630+ #endif
631+
632+ set_reentrant (0 );
633+ return ptr ;
633634}
634635
635636static void *
636637tracemalloc_raw_realloc (void * ctx , void * ptr , size_t new_size )
637638{
638- return tracemalloc_realloc ( ctx , ptr , new_size , 0 );
639- }
639+ #ifdef WITH_THREAD
640+ PyGILState_STATE gil_state ;
640641#endif
642+ void * ptr2 ;
643+
644+ if (get_reentrant ()) {
645+ /* Reentrant call to PyMem_RawRealloc(). */
646+ PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
647+
648+ ptr2 = alloc -> realloc (alloc -> ctx , ptr , new_size );
649+ if (ptr2 != NULL && ptr != NULL )
650+ tracemalloc_remove_trace (ptr );
651+
652+ return ptr2 ;
653+ }
654+
655+ /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
656+ indirectly which would call PyGILState_Ensure() if reentrant calls are
657+ not disabled. */
658+ set_reentrant (1 );
659+
660+ #ifdef WITH_THREAD
661+ gil_state = PyGILState_Ensure ();
662+ ptr2 = tracemalloc_realloc (ctx , ptr , new_size );
663+ PyGILState_Release (gil_state );
664+ #else
665+ ptr2 = tracemalloc_realloc (ctx , ptr , new_size );
666+ #endif
667+
668+ set_reentrant (0 );
669+ return ptr2 ;
670+ }
671+ #endif /* TRACE_RAW_MALLOC */
641672
642673static int
643674tracemalloc_clear_filename (_Py_hashtable_entry_t * entry , void * user_data )
0 commit comments