@@ -439,7 +439,7 @@ int pthread_attr_destroy(pthread_attr_t *a)
439
439
#endif
440
440
441
441
static void
442
- hardware_stack_limits (uintptr_t * top , uintptr_t * base )
442
+ hardware_stack_limits (uintptr_t * base , uintptr_t * top )
443
443
{
444
444
#ifdef WIN32
445
445
ULONG_PTR low , high ;
@@ -482,23 +482,86 @@ hardware_stack_limits(uintptr_t *top, uintptr_t *base)
482
482
#endif
483
483
}
484
484
485
- void
486
- _Py_InitializeRecursionLimits (PyThreadState * tstate )
485
+ static void
486
+ tstate_set_stack (PyThreadState * tstate ,
487
+ uintptr_t base , uintptr_t top )
487
488
{
488
- uintptr_t top ;
489
- uintptr_t base ;
490
- hardware_stack_limits ( & top , & base );
489
+ assert ( base < top ) ;
490
+ assert (( top - base ) >= ( _PyOS_STACK_MARGIN_BYTES * 3 )) ;
491
+
491
492
#ifdef _Py_THREAD_SANITIZER
492
493
// Thread sanitizer crashes if we use more than half the stack.
493
494
uintptr_t stacksize = top - base ;
494
- base += stacksize / 2 ;
495
+ base += stacksize / 2 ;
495
496
#endif
496
497
_PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )tstate ;
497
498
_tstate -> c_stack_top = top ;
498
499
_tstate -> c_stack_hard_limit = base + _PyOS_STACK_MARGIN_BYTES ;
499
500
_tstate -> c_stack_soft_limit = base + _PyOS_STACK_MARGIN_BYTES * 2 ;
501
+
502
+ #ifndef NDEBUG
503
+ // Sanity checks
504
+ _PyThreadStateImpl * ts = (_PyThreadStateImpl * )tstate ;
505
+ assert (ts -> c_stack_hard_limit <= ts -> c_stack_soft_limit );
506
+ assert (ts -> c_stack_soft_limit < ts -> c_stack_top );
507
+ #endif
508
+ }
509
+
510
+
511
+ void
512
+ _Py_InitializeRecursionLimits (PyThreadState * tstate )
513
+ {
514
+ uintptr_t base , top ;
515
+ hardware_stack_limits (& base , & top );
516
+ assert (top != 0 );
517
+
518
+ tstate_set_stack (tstate , base , top );
519
+ _PyThreadStateImpl * ts = (_PyThreadStateImpl * )tstate ;
520
+ ts -> c_stack_init_base = base ;
521
+ ts -> c_stack_init_top = top ;
522
+
523
+ // Test the stack pointer
524
+ #if !defined(NDEBUG ) && !defined(__wasi__ )
525
+ uintptr_t here_addr = _Py_get_machine_stack_pointer ();
526
+ assert (ts -> c_stack_soft_limit < here_addr );
527
+ assert (here_addr < ts -> c_stack_top );
528
+ #endif
529
+ }
530
+
531
+
532
+ int
533
+ PyUnstable_ThreadState_SetStack (PyThreadState * tstate ,
534
+ void * stack_start_addr , size_t stack_size )
535
+ {
536
+ if (stack_size < (_PyOS_STACK_MARGIN_BYTES * 3 )) {
537
+ PyErr_Format (PyExc_ValueError ,
538
+ "stack_size must be at least %zu bytes" ,
539
+ _PyOS_STACK_MARGIN_BYTES * 3 );
540
+ return -1 ;
541
+ }
542
+
543
+ uintptr_t base = (uintptr_t )stack_start_addr ;
544
+ uintptr_t top = base + stack_size ;
545
+ tstate_set_stack (tstate , base , top );
546
+ return 0 ;
500
547
}
501
548
549
+
550
+ void
551
+ PyUnstable_ThreadState_ResetStack (PyThreadState * tstate )
552
+ {
553
+ _PyThreadStateImpl * ts = (_PyThreadStateImpl * )tstate ;
554
+ if (ts -> c_stack_init_top != 0 ) {
555
+ tstate_set_stack (tstate ,
556
+ ts -> c_stack_init_base ,
557
+ ts -> c_stack_init_top );
558
+ return ;
559
+ }
560
+
561
+ _Py_InitializeRecursionLimits (tstate );
562
+ }
563
+
564
+
502
565
/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
503
566
if the recursion_depth reaches recursion_limit. */
504
567
int
0 commit comments