10
10
#include "pycore_interpreteridobject.h"
11
11
12
12
13
+ /*
14
+ This module has the following process-global state:
15
+
16
+ _globals (static struct globals):
17
+ module_count (int)
18
+ channels (struct _channels):
19
+ numopen (int64_t)
20
+ next_id; (int64_t)
21
+ mutex (PyThread_type_lock)
22
+ head (linked list of struct _channelref *):
23
+ id (int64_t)
24
+ objcount (Py_ssize_t)
25
+ next (struct _channelref *):
26
+ ...
27
+ chan (struct _channel *):
28
+ open (int)
29
+ mutex (PyThread_type_lock)
30
+ closing (struct _channel_closing *):
31
+ ref (struct _channelref *):
32
+ ...
33
+ ends (struct _channelends *):
34
+ numsendopen (int64_t)
35
+ numrecvopen (int64_t)
36
+ send (struct _channelend *):
37
+ interp (int64_t)
38
+ open (int)
39
+ next (struct _channelend *)
40
+ recv (struct _channelend *):
41
+ ...
42
+ queue (struct _channelqueue *):
43
+ count (int64_t)
44
+ first (struct _channelitem *):
45
+ next (struct _channelitem *):
46
+ ...
47
+ data (_PyCrossInterpreterData *):
48
+ data (void *)
49
+ obj (PyObject *)
50
+ interp (int64_t)
51
+ new_object (xid_newobjectfunc)
52
+ free (xid_freefunc)
53
+ last (struct _channelitem *):
54
+ ...
55
+
56
+ The above state includes the following allocations by the module:
57
+
58
+ * 1 top-level mutex (to protect the rest of the state)
59
+ * for each channel:
60
+ * 1 struct _channelref
61
+ * 1 struct _channel
62
+ * 0-1 struct _channel_closing
63
+ * 1 struct _channelends
64
+ * 2 struct _channelend
65
+ * 1 struct _channelqueue
66
+ * for each item in each channel:
67
+ * 1 struct _channelitem
68
+ * 1 _PyCrossInterpreterData
69
+
70
+ The only objects in that global state are the references held by each
71
+ channel's queue, which are safely managed via the _PyCrossInterpreterData_*()
72
+ API.. The module does not create any objects that are shared globally.
73
+ */
74
+
13
75
#define MODULE_NAME "_xxinterpchannels"
14
76
15
77
78
+ #define GLOBAL_MALLOC (TYPE ) \
79
+ PyMem_RawMalloc(sizeof(TYPE))
80
+ #define GLOBAL_FREE (VAR ) \
81
+ PyMem_RawFree(VAR)
82
+
83
+
16
84
static PyInterpreterState *
17
85
_get_current_interp (void )
18
86
{
@@ -301,7 +369,7 @@ typedef struct _channelitem {
301
369
static _channelitem *
302
370
_channelitem_new (void )
303
371
{
304
- _channelitem * item = PyMem_NEW (_channelitem , 1 );
372
+ _channelitem * item = GLOBAL_MALLOC (_channelitem );
305
373
if (item == NULL ) {
306
374
PyErr_NoMemory ();
307
375
return NULL ;
@@ -316,7 +384,8 @@ _channelitem_clear(_channelitem *item)
316
384
{
317
385
if (item -> data != NULL ) {
318
386
(void )_release_xid_data (item -> data , 1 );
319
- PyMem_Free (item -> data );
387
+ // It was allocated in _channel_send().
388
+ GLOBAL_FREE (item -> data );
320
389
item -> data = NULL ;
321
390
}
322
391
item -> next = NULL ;
@@ -326,7 +395,7 @@ static void
326
395
_channelitem_free (_channelitem * item )
327
396
{
328
397
_channelitem_clear (item );
329
- PyMem_Free (item );
398
+ GLOBAL_FREE (item );
330
399
}
331
400
332
401
static void
@@ -357,7 +426,7 @@ typedef struct _channelqueue {
357
426
static _channelqueue *
358
427
_channelqueue_new (void )
359
428
{
360
- _channelqueue * queue = PyMem_NEW (_channelqueue , 1 );
429
+ _channelqueue * queue = GLOBAL_MALLOC (_channelqueue );
361
430
if (queue == NULL ) {
362
431
PyErr_NoMemory ();
363
432
return NULL ;
@@ -381,7 +450,7 @@ static void
381
450
_channelqueue_free (_channelqueue * queue )
382
451
{
383
452
_channelqueue_clear (queue );
384
- PyMem_Free (queue );
453
+ GLOBAL_FREE (queue );
385
454
}
386
455
387
456
static int
@@ -433,7 +502,7 @@ typedef struct _channelend {
433
502
static _channelend *
434
503
_channelend_new (int64_t interp )
435
504
{
436
- _channelend * end = PyMem_NEW (_channelend , 1 );
505
+ _channelend * end = GLOBAL_MALLOC (_channelend );
437
506
if (end == NULL ) {
438
507
PyErr_NoMemory ();
439
508
return NULL ;
@@ -447,7 +516,7 @@ _channelend_new(int64_t interp)
447
516
static void
448
517
_channelend_free (_channelend * end )
449
518
{
450
- PyMem_Free (end );
519
+ GLOBAL_FREE (end );
451
520
}
452
521
453
522
static void
@@ -492,7 +561,7 @@ typedef struct _channelassociations {
492
561
static _channelends *
493
562
_channelends_new (void )
494
563
{
495
- _channelends * ends = PyMem_NEW (_channelends , 1 );
564
+ _channelends * ends = GLOBAL_MALLOC (_channelends );
496
565
if (ends == NULL ) {
497
566
return NULL ;
498
567
}
@@ -519,7 +588,7 @@ static void
519
588
_channelends_free (_channelends * ends )
520
589
{
521
590
_channelends_clear (ends );
522
- PyMem_Free (ends );
591
+ GLOBAL_FREE (ends );
523
592
}
524
593
525
594
static _channelend *
@@ -660,20 +729,20 @@ typedef struct _channel {
660
729
static _PyChannelState *
661
730
_channel_new (PyThread_type_lock mutex )
662
731
{
663
- _PyChannelState * chan = PyMem_NEW (_PyChannelState , 1 );
732
+ _PyChannelState * chan = GLOBAL_MALLOC (_PyChannelState );
664
733
if (chan == NULL ) {
665
734
return NULL ;
666
735
}
667
736
chan -> mutex = mutex ;
668
737
chan -> queue = _channelqueue_new ();
669
738
if (chan -> queue == NULL ) {
670
- PyMem_Free (chan );
739
+ GLOBAL_FREE (chan );
671
740
return NULL ;
672
741
}
673
742
chan -> ends = _channelends_new ();
674
743
if (chan -> ends == NULL ) {
675
744
_channelqueue_free (chan -> queue );
676
- PyMem_Free (chan );
745
+ GLOBAL_FREE (chan );
677
746
return NULL ;
678
747
}
679
748
chan -> open = 1 ;
@@ -691,7 +760,7 @@ _channel_free(_PyChannelState *chan)
691
760
PyThread_release_lock (chan -> mutex );
692
761
693
762
PyThread_free_lock (chan -> mutex );
694
- PyMem_Free (chan );
763
+ GLOBAL_FREE (chan );
695
764
}
696
765
697
766
static int
@@ -814,7 +883,7 @@ typedef struct _channelref {
814
883
static _channelref *
815
884
_channelref_new (int64_t id , _PyChannelState * chan )
816
885
{
817
- _channelref * ref = PyMem_NEW (_channelref , 1 );
886
+ _channelref * ref = GLOBAL_MALLOC (_channelref );
818
887
if (ref == NULL ) {
819
888
return NULL ;
820
889
}
@@ -841,7 +910,7 @@ _channelref_free(_channelref *ref)
841
910
_channel_clear_closing (ref -> chan );
842
911
}
843
912
//_channelref_clear(ref);
844
- PyMem_Free (ref );
913
+ GLOBAL_FREE (ref );
845
914
}
846
915
847
916
static _channelref *
@@ -1163,7 +1232,7 @@ _channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) {
1163
1232
res = ERR_CHANNEL_CLOSED ;
1164
1233
goto done ;
1165
1234
}
1166
- chan -> closing = PyMem_NEW (struct _channel_closing , 1 );
1235
+ chan -> closing = GLOBAL_MALLOC (struct _channel_closing );
1167
1236
if (chan -> closing == NULL ) {
1168
1237
goto done ;
1169
1238
}
@@ -1179,7 +1248,7 @@ static void
1179
1248
_channel_clear_closing (struct _channel * chan ) {
1180
1249
PyThread_acquire_lock (chan -> mutex , WAIT_LOCK );
1181
1250
if (chan -> closing != NULL ) {
1182
- PyMem_Free (chan -> closing );
1251
+ GLOBAL_FREE (chan -> closing );
1183
1252
chan -> closing = NULL ;
1184
1253
}
1185
1254
PyThread_release_lock (chan -> mutex );
@@ -1257,14 +1326,14 @@ _channel_send(_channels *channels, int64_t id, PyObject *obj)
1257
1326
}
1258
1327
1259
1328
// Convert the object to cross-interpreter data.
1260
- _PyCrossInterpreterData * data = PyMem_NEW (_PyCrossInterpreterData , 1 );
1329
+ _PyCrossInterpreterData * data = GLOBAL_MALLOC (_PyCrossInterpreterData );
1261
1330
if (data == NULL ) {
1262
1331
PyThread_release_lock (mutex );
1263
1332
return -1 ;
1264
1333
}
1265
1334
if (_PyObject_GetCrossInterpreterData (obj , data ) != 0 ) {
1266
1335
PyThread_release_lock (mutex );
1267
- PyMem_Free (data );
1336
+ GLOBAL_FREE (data );
1268
1337
return -1 ;
1269
1338
}
1270
1339
@@ -1274,7 +1343,7 @@ _channel_send(_channels *channels, int64_t id, PyObject *obj)
1274
1343
if (res != 0 ) {
1275
1344
// We may chain an exception here:
1276
1345
(void )_release_xid_data (data , 0 );
1277
- PyMem_Free (data );
1346
+ GLOBAL_FREE (data );
1278
1347
return res ;
1279
1348
}
1280
1349
@@ -1323,11 +1392,13 @@ _channel_recv(_channels *channels, int64_t id, PyObject **res)
1323
1392
if (obj == NULL ) {
1324
1393
assert (PyErr_Occurred ());
1325
1394
(void )_release_xid_data (data , 1 );
1326
- PyMem_Free (data );
1395
+ // It was allocated in _channel_send().
1396
+ GLOBAL_FREE (data );
1327
1397
return -1 ;
1328
1398
}
1329
1399
int release_res = _release_xid_data (data , 0 );
1330
- PyMem_Free (data );
1400
+ // It was allocated in _channel_send().
1401
+ GLOBAL_FREE (data );
1331
1402
if (release_res < 0 ) {
1332
1403
// The source interpreter has been destroyed already.
1333
1404
assert (PyErr_Occurred ());
0 commit comments