--- ceval.c.org Sat Dec 10 19:50:16 2005 +++ ceval.c Mon Jan 23 09:53:55 2006 @@ -209,6 +209,8 @@ static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */ static long main_thread = 0; +static PyThread_type_lock async_lock = 0; /* For asynchronous operations*/ + int PyEval_ThreadsInitialized(void) { @@ -223,6 +225,7 @@ interpreter_lock = PyThread_allocate_lock(); PyThread_acquire_lock(interpreter_lock, 1); main_thread = PyThread_get_thread_ident(); + async_lock = PyThread_allocate_lock(); } void @@ -257,6 +260,7 @@ Py_FatalError("PyEval_ReleaseThread: NULL thread state"); if (PyThreadState_Swap(NULL) != tstate) Py_FatalError("PyEval_ReleaseThread: wrong thread state"); + PyThread_release_lock(async_lock); PyThread_release_lock(interpreter_lock); } @@ -354,22 +358,37 @@ static volatile int pendinglast = 0; static volatile int things_to_do = 0; +#ifdef WITH_THREAD + +#define AsyncLock() PyThread_acquire_lock(async_lock, 1) +#define AsyncUnlock() PyThread_release_lock(async_lock) + +#else +/* + * No semaphores/mutexes available, use the following makeshift solution. + * Never really atomic but it's a start... + */ +static volatile int busy = 0; + +static int AsyncLock() { if (busy) return 0; busy = 1; return 1; } +static void AsyncUnlock() { busy = 0; } + +#endif + int Py_AddPendingCall(int (*func)(void *), void *arg) { - static volatile int busy = 0; int i, j; /* XXX Begin critical section */ /* XXX If you want this to be safe against nested XXX asynchronous calls, you'll have to work harder! */ - if (busy) + if (!AsyncLock()) return -1; - busy = 1; i = pendinglast; j = (i + 1) % NPENDINGCALLS; if (j == pendingfirst) { - busy = 0; - return -1; /* Queue full */ + AsyncUnlock(); + return -1; /* Queue full */ } pendingcalls[i].func = func; pendingcalls[i].arg = arg; @@ -376,8 +395,8 @@ pendinglast = j; _Py_Ticker = 0; - things_to_do = 1; /* Signal main loop */ - busy = 0; + things_to_do = 1; /* Signal main loop */ + AsyncUnlock(); /* XXX End critical section */ return 0; } @@ -385,14 +404,12 @@ int Py_MakePendingCalls(void) { - static int busy = 0; #ifdef WITH_THREAD if (main_thread && PyThread_get_thread_ident() != main_thread) return 0; #endif - if (busy) + if (!AsyncLock()) return 0; - busy = 1; things_to_do = 0; for (;;) { int i; @@ -400,21 +417,20 @@ void *arg; i = pendingfirst; if (i == pendinglast) - break; /* Queue empty */ + break; /* Queue empty */ func = pendingcalls[i].func; arg = pendingcalls[i].arg; pendingfirst = (i + 1) % NPENDINGCALLS; if (func(arg) < 0) { - busy = 0; - things_to_do = 1; /* We're not done yet */ + AsyncUnlock(); + things_to_do = 1; /* We're not done yet */ return -1; } } - busy = 0; + AsyncUnlock(); return 0; } - /* The interpreter's recursion limit */ #ifndef Py_DEFAULT_RECURSION_LIMIT