@@ -81,8 +81,28 @@ static void *coroutine_wrapper(void *action_, void *arg_)
8181
8282 /* New coroutine gets a brand new Python interpreter stack frame. */
8383#if PY_VERSION_HEX >= 0x30B0000
84- PyThreadState * new_threadstate = PyThreadState_New (thread_state -> interp );
85- thread_state = PyThreadState_Swap (new_threadstate );
84+ // TODO: This section should just set up a clean stack frame
85+
86+ // PyObject *context = thread_state->context;
87+ // _PyCFrame *cframe = thread_state->cframe;
88+ // struct _PyInterpreterFrame *current_frame = thread_state->cframe->current_frame;
89+
90+ // thread_state->cframe = thread_state->cframe;
91+
92+ // int recursion_depth = thread_state->recursion_limit - thread_state->recursion_remaining;
93+
94+ // // May not be needed?
95+
96+ // _PyStackChunk *datastack_chunk = thread_state->datastack_chunk;
97+ // PyObject **datastack_top = thread_state->datastack_top;
98+ // PyObject **datastack_limit = thread_state->datastack_limit;
99+
100+ // PyFrameObject *frame = PyThreadState_GetFrame(thread_state);
101+ // Py_XDECREF(frame); // PyThreadState_GetFrame gives us a new reference.
102+
103+ // int trash_delete_nesting = thread_state->trash_delete_nesting;
104+
105+ thread_state -> recursion_remaining = thread_state -> recursion_limit ;
86106#else
87107 thread_state -> frame = NULL ;
88108 thread_state -> recursion_depth = 0 ;
@@ -108,9 +128,20 @@ static void *coroutine_wrapper(void *action_, void *arg_)
108128
109129
110130#if PY_VERSION_HEX >= 0x30B0000
111- new_threadstate = PyThreadState_Swap (thread_state );
112- PyThreadState_Clear (new_threadstate );
113- PyThreadState_Delete (new_threadstate );
131+ // thread_state->context = context;
132+ // /* Incrementing this value invalidates the contextvars cache,
133+ // which would otherwise remain valid across switches */
134+ // thread_state->context_ver++;
135+
136+ // thread_state->cframe = cframe;
137+
138+ // thread_state->recursion_remaining = thread_state->recursion_limit - recursion_depth;
139+
140+ // thread_state->cframe->current_frame = interp_frame;
141+
142+ // thread_state->datastack_chunk = datastack_chunk;
143+ // thread_state->datastack_top = datastack_top;
144+ // thread_state->datastack_limit = datastack_limit;
114145#else
115146 /* Some of the stuff we've initialised can leak through, so far I've only
116147 * seen exc_type still set at this point, but maybe other fields can also
@@ -162,7 +193,30 @@ static PyObject *coroutine_switch(PyObject *Self, PyObject *args)
162193 {
163194 PyThreadState * thread_state = PyThreadState_GET ();
164195
165- #if PY_VERSION_HEX < 0x30B0000
196+ #if PY_VERSION_HEX >= 0x30B0000
197+ PyObject * context = thread_state -> context ;
198+ _PyCFrame * cframe = thread_state -> cframe ;
199+ struct _PyInterpreterFrame * current_frame = thread_state -> cframe -> current_frame ;
200+
201+ // thread_state->cframe = NULL;
202+
203+ int recursion_depth = thread_state -> recursion_limit - thread_state -> recursion_remaining ;
204+
205+ // May not be needed?
206+
207+ _PyStackChunk * datastack_chunk = thread_state -> datastack_chunk ;
208+ PyObject * * datastack_top = thread_state -> datastack_top ;
209+ PyObject * * datastack_limit = thread_state -> datastack_limit ;
210+
211+ PyFrameObject * frame = PyThreadState_GetFrame (thread_state );
212+ // assert(frame);
213+ Py_XDECREF (frame ); // PyThreadState_GetFrame gives us a new reference.
214+
215+ int trash_delete_nesting = thread_state -> trash_delete_nesting ;
216+
217+ _PyErr_StackItem exc_state = thread_state -> exc_state ;
218+ _PyErr_StackItem * exc_info = thread_state -> exc_info ;
219+ #else
166220 /* Need to switch the Python interpreter's record of recursion depth and
167221 * top frame around as we switch frames, otherwise the interpreter gets
168222 * confused and thinks we've recursed too deep. In truth tracking this
@@ -191,7 +245,25 @@ static PyObject *coroutine_switch(PyObject *Self, PyObject *args)
191245 PyObject * result = switch_cocore (target , arg );
192246
193247#if PY_VERSION_HEX >= 0x30B0000
194- PyThreadState_Swap (thread_state );
248+ thread_state -> context = context ;
249+ /* Incrementing this value invalidates the contextvars cache,
250+ which would otherwise remain valid across switches */
251+ thread_state -> context_ver ++ ;
252+
253+ thread_state -> cframe = cframe ;
254+
255+ thread_state -> recursion_remaining = thread_state -> recursion_limit - recursion_depth ;
256+
257+ thread_state -> cframe -> current_frame = current_frame ;
258+
259+ thread_state -> datastack_chunk = datastack_chunk ;
260+ thread_state -> datastack_top = datastack_top ;
261+ thread_state -> datastack_limit = datastack_limit ;
262+
263+ thread_state -> trash_delete_nesting = trash_delete_nesting ;
264+
265+ thread_state -> exc_state = exc_state ;
266+ thread_state -> exc_info = exc_info ;
195267#else
196268 /* Restore previously saved state. I wonder if PyThreadState_GET()
197269 * really needs to be called again here... */
0 commit comments