@@ -957,7 +957,7 @@ _PyMem_Strdup(const char *str)
957
957
958
958
// A pointer to be freed once the QSBR read sequence reaches qsbr_goal.
959
959
struct _mem_work_item {
960
- void * ptr ;
960
+ void * ptr ; // lowest bit tagged 1 for objects freed with PyObject_Free
961
961
uint64_t qsbr_goal ;
962
962
};
963
963
@@ -971,16 +971,26 @@ struct _mem_work_chunk {
971
971
struct _mem_work_item array [WORK_ITEMS_PER_CHUNK ];
972
972
};
973
973
974
- void
975
- _PyMem_FreeDelayed (void * ptr )
974
+ void free_work_item (void * ptr )
975
+ {
976
+ if (((uintptr_t )ptr ) & 0x01 ) {
977
+ PyObject_Free (((char * )ptr ) - 1 );
978
+ }
979
+ else {
980
+ PyMem_Free (ptr );
981
+ }
982
+ }
983
+
984
+ static void
985
+ free_delayed (void * ptr )
976
986
{
977
987
#ifndef Py_GIL_DISABLED
978
- PyMem_Free (ptr );
988
+ free_work_item (ptr );
979
989
#else
980
990
if (_PyRuntime .stoptheworld .world_stopped ) {
981
991
// Free immediately if the world is stopped, including during
982
992
// interpreter shutdown.
983
- PyMem_Free (ptr );
993
+ free_work_item (ptr );
984
994
return ;
985
995
}
986
996
@@ -1007,7 +1017,7 @@ _PyMem_FreeDelayed(void *ptr)
1007
1017
if (buf == NULL ) {
1008
1018
// failed to allocate a buffer, free immediately
1009
1019
_PyEval_StopTheWorld (tstate -> base .interp );
1010
- PyMem_Free (ptr );
1020
+ free_work_item (ptr );
1011
1021
_PyEval_StartTheWorld (tstate -> base .interp );
1012
1022
return ;
1013
1023
}
@@ -1024,6 +1034,20 @@ _PyMem_FreeDelayed(void *ptr)
1024
1034
#endif
1025
1035
}
1026
1036
1037
+ void
1038
+ _PyMem_FreeDelayed (void * ptr )
1039
+ {
1040
+ assert (!((uintptr_t )ptr & 0x01 ));
1041
+ free_delayed (ptr );
1042
+ }
1043
+
1044
+
1045
+ void _PyObject_FreeDelayed (void * ptr )
1046
+ {
1047
+ assert (!((uintptr_t )ptr & 0x01 ));
1048
+ free_delayed ((void * )(((uintptr_t )ptr )|0x01 ));
1049
+ }
1050
+
1027
1051
static struct _mem_work_chunk *
1028
1052
work_queue_first (struct llist_node * head )
1029
1053
{
@@ -1043,7 +1067,7 @@ process_queue(struct llist_node *head, struct _qsbr_thread_state *qsbr,
1043
1067
return ;
1044
1068
}
1045
1069
1046
- PyMem_Free (item -> ptr );
1070
+ free_work_item (item -> ptr );
1047
1071
buf -> rd_idx ++ ;
1048
1072
}
1049
1073
@@ -1119,6 +1143,23 @@ _PyMem_AbandonDelayed(PyThreadState *tstate)
1119
1143
assert (llist_empty (queue )); // the thread's queue is now empty
1120
1144
}
1121
1145
1146
+ void
1147
+ _PyMem_ProcessAllDelayed (PyInterpreterState * interp )
1148
+ {
1149
+ PyThreadState * tstate = PyInterpreterState_ThreadHead (interp );
1150
+ while (tstate != NULL ) {
1151
+ _PyThreadStateImpl * tstate_impl = (_PyThreadStateImpl * )tstate ;
1152
+
1153
+ // Process thread-local work
1154
+ process_queue (& tstate_impl -> mem_free_queue , tstate_impl -> qsbr , true);
1155
+
1156
+ tstate = PyThreadState_Next (tstate );
1157
+ }
1158
+
1159
+ // Process shared interpreter work
1160
+ process_interp_queue (& interp -> mem_free_queue , ((_PyThreadStateImpl * )_PyThreadState_GET ())-> qsbr );
1161
+ }
1162
+
1122
1163
void
1123
1164
_PyMem_FiniDelayed (PyInterpreterState * interp )
1124
1165
{
@@ -1130,7 +1171,7 @@ _PyMem_FiniDelayed(PyInterpreterState *interp)
1130
1171
// Free the remaining items immediately. There should be no other
1131
1172
// threads accessing the memory at this point during shutdown.
1132
1173
struct _mem_work_item * item = & buf -> array [buf -> rd_idx ];
1133
- PyMem_Free (item -> ptr );
1174
+ free_work_item (item -> ptr );
1134
1175
buf -> rd_idx ++ ;
1135
1176
}
1136
1177
0 commit comments