@@ -200,6 +200,9 @@ Copyright (C) 1994 Steen Lumholt.
200200*/
201201
202202static PyThread_type_lock tcl_lock = 0 ;
203+ /* Only the thread holding the lock can modify these */
204+ static unsigned long tcl_lock_thread_ident = 0 ;
205+ static unsigned int tcl_lock_reentry_count = 0 ;
203206
204207#ifdef TCL_THREADS
205208static Tcl_ThreadDataKey state_key ;
@@ -209,20 +212,43 @@ typedef PyThreadState *ThreadSpecificData;
209212static PyThreadState * tcl_tstate = NULL ;
210213#endif
211214
215+ #define ACQUIRE_TCL_LOCK \
216+ if (tcl_lock) {\
217+ if (tcl_lock_thread_ident == PyThread_get_thread_ident()) {\
218+ tcl_lock_reentry_count++; \
219+ if(!tcl_lock_reentry_count) \
220+ Py_FatalError("Tcl lock reentry count overflow"); \
221+ } else { \
222+ PyThread_acquire_lock(tcl_lock, 1); \
223+ tcl_lock_thread_ident = PyThread_get_thread_ident(); \
224+ }\
225+ }
226+
227+ #define RELEASE_TCL_LOCK \
228+ if (tcl_lock){\
229+ if (tcl_lock_reentry_count) { \
230+ tcl_lock_reentry_count--; \
231+ } else { \
232+ tcl_lock_thread_ident = 0; \
233+ PyThread_release_lock(tcl_lock); \
234+ }\
235+ }
236+
212237#define ENTER_TCL \
213238 { PyThreadState *tstate = PyThreadState_Get();\
214239 ENTER_TCL_CUSTOM_TSTATE(tstate)
215240
216241#define ENTER_TCL_CUSTOM_TSTATE (tstate ) \
217242 Py_BEGIN_ALLOW_THREADS\
218- if (tcl_lock)PyThread_acquire_lock(tcl_lock, 1) ; tcl_tstate = tstate;
243+ ACQUIRE_TCL_LOCK ; tcl_tstate = tstate;
219244
220245#define LEAVE_TCL \
221- tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
246+ tcl_tstate = NULL; \
247+ RELEASE_TCL_LOCK; Py_END_ALLOW_THREADS}
222248
223249#define LEAVE_TCL_WITH_BUSYWAIT (result ) \
224250 tcl_tstate = NULL; \
225- if (tcl_lock)PyThread_release_lock(tcl_lock) ;\
251+ RELEASE_TCL_LOCK ;\
226252 if (result == 0)\
227253 Sleep(Tkinter_busywaitinterval);\
228254 Py_END_ALLOW_THREADS
@@ -235,15 +261,16 @@ static PyThreadState *tcl_tstate = NULL;
235261 Py_BEGIN_ALLOW_THREADS
236262
237263#define LEAVE_OVERLAP_TCL \
238- tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock) ; }
264+ tcl_tstate = NULL; RELEASE_TCL_LOCK ; }
239265
240266#define ENTER_PYTHON \
241267 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
242- if(tcl_lock)PyThread_release_lock(tcl_lock) ; PyEval_RestoreThread((tstate)); }
268+ RELEASE_TCL_LOCK ; PyEval_RestoreThread((tstate)); }
243269
244270#define LEAVE_PYTHON \
245271 { PyThreadState *tstate = PyEval_SaveThread(); \
246- if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
272+ ACQUIRE_TCL_LOCK;\
273+ tcl_tstate = tstate; }
247274
248275#define ENTER_PYTHON_OVERLAP \
249276{ PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; PyEval_RestoreThread((tstate)); }
0 commit comments