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