Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 78997) +++ Python/ceval.c (working copy) @@ -237,6 +237,8 @@ #define UNSIGNAL_ASYNC_EXC() \ do { pending_async_exc = 0; COMPUTE_EVAL_BREAKER(); } while (0) +/* Big value helps the OS classify CPU bound threads as such. */ +#define DROP_COUNTDOWN_TICKS 500000 #ifdef WITH_THREAD @@ -252,6 +254,7 @@ static volatile int eval_breaker = 0; /* Request for droppping the GIL */ static volatile int gil_drop_request = 0; +static volatile int gil_drop_countdown = DROP_COUNTDOWN_TICKS; /* Request for running pending calls */ static volatile int pendingcalls_to_do = 0; /* Request for looking at the `async_exc` field of the current thread state */ @@ -1235,16 +1238,20 @@ } if (gil_drop_request) { #ifdef WITH_THREAD - /* Give another thread a chance */ - if (PyThreadState_Swap(NULL) != tstate) - Py_FatalError("ceval: tstate mix-up"); - drop_gil(tstate); - - /* Other threads may run now */ - - take_gil(tstate); - if (PyThreadState_Swap(tstate) != NULL) - Py_FatalError("ceval: orphan tstate"); + /* Better use time based countdown - + ticks just for illustration. */ + if (--gil_drop_countdown <= 0) { + /* Give another thread a chance */ + if (PyThreadState_Swap(NULL) != tstate) + Py_FatalError("ceval: tstate mix-up"); + drop_gil(tstate); + + /* Other threads may run now */ + + take_gil(tstate); + if (PyThreadState_Swap(tstate) != NULL) + Py_FatalError("ceval: orphan tstate"); + } #endif } /* Check for asynchronous exceptions. */ Index: Python/ceval_gil.h =================================================================== --- Python/ceval_gil.h (revision 78997) +++ Python/ceval_gil.h (working copy) @@ -296,20 +296,18 @@ if (!gil_locked) goto _ready; - + + /* Set running thread to switch N ticks into the future. */ + if (!gil_drop_request) { + gil_drop_countdown = DROP_COUNTDOWN_TICKS; + SET_GIL_DROP_REQUEST(); + } + COND_RESET(gil_cond); while (gil_locked) { - int timed_out = 0; - unsigned long saved_switchnum; - - saved_switchnum = gil_switch_number; - COND_TIMED_WAIT(gil_cond, gil_mutex, INTERVAL, timed_out); - /* If we timed out and no switch occurred in the meantime, it is time - to ask the GIL-holding thread to drop it. */ - if (timed_out && gil_locked && gil_switch_number == saved_switchnum) { - SET_GIL_DROP_REQUEST(); - } + COND_WAIT(gil_cond, gil_mutex); } + _ready: #ifdef FORCE_SWITCHING /* This mutex must be taken before modifying gil_last_holder (see drop_gil()). */