@@ -66,25 +66,25 @@ get_legacy_reftotal(void)
66
66
67
67
#ifdef Py_REF_DEBUG
68
68
69
- # define REFTOTAL (runtime ) \
70
- (runtime) ->object_state.reftotal
69
+ # define REFTOTAL (interp ) \
70
+ interp ->object_state.reftotal
71
71
72
72
static inline void
73
- reftotal_increment (_PyRuntimeState * runtime )
73
+ reftotal_increment (PyInterpreterState * interp )
74
74
{
75
- REFTOTAL (runtime )++ ;
75
+ REFTOTAL (interp )++ ;
76
76
}
77
77
78
78
static inline void
79
- reftotal_decrement (_PyRuntimeState * runtime )
79
+ reftotal_decrement (PyInterpreterState * interp )
80
80
{
81
- REFTOTAL (runtime )-- ;
81
+ REFTOTAL (interp )-- ;
82
82
}
83
83
84
84
static inline void
85
- reftotal_add (_PyRuntimeState * runtime , Py_ssize_t n )
85
+ reftotal_add (PyInterpreterState * interp , Py_ssize_t n )
86
86
{
87
- REFTOTAL (runtime ) += n ;
87
+ REFTOTAL (interp ) += n ;
88
88
}
89
89
90
90
static inline Py_ssize_t get_global_reftotal (_PyRuntimeState * );
99
99
_Py_FinalizeRefTotal (_PyRuntimeState * runtime )
100
100
{
101
101
last_final_reftotal = get_global_reftotal (runtime );
102
- REFTOTAL (runtime ) = 0 ;
102
+ runtime -> object_state .interpreter_leaks = 0 ;
103
+ }
104
+
105
+ void
106
+ _PyInterpreterState_FinalizeRefTotal (PyInterpreterState * interp )
107
+ {
108
+ interp -> runtime -> object_state .interpreter_leaks += REFTOTAL (interp );
109
+ REFTOTAL (interp ) = 0 ;
110
+ }
111
+
112
+ static inline Py_ssize_t
113
+ get_reftotal (PyInterpreterState * interp )
114
+ {
115
+ /* For a single interpreter, we ignore the legacy _Py_RefTotal,
116
+ since we can't determine which interpreter updated it. */
117
+ return REFTOTAL (interp );
103
118
}
104
119
105
120
static inline Py_ssize_t
106
121
get_global_reftotal (_PyRuntimeState * runtime )
107
122
{
108
- /* For an update from _Py_RefTotal first. */
109
- Py_ssize_t legacy = get_legacy_reftotal ();
110
- return REFTOTAL (runtime ) + legacy + last_final_reftotal ;
123
+ Py_ssize_t total = 0 ;
124
+
125
+ /* Add up the total from each interpreter. */
126
+ HEAD_LOCK (& _PyRuntime );
127
+ PyInterpreterState * interp = PyInterpreterState_Head ();
128
+ for (; interp != NULL ; interp = PyInterpreterState_Next (interp )) {
129
+ total += REFTOTAL (interp );
130
+ }
131
+ HEAD_UNLOCK (& _PyRuntime );
132
+
133
+ /* Add in the updated value from the legacy _Py_RefTotal. */
134
+ total += get_legacy_reftotal ();
135
+ total += last_final_reftotal ;
136
+ total += runtime -> object_state .interpreter_leaks ;
137
+
138
+ return total ;
111
139
}
112
140
113
141
#undef REFTOTAL
@@ -118,7 +146,8 @@ _PyDebug_PrintTotalRefs(void) {
118
146
fprintf (stderr ,
119
147
"[%zd refs, %zd blocks]\n" ,
120
148
get_global_reftotal (runtime ), _Py_GetAllocatedBlocks ());
121
- /* It may be helpful to also print the "legacy" reftotal separately. */
149
+ /* It may be helpful to also print the "legacy" reftotal separately.
150
+ Likewise for the total for each interpreter. */
122
151
}
123
152
#endif /* Py_REF_DEBUG */
124
153
@@ -177,32 +206,32 @@ _Py_NegativeRefcount(const char *filename, int lineno, PyObject *op)
177
206
void
178
207
_Py_IncRefTotal_DO_NOT_USE_THIS (void )
179
208
{
180
- reftotal_increment (& _PyRuntime );
209
+ reftotal_increment (_PyInterpreterState_GET () );
181
210
}
182
211
183
212
/* This is used strictly by Py_DECREF(). */
184
213
void
185
214
_Py_DecRefTotal_DO_NOT_USE_THIS (void )
186
215
{
187
- reftotal_decrement (& _PyRuntime );
216
+ reftotal_decrement (_PyInterpreterState_GET () );
188
217
}
189
218
190
219
void
191
- _Py_IncRefTotal (void )
220
+ _Py_IncRefTotal (PyInterpreterState * interp )
192
221
{
193
- reftotal_increment (& _PyRuntime );
222
+ reftotal_increment (interp );
194
223
}
195
224
196
225
void
197
- _Py_DecRefTotal (void )
226
+ _Py_DecRefTotal (PyInterpreterState * interp )
198
227
{
199
- reftotal_decrement (& _PyRuntime );
228
+ reftotal_decrement (interp );
200
229
}
201
230
202
231
void
203
- _Py_AddRefTotal (Py_ssize_t n )
232
+ _Py_AddRefTotal (PyInterpreterState * interp , Py_ssize_t n )
204
233
{
205
- reftotal_add (& _PyRuntime , n );
234
+ reftotal_add (interp , n );
206
235
}
207
236
208
237
/* This includes the legacy total
@@ -219,6 +248,12 @@ _Py_GetLegacyRefTotal(void)
219
248
return get_legacy_reftotal ();
220
249
}
221
250
251
+ Py_ssize_t
252
+ _PyInterpreterState_GetRefTotal (PyInterpreterState * interp )
253
+ {
254
+ return get_reftotal (interp );
255
+ }
256
+
222
257
#endif /* Py_REF_DEBUG */
223
258
224
259
void
@@ -2128,7 +2163,7 @@ void
2128
2163
_Py_NewReference (PyObject * op )
2129
2164
{
2130
2165
#ifdef Py_REF_DEBUG
2131
- reftotal_increment (& _PyRuntime );
2166
+ reftotal_increment (_PyInterpreterState_GET () );
2132
2167
#endif
2133
2168
new_reference (op );
2134
2169
}
0 commit comments