[Python-checkins] r75644 - in sandbox/trunk/newgil: Makefile.pre.in Python/ceval.c Python/ceval_gil.h Python/ceval_pthread.h
antoine.pitrou
python-checkins at python.org
Sat Oct 24 00:57:42 CEST 2009
Author: antoine.pitrou
Date: Sat Oct 24 00:57:41 2009
New Revision: 75644
Log:
Rename file, since it is no longer posix-specific.
Added:
sandbox/trunk/newgil/Python/ceval_gil.h
- copied, changed from r75643, /sandbox/trunk/newgil/Python/ceval_pthread.h
Removed:
sandbox/trunk/newgil/Python/ceval_pthread.h
Modified:
sandbox/trunk/newgil/Makefile.pre.in
sandbox/trunk/newgil/Python/ceval.c
Modified: sandbox/trunk/newgil/Makefile.pre.in
==============================================================================
--- sandbox/trunk/newgil/Makefile.pre.in (original)
+++ sandbox/trunk/newgil/Makefile.pre.in Sat Oct 24 00:57:41 2009
@@ -596,7 +596,7 @@
$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
$(OPCODETARGETGEN) $(OPCODETARGETS_H)
-Python/ceval.o: $(OPCODETARGETS_H) Python/ceval_pthread.h
+Python/ceval.o: $(OPCODETARGETS_H) Python/ceval_gil.h
Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \
$(BYTESTR_DEPS) \
Modified: sandbox/trunk/newgil/Python/ceval.c
==============================================================================
--- sandbox/trunk/newgil/Python/ceval.c (original)
+++ sandbox/trunk/newgil/Python/ceval.c Sat Oct 24 00:57:41 2009
@@ -239,7 +239,7 @@
/* Request for looking at the `async_exc` field of the current thread state */
static volatile int pending_async_exc = 0;
-#include "ceval_pthread.h"
+#include "ceval_gil.h"
int
PyEval_ThreadsInitialized(void)
Copied: sandbox/trunk/newgil/Python/ceval_gil.h (from r75643, /sandbox/trunk/newgil/Python/ceval_pthread.h)
==============================================================================
--- /sandbox/trunk/newgil/Python/ceval_pthread.h (original)
+++ sandbox/trunk/newgil/Python/ceval_gil.h Sat Oct 24 00:57:41 2009
@@ -1,5 +1,5 @@
/*
- * Implementation of the Global Interpreter Lock (GIL) for POSIX pthreads.
+ * Implementation of the Global Interpreter Lock (GIL).
*/
#include <stdlib.h>
Deleted: sandbox/trunk/newgil/Python/ceval_pthread.h
==============================================================================
--- sandbox/trunk/newgil/Python/ceval_pthread.h Sat Oct 24 00:57:41 2009
+++ (empty file)
@@ -1,358 +0,0 @@
-/*
- * Implementation of the Global Interpreter Lock (GIL) for POSIX pthreads.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-
-
-/* First some general settings */
-
-/* milliseconds */
-#define INTERVAL 5
-
-/* Enable if you want to force the switching of threads at least every INTERVAL */
-#undef FORCE_SWITCHING
-#define FORCE_SWITCHING
-
-#undef TRACE_PRIO
-/* #define TRACE_PRIO */
-
-
-#ifndef _POSIX_THREADS
-/* This means pthreads are not implemented in libc headers, hence the macro
- not present in unistd.h. But they still can be implemented as an external
- library (e.g. gnu pth in pthread emulation) */
-# ifdef HAVE_PTHREAD_H
-# include <pthread.h> /* _POSIX_THREADS */
-# endif
-#endif
-
-
-#ifdef _POSIX_THREADS
-
-/*
- * POSIX support
- */
-
-#include <pthread.h>
-
-#define ADD_MILLISECONDS(tv, interval) \
-do { \
- tv.tv_usec += interval * 1000; \
- tv.tv_sec += tv.tv_usec / 1000000; \
- tv.tv_usec %= 1000000; \
-} while (0)
-
-/* We assume all modern POSIX systems have gettimeofday() */
-#ifdef GETTIMEOFDAY_NO_TZ
-#define GETTIMEOFDAY(ptv) gettimeofday(ptv)
-#else
-#define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL)
-#endif
-
-#define MUTEX_T pthread_mutex_t
-#define MUTEX_INIT(mut) \
- if (pthread_mutex_init(&mut, NULL)) { \
- Py_FatalError("pthread_mutex_init(" #mut ") failed"); };
-#define MUTEX_LOCK(mut) \
- if (pthread_mutex_lock(&mut)) { \
- Py_FatalError("pthread_mutex_lock(" #mut ") failed"); };
-#define MUTEX_UNLOCK(mut) \
- if (pthread_mutex_unlock(&mut)) { \
- Py_FatalError("pthread_mutex_unlock(" #mut ") failed"); };
-
-#define COND_T pthread_cond_t
-#define COND_INIT(cond) \
- if (pthread_cond_init(&cond, NULL)) { \
- Py_FatalError("pthread_cond_init(" #cond ") failed"); };
-#define COND_PREPARE(cond)
-#define COND_SIGNAL(cond) \
- if (pthread_cond_signal(&cond)) { \
- Py_FatalError("pthread_cond_signal(" #cond ") failed"); };
-#define COND_WAIT(cond, mut) \
- if (pthread_cond_wait(&cond, &mut)) { \
- Py_FatalError("pthread_cond_wait(" #cond ") failed"); };
-#define COND_TIMED_WAIT(cond, mut, milliseconds, timeout_result) \
- { \
- int r; \
- struct timespec ts; \
- struct timeval deadline; \
- \
- GETTIMEOFDAY(&deadline); \
- ADD_MILLISECONDS(deadline, INTERVAL); \
- ts.tv_sec = deadline.tv_sec; \
- ts.tv_nsec = deadline.tv_usec * 1000; \
- \
- r = pthread_cond_timedwait(&cond, &mut, &ts); \
- if (r == ETIMEDOUT) \
- timeout_result = 1; \
- else if (r) \
- Py_FatalError("pthread_cond_timedwait(" #cond ") failed"); \
- else \
- timeout_result = 0; \
- } \
-
-#elif defined(NT_THREADS)
-
-/*
- * Windows (2000 and later, as well as (hopefully) CE) support
- */
-
-#include <windows.h>
-
-#define MUTEX_T HANDLE
-#define MUTEX_INIT(mut) \
- if (!(mut = CreateMutex(NULL, FALSE, NULL))) { \
- Py_FatalError("CreateMutex(" #mut ") failed"); };
-#define MUTEX_LOCK(mut) \
- if (WaitForSingleObject(mut, INFINITE) != WAIT_OBJECT_0) { \
- Py_FatalError("WaitForSingleObject(" #mut ") failed"); };
-#define MUTEX_UNLOCK(mut) \
- if (!ReleaseMutex(mut)) { \
- Py_FatalError("ReleaseMutex(" #mut ") failed"); };
-
-/* We emulate condition variables with events. It is sufficient here.
- (WaitForMultipleObjects() allows the event to be reset and the mutex
- to be taken atomically) */
-#define COND_T HANDLE
-#define COND_INIT(cond) \
- /* auto-reset, non-signalled */ \
- if (!(cond = CreateEvent(NULL, FALSE, FALSE, NULL))) { \
- Py_FatalError("CreateMutex(" #cond ") failed"); };
-#define COND_PREPARE(cond) \
- if (!ResetEvent(cond)) { \
- Py_FatalError("ResetEvent(" #cond ") failed"); };
-#define COND_SIGNAL(cond) \
- if (!SetEvent(cond)) { \
- Py_FatalError("SetEvent(" #cond ") failed"); };
-#define COND_WAIT(cond, mut) \
- { \
- DWORD r; \
- HANDLE objects[2] = { cond, mut }; \
- MUTEX_UNLOCK(mut); \
- r = WaitForMultipleObjects(2, objects, TRUE, INFINITE); \
- if (r != WAIT_OBJECT_0) \
- Py_FatalError("WaitForSingleObject(" #cond ") failed"); \
- }
-#define COND_TIMED_WAIT(cond, mut, milliseconds, timeout_result) \
- { \
- DWORD r; \
- HANDLE objects[2] = { cond, mut }; \
- MUTEX_UNLOCK(mut); \
- r = WaitForMultipleObjects(2, objects, TRUE, milliseconds); \
- if (r == WAIT_TIMEOUT) { \
- MUTEX_LOCK(mut); \
- timeout_result = 1; \
- } \
- else if (r != WAIT_OBJECT_0) \
- Py_FatalError("WaitForSingleObject(" #cond ") failed"); \
- else \
- timeout_result = 0; \
- }
-
-#else
-
-#error You need either a POSIX-compatible or a Windows system!
-
-#endif /* _POSIX_THREADS, NT_THREADS */
-
-
-/* Whether the GIL is already taken (-1 if uninitialized) */
-static volatile int gil_locked = -1;
-/* Number of GIL switches since the beginning */
-static unsigned long gil_switch_number = 0;
-/* Last thread holding / having held the GIL */
-static PyThreadState *gil_last_holder = NULL;
-
-/* This condition variable allows to put threads to sleep.
- In addition, the mutex also protects the above variables. */
-static COND_T gil_cond;
-static MUTEX_T gil_mutex;
-/* This mutex is taken when a priority request is made, and released when
- it is finally honoured.
- Other threads can sleep by trying to lock the mutex. */
-static MUTEX_T prio_mutex;
-/* The thread making the prio request, or NULL. */
-static volatile PyThreadState *prio_request = NULL;
-
-#ifdef FORCE_SWITCHING
-/* This condition variable forces the GIL-releasing thread to wait for
- the scheduling of a GIL-awaiting thread, if any. */
-static COND_T switch_cond;
-static MUTEX_T switch_mutex;
-#endif
-
-
-#define YIELD_IF_PRIO_REQUEST() \
-do { \
- if (prio_request) { \
- MUTEX_LOCK(prio_mutex); \
- MUTEX_UNLOCK(prio_mutex); \
- } \
-} while (0)
-
-
-
-static int gil_created(void)
-{
- return gil_locked >= 0;
-}
-
-static void create_gil(void)
-{
- MUTEX_INIT(gil_mutex);
- MUTEX_INIT(prio_mutex);
-#ifdef FORCE_SWITCHING
- MUTEX_INIT(switch_mutex);
-#endif
- COND_INIT(gil_cond);
-#ifdef FORCE_SWITCHING
- COND_INIT(switch_cond);
-#endif
- gil_locked = 0;
- gil_last_holder = NULL;
- prio_request = NULL;
-}
-
-static void recreate_gil(void)
-{
- create_gil();
-}
-
-static void drop_gil(PyThreadState *tstate)
-{
- /* NOTE: tstate is allowed to be NULL. */
- if (!gil_locked)
- Py_FatalError("drop_gil: GIL is not locked");
- if (tstate != NULL && tstate != gil_last_holder)
- Py_FatalError("drop_gil: wrong thread state");
-
- MUTEX_LOCK(gil_mutex);
- gil_locked = 0;
- COND_SIGNAL(gil_cond);
-#ifdef FORCE_SWITCHING
- COND_PREPARE(switch_cond);
-#endif
- MUTEX_UNLOCK(gil_mutex);
-
-#ifdef FORCE_SWITCHING
- if (gil_drop_request) {
- MUTEX_LOCK(switch_mutex);
- /* Not switched yet => wait */
- if (gil_last_holder == tstate)
- COND_WAIT(switch_cond, switch_mutex);
- MUTEX_UNLOCK(switch_mutex);
- }
-#endif
-}
-
-static void _take_gil(PyThreadState *tstate, int prio)
-{
- int err;
- if (tstate == NULL)
- Py_FatalError("take_gil: NULL tstate");
-
- /* If another thread is requesting priority, give it a chance to run
- before we take the mutex.
- */
- YIELD_IF_PRIO_REQUEST();
-
- err = errno;
- MUTEX_LOCK(gil_mutex);
-
- if (!gil_locked) {
- prio = 0;
- goto _ready;
- }
-
- COND_PREPARE(gil_cond);
-
- if (prio) {
-#ifdef TRACE_PRIO
- struct timeval tv;
- GETTIMEOFDAY(&tv);
- printf("trying to take gil with prio: %.3f <--\n",
- tv.tv_sec + tv.tv_usec / 1000000.0);
-#endif
- if (!prio_request) {
- MUTEX_LOCK(prio_mutex);
- prio_request = tstate;
- }
- else
- prio = 0;
- }
- while (gil_locked) {
- int timed_out = 0;
- unsigned long saved_switchnum;
-
- if (prio_request) {
- /* Tell the eval loop the GIL must be dropped as soon as possible */
- SET_GIL_DROP_REQUEST();
- if (!prio) {
- /* If another thread is making the prio_request, give it a
- chance to run and take the mutex. */
- MUTEX_UNLOCK(gil_mutex);
- YIELD_IF_PRIO_REQUEST();
- MUTEX_LOCK(gil_mutex);
- }
- }
-
- 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();
- }
- }
-_ready:
-#ifdef FORCE_SWITCHING
- /* This mutex must be taken before modifying gil_last_holder (see drop_gil()). */
- MUTEX_LOCK(switch_mutex);
-#endif
- /* We now hold the GIL */
- gil_locked = 1;
-
- if (tstate != gil_last_holder) {
- gil_last_holder = tstate;
- ++gil_switch_number;
-#ifdef TRACE_PRIO
- if (prio) {
- struct timeval tv;
- GETTIMEOFDAY(&tv);
- printf("gil taken with prio: %.3f\n",
- tv.tv_sec + tv.tv_usec / 1000000.0);
- }
-#endif
- }
-#ifdef FORCE_SWITCHING
- COND_SIGNAL(switch_cond);
- MUTEX_UNLOCK(switch_mutex);
-#endif
- if (prio) {
- /* The prio request was granted. */
- prio_request = NULL;
- MUTEX_UNLOCK(prio_mutex);
- }
- if (gil_drop_request && !prio_request) {
- /* No prio_request pending. */
- RESET_GIL_DROP_REQUEST();
- }
- if (tstate->async_exc != NULL) {
- _PyEval_SignalAsyncExc();
- }
-
- MUTEX_UNLOCK(gil_mutex);
- errno = err;
-}
-
-static void take_gil(PyThreadState *tstate)
-{
- _take_gil(tstate, 0);
-}
-
-static void take_gil_prio(PyThreadState *tstate)
-{
- _take_gil(tstate, 1);
-}
More information about the Python-checkins
mailing list