@@ -565,6 +565,124 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
565
565
#endif
566
566
567
567
568
+ //---------------
569
+ // global objects
570
+ //---------------
571
+
572
+ /* The global objects thread state is meant to be used in a very limited
573
+ way and should not be used to actually run any Python code. */
574
+
575
+ static PyThreadState *
576
+ bind_global_objects_state (_PyRuntimeState * runtime )
577
+ {
578
+ PyThreadState * main_tstate = & runtime -> cached_objects .main_tstate ;
579
+
580
+ bind_tstate (main_tstate );
581
+ /* Unlike _PyThreadState_Bind(), we do not modify gilstate TSS. */
582
+
583
+ return main_tstate ;
584
+ }
585
+
586
+ static void
587
+ unbind_global_objects_state (_PyRuntimeState * runtime )
588
+ {
589
+ PyThreadState * main_tstate = & runtime -> cached_objects .main_tstate ;
590
+ assert (tstate_is_alive (main_tstate ));
591
+ assert (!main_tstate -> _status .active );
592
+ assert (gilstate_tss_get (runtime ) != main_tstate );
593
+
594
+ unbind_tstate (main_tstate );
595
+
596
+ /* This thread state may be bound/unbound repeatedly,
597
+ so we must erase evidence that it was ever bound (or unbound). */
598
+ main_tstate -> _status .bound = 0 ;
599
+ main_tstate -> _status .unbound = 0 ;
600
+
601
+ /* We must fully unlink the thread state from any OS thread,
602
+ to allow it to be bound more than once. */
603
+ main_tstate -> thread_id = 0 ;
604
+ #ifdef PY_HAVE_THREAD_NATIVE_ID
605
+ main_tstate -> native_thread_id = 0 ;
606
+ #endif
607
+ }
608
+
609
+ static inline void
610
+ acquire_global_objects_lock (_PyRuntimeState * runtime )
611
+ {
612
+ /* For now we can rely on the GIL, so we don't actually
613
+ acquire a global lock here. */
614
+ assert (current_fast_get (runtime ) != NULL );
615
+ }
616
+
617
+ static inline void
618
+ release_global_objects_lock (_PyRuntimeState * runtime )
619
+ {
620
+ /* For now we can rely on the GIL, so we don't actually
621
+ release a global lock here. */
622
+ assert (current_fast_get (runtime ) != NULL );
623
+ }
624
+
625
+ PyObject *
626
+ _Py_AddToGlobalDict (PyObject * dict , PyObject * key , PyObject * value )
627
+ {
628
+ assert (dict != NULL );
629
+ assert (PyDict_CheckExact (dict ));
630
+
631
+ /* All global objects are stored in _PyRuntime
632
+ and owned by the main interpreter. */
633
+ _PyRuntimeState * runtime = & _PyRuntime ;
634
+ PyThreadState * curts = current_fast_get (runtime );
635
+ PyInterpreterState * interp = curts -> interp ;
636
+ assert (interp != NULL ); // The GIL must be held.
637
+
638
+ /* Due to interpreter isolation we must hold a global lock,
639
+ starting at this point and ending before we return.
640
+ Note that the operations in this function are very fucused
641
+ and we should not expect any reentrancy. */
642
+ acquire_global_objects_lock (runtime );
643
+
644
+ /* Swap to the main interpreter, if necessary. */
645
+ PyThreadState * oldts = NULL ;
646
+ if (!_Py_IsMainInterpreter (interp )) {
647
+ PyThreadState * main_tstate = bind_global_objects_state (runtime );
648
+
649
+ oldts = _PyThreadState_Swap (runtime , main_tstate );
650
+ assert (oldts != NULL );
651
+ assert (!_Py_IsMainInterpreter (oldts -> interp ));
652
+
653
+ /* The limitations of the global objects thread state apply
654
+ from this point to the point we swap back to oldts. */
655
+ }
656
+
657
+ /* This might trigger a resize, which is why we must "acquire"
658
+ the global object state. Also note that PyDict_SetDefault()
659
+ must be compatible with our reentrancy and global objects state
660
+ constraints. */
661
+ PyObject * actual = PyDict_SetDefault (dict , key , value );
662
+ if (actual == NULL ) {
663
+ /* Raising an exception from one interpreter in another
664
+ is problematic, so we clear it and let the caller deal
665
+ with the returned NULL. */
666
+ assert (PyErr_ExceptionMatches (PyExc_MemoryError ));
667
+ PyErr_Clear ();
668
+ }
669
+
670
+ /* Swap back, it it wasn't in the main interpreter already. */
671
+ if (oldts != NULL ) {
672
+ // The returned tstate should be _PyRuntime.cached_objects.main_tstate.
673
+ _PyThreadState_Swap (runtime , oldts );
674
+
675
+ unbind_global_objects_state (runtime );
676
+ }
677
+
678
+ release_global_objects_lock (runtime );
679
+
680
+ // XXX Immortalize the key and value.
681
+
682
+ return actual ;
683
+ }
684
+
685
+
568
686
/*************************************/
569
687
/* the per-interpreter runtime state */
570
688
/*************************************/
@@ -1217,8 +1335,7 @@ free_threadstate(PyThreadState *tstate)
1217
1335
1218
1336
static void
1219
1337
init_threadstate (PyThreadState * tstate ,
1220
- PyInterpreterState * interp , uint64_t id ,
1221
- PyThreadState * next )
1338
+ PyInterpreterState * interp , uint64_t id )
1222
1339
{
1223
1340
if (tstate -> _status .initialized ) {
1224
1341
Py_FatalError ("thread state already initialized" );
@@ -1227,18 +1344,13 @@ init_threadstate(PyThreadState *tstate,
1227
1344
assert (interp != NULL );
1228
1345
tstate -> interp = interp ;
1229
1346
1347
+ // next/prev are set in add_threadstate().
1348
+ assert (tstate -> next == NULL );
1349
+ assert (tstate -> prev == NULL );
1350
+
1230
1351
assert (id > 0 );
1231
1352
tstate -> id = id ;
1232
1353
1233
- assert (interp -> threads .head == tstate );
1234
- assert ((next != NULL && id != 1 ) || (next == NULL && id == 1 ));
1235
- if (next != NULL ) {
1236
- assert (next -> prev == NULL || next -> prev == tstate );
1237
- next -> prev = tstate ;
1238
- }
1239
- tstate -> next = next ;
1240
- assert (tstate -> prev == NULL );
1241
-
1242
1354
// thread_id and native_thread_id are set in bind_tstate().
1243
1355
1244
1356
tstate -> py_recursion_limit = interp -> ceval .recursion_limit ,
@@ -1259,6 +1371,22 @@ init_threadstate(PyThreadState *tstate,
1259
1371
tstate -> _status .initialized = 1 ;
1260
1372
}
1261
1373
1374
+ static void
1375
+ add_threadstate (PyInterpreterState * interp , PyThreadState * tstate ,
1376
+ PyThreadState * next )
1377
+ {
1378
+ assert (interp -> threads .head != tstate );
1379
+ assert ((next != NULL && tstate -> id != 1 ) ||
1380
+ (next == NULL && tstate -> id == 1 ));
1381
+ if (next != NULL ) {
1382
+ assert (next -> prev == NULL || next -> prev == tstate );
1383
+ next -> prev = tstate ;
1384
+ }
1385
+ tstate -> next = next ;
1386
+ assert (tstate -> prev == NULL );
1387
+ interp -> threads .head = tstate ;
1388
+ }
1389
+
1262
1390
static PyThreadState *
1263
1391
new_threadstate (PyInterpreterState * interp )
1264
1392
{
@@ -1298,9 +1426,9 @@ new_threadstate(PyInterpreterState *interp)
1298
1426
& initial ._main_interpreter ._initial_thread ,
1299
1427
sizeof (* tstate ));
1300
1428
}
1301
- interp -> threads .head = tstate ;
1302
1429
1303
- init_threadstate (tstate , interp , id , old_head );
1430
+ init_threadstate (tstate , interp , id );
1431
+ add_threadstate (interp , tstate , old_head );
1304
1432
1305
1433
HEAD_UNLOCK (runtime );
1306
1434
if (!used_newtstate ) {
@@ -1347,6 +1475,33 @@ _PyThreadState_Init(PyThreadState *tstate)
1347
1475
Py_FatalError ("_PyThreadState_Init() is for internal use only" );
1348
1476
}
1349
1477
1478
+ void
1479
+ _PyThreadState_InitDetached (PyThreadState * tstate , PyInterpreterState * interp )
1480
+ {
1481
+ _PyRuntimeState * runtime = interp -> runtime ;
1482
+
1483
+ HEAD_LOCK (runtime );
1484
+ interp -> threads .next_unique_id += 1 ;
1485
+ uint64_t id = interp -> threads .next_unique_id ;
1486
+ HEAD_UNLOCK (runtime );
1487
+
1488
+ init_threadstate (tstate , interp , id );
1489
+ // We do not call add_threadstate().
1490
+ }
1491
+
1492
+
1493
+ static void
1494
+ clear_datastack (PyThreadState * tstate )
1495
+ {
1496
+ _PyStackChunk * chunk = tstate -> datastack_chunk ;
1497
+ tstate -> datastack_chunk = NULL ;
1498
+ while (chunk != NULL ) {
1499
+ _PyStackChunk * prev = chunk -> previous ;
1500
+ _PyObject_VirtualFree (chunk , chunk -> size );
1501
+ chunk = prev ;
1502
+ }
1503
+ }
1504
+
1350
1505
void
1351
1506
PyThreadState_Clear (PyThreadState * tstate )
1352
1507
{
@@ -1421,7 +1576,6 @@ PyThreadState_Clear(PyThreadState *tstate)
1421
1576
// XXX Do it as early in the function as possible.
1422
1577
}
1423
1578
1424
-
1425
1579
/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
1426
1580
static void
1427
1581
tstate_delete_common (PyThreadState * tstate )
@@ -1454,17 +1608,25 @@ tstate_delete_common(PyThreadState *tstate)
1454
1608
unbind_tstate (tstate );
1455
1609
1456
1610
// XXX Move to PyThreadState_Clear()?
1457
- _PyStackChunk * chunk = tstate -> datastack_chunk ;
1458
- tstate -> datastack_chunk = NULL ;
1459
- while (chunk != NULL ) {
1460
- _PyStackChunk * prev = chunk -> previous ;
1461
- _PyObject_VirtualFree (chunk , chunk -> size );
1462
- chunk = prev ;
1463
- }
1611
+ clear_datastack (tstate );
1464
1612
1465
1613
tstate -> _status .finalized = 1 ;
1466
1614
}
1467
1615
1616
+ void
1617
+ _PyThreadState_ClearDetached (PyThreadState * tstate )
1618
+ {
1619
+ assert (!tstate -> _status .bound );
1620
+ assert (!tstate -> _status .bound_gilstate );
1621
+ assert (tstate -> datastack_chunk == NULL );
1622
+ assert (tstate -> thread_id == 0 );
1623
+ assert (tstate -> native_thread_id == 0 );
1624
+ assert (tstate -> next == NULL );
1625
+ assert (tstate -> prev == NULL );
1626
+
1627
+ PyThreadState_Clear (tstate );
1628
+ clear_datastack (tstate );
1629
+ }
1468
1630
1469
1631
static void
1470
1632
zapthreads (PyInterpreterState * interp )
0 commit comments