summaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/thread_nt.h33
-rw-r--r--Python/thread_pthread.h101
2 files changed, 107 insertions, 27 deletions
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 0c5d1929c3..e2e4443d86 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -34,13 +34,13 @@ DeleteNonRecursiveMutex(PNRMUTEX mutex)
}
DWORD
-EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait)
+EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
{
/* Assume that the thread waits successfully */
DWORD ret ;
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
- if (!wait)
+ if (milliseconds == 0)
{
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
return WAIT_TIMEOUT ;
@@ -49,7 +49,7 @@ EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait)
else
ret = InterlockedIncrement(&mutex->owned) ?
/* Some thread owns the mutex, let's wait... */
- WaitForSingleObject(mutex->hevent, INFINITE) : WAIT_OBJECT_0 ;
+ WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ;
mutex->thread_id = GetCurrentThreadId() ; /* We own it */
return ret ;
@@ -239,18 +239,37 @@ PyThread_free_lock(PyThread_type_lock aLock)
* if the lock has already been acquired by this thread!
*/
int
-PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
+PyThread_acquire_lock_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds)
{
int success ;
+ PY_TIMEOUT_T milliseconds;
+
+ if (microseconds >= 0) {
+ milliseconds = microseconds / 1000;
+ if (microseconds % 1000 > 0)
+ ++milliseconds;
+ if ((DWORD) milliseconds != milliseconds)
+ Py_FatalError("Timeout too large for a DWORD, "
+ "please check PY_TIMEOUT_MAX");
+ }
+ else
+ milliseconds = INFINITE;
- dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag));
+ dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n",
+ PyThread_get_thread_ident(), aLock, microseconds));
- success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ;
+ success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ;
- dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
+ dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n",
+ PyThread_get_thread_ident(), aLock, microseconds, success));
return success;
}
+int
+PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
+{
+ return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0);
+}
void
PyThread_release_lock(PyThread_type_lock aLock)
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 4305a198ba..6088c71fdb 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -83,6 +83,26 @@
#endif
+/* 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 MICROSECONDS_TO_TIMESPEC(microseconds, ts) \
+do { \
+ struct timeval tv; \
+ GETTIMEOFDAY(&tv); \
+ tv.tv_usec += microseconds % 1000000; \
+ tv.tv_sec += microseconds / 1000000; \
+ tv.tv_sec += tv.tv_usec / 1000000; \
+ tv.tv_usec %= 1000000; \
+ ts.tv_sec = tv.tv_sec; \
+ ts.tv_nsec = tv.tv_usec * 1000; \
+} while(0)
+
+
/* A pthread mutex isn't sufficient to model the Python lock type
* because, according to Draft 5 of the docs (P1003.4a/D5), both of the
* following are undefined:
@@ -295,34 +315,53 @@ fix_status(int status)
return (status == -1) ? errno : status;
}
-int
-PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+int
+PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
{
int success;
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
+ struct timespec ts;
- dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
+ dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n",
+ lock, microseconds));
+ if (microseconds > 0)
+ MICROSECONDS_TO_TIMESPEC(microseconds, ts);
do {
- if (waitflag)
- status = fix_status(sem_wait(thelock));
- else
+ if (microseconds > 0)
+ status = fix_status(sem_timedwait(thelock, &ts));
+ else if (microseconds == 0)
status = fix_status(sem_trywait(thelock));
+ else
+ status = fix_status(sem_wait(thelock));
} while (status == EINTR); /* Retry if interrupted by a signal */
- if (waitflag) {
+ if (microseconds > 0) {
+ if (status != ETIMEDOUT)
+ CHECK_STATUS("sem_timedwait");
+ }
+ else if (microseconds == 0) {
+ if (status != EAGAIN)
+ CHECK_STATUS("sem_trywait");
+ }
+ else {
CHECK_STATUS("sem_wait");
- } else if (status != EAGAIN) {
- CHECK_STATUS("sem_trywait");
}
success = (status == 0) ? 1 : 0;
- dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
+ dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n",
+ lock, microseconds, success));
return success;
}
+int
+PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+{
+ return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0);
+}
+
void
PyThread_release_lock(PyThread_type_lock lock)
{
@@ -390,40 +429,62 @@ PyThread_free_lock(PyThread_type_lock lock)
free((void *)thelock);
}
-int
-PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+int
+PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
{
int success;
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
- dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
+ dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n",
+ lock, microseconds));
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS("pthread_mutex_lock[1]");
success = thelock->locked == 0;
- if ( !success && waitflag ) {
+ if (!success && microseconds != 0) {
+ struct timespec ts;
+ if (microseconds > 0)
+ MICROSECONDS_TO_TIMESPEC(microseconds, ts);
/* continue trying until we get the lock */
/* mut must be locked by me -- part of the condition
* protocol */
- while ( thelock->locked ) {
- status = pthread_cond_wait(&thelock->lock_released,
- &thelock->mut);
- CHECK_STATUS("pthread_cond_wait");
+ while (thelock->locked) {
+ if (microseconds > 0) {
+ status = pthread_cond_timedwait(
+ &thelock->lock_released,
+ &thelock->mut, &ts);
+ if (status == ETIMEDOUT)
+ break;
+ CHECK_STATUS("pthread_cond_timed_wait");
+ }
+ else {
+ status = pthread_cond_wait(
+ &thelock->lock_released,
+ &thelock->mut);
+ CHECK_STATUS("pthread_cond_wait");
+ }
}
- success = 1;
+ success = (status == 0);
}
if (success) thelock->locked = 1;
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS("pthread_mutex_unlock[1]");
if (error) success = 0;
- dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
+ dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n",
+ lock, microseconds, success));
return success;
}
+int
+PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
+{
+ return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0);
+}
+
void
PyThread_release_lock(PyThread_type_lock lock)
{