@@ -530,9 +530,16 @@ merge_gc_stats_array(GCStats *dest, const GCStats *src)
530530 }
531531}
532532
533+ void
534+ stats_zero_thread (_PyThreadStateImpl * tstate )
535+ {
536+ // Zero the thread local stat counters
537+ memset (tstate -> pystats_struct , 0 , sizeof (PyStats ));
538+ }
539+
533540// merge stats for a single thread into the global structure
534541void
535- stats_merge_thread (_PyThreadStateImpl * tstate , bool zero )
542+ stats_merge_thread (_PyThreadStateImpl * tstate )
536543{
537544 PyStats * src = tstate -> pystats_struct ;
538545 PyStats * dest = ((PyThreadState * )tstate )-> interp -> pystats_struct ;
@@ -549,11 +556,6 @@ stats_merge_thread(_PyThreadStateImpl *tstate, bool zero)
549556 merge_ft_stats (& dest -> ft_stats , & src -> ft_stats );
550557 merge_rare_event_stats (& dest -> rare_event_stats , & src -> rare_event_stats );
551558 merge_gc_stats_array (dest -> gc_stats , src -> gc_stats );
552-
553- if (zero ) {
554- // Zero the source stat counters
555- memset (src , 0 , sizeof (PyStats ));
556- }
557559}
558560#endif // Py_GIL_DISABLED
559561
@@ -602,10 +604,9 @@ stats_toggle_on_off(PyThreadState *tstate, int on)
602604 return 0 ;
603605}
604606
605- // merge stats for all threads into the per-interpreter structure
606- // if 'zero' is true then the per-interpreter stats are zeroed after merging
607+ // zero stats for all threads and for the interpreter
607608static void
608- stats_merge_all ( bool zero )
609+ stats_zero_all ( void )
609610{
610611 PyThreadState * tstate = _PyThreadState_GET ();
611612 if (tstate == NULL ) {
@@ -618,12 +619,32 @@ stats_merge_all(bool zero)
618619 _PyEval_StopTheWorld (interp );
619620#ifdef Py_GIL_DISABLED
620621 _Py_FOR_EACH_TSTATE_UNLOCKED (interp , ts ) {
621- stats_merge_thread ((_PyThreadStateImpl * )ts , true );
622+ stats_zero_thread ((_PyThreadStateImpl * )ts );
622623 }
623624#endif
624- if (zero ) {
625- memset (interp -> pystats_struct , 0 , sizeof (PyStats ));
625+ memset (interp -> pystats_struct , 0 , sizeof (PyStats ));
626+ _PyEval_StartTheWorld (interp );
627+ }
628+
629+ // merge stats for all threads into the per-interpreter structure
630+ static void
631+ stats_merge_all (void )
632+ {
633+ PyThreadState * tstate = _PyThreadState_GET ();
634+ if (tstate == NULL ) {
635+ return ;
636+ }
637+ if (FT_ATOMIC_LOAD_PTR_RELAXED (tstate -> interp -> pystats_struct ) == NULL ) {
638+ return ;
626639 }
640+ PyInterpreterState * interp = tstate -> interp ;
641+ _PyEval_StopTheWorld (interp );
642+ #ifdef Py_GIL_DISABLED
643+ _Py_FOR_EACH_TSTATE_UNLOCKED (interp , ts ) {
644+ stats_merge_thread ((_PyThreadStateImpl * )ts );
645+ stats_zero_thread ((_PyThreadStateImpl * )ts );
646+ }
647+ #endif
627648 _PyEval_StartTheWorld (interp );
628649}
629650
@@ -644,7 +665,7 @@ _Py_StatsOff(void)
644665void
645666_Py_StatsClear (void )
646667{
647- stats_merge_all (true );
668+ stats_zero_all ( );
648669}
649670
650671static int
663684_Py_PrintSpecializationStats (int to_file )
664685{
665686 assert (to_file );
666- stats_merge_all (false );
687+ stats_merge_all ();
667688 PyThreadState * tstate = _PyThreadState_GET ();
668689 STATS_LOCK (tstate -> interp );
669690 PyStats * stats = tstate -> interp -> pystats_struct ;
@@ -761,7 +782,7 @@ _PyStats_ThreadFini(_PyThreadStateImpl *tstate)
761782{
762783#ifdef Py_GIL_DISABLED
763784 STATS_LOCK (((PyThreadState * )tstate )-> interp );
764- stats_merge_thread (tstate , false );
785+ stats_merge_thread (tstate );
765786 STATS_UNLOCK (((PyThreadState * )tstate )-> interp );
766787 PyMem_RawFree (tstate -> pystats_struct );
767788#endif
0 commit comments