Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Attempt at adapting Victor's patch from https://bugs.python.org/issue…
  • Loading branch information
embray committed Jan 31, 2019
commit 3497cc848ee1cb995f048e9f8b69071d6cfb459a
4 changes: 2 additions & 2 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ regen-opcode-targets:
$(srcdir)/Python/opcode_targets.h.new
$(UPDATE_FILE) $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/opcode_targets.h.new

Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h
Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h $(srcdir)/Python/condvar.h

Python/frozen.o: $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib_external.h \
$(srcdir)/Python/importlib_zipimport.h
Expand Down Expand Up @@ -1838,7 +1838,7 @@ patchcheck: @DEF_MAKE_RULE@

# Dependencies

Python/thread.o: @THREADHEADERS@
Python/thread.o: @THREADHEADERS@ $(srcdir)/Python/condvar.h

# Declare targets that aren't real files
.PHONY: all build_all sharedmods check-clean-src oldsharedmods test quicktest
Expand Down
51 changes: 31 additions & 20 deletions Python/condvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,44 +48,55 @@
* POSIX support
*/

#define PyCOND_ADD_MICROSECONDS(tv, interval) \
do { /* TODO: add overflow and truncation checks */ \
tv.tv_usec += (long) interval; \
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 PyCOND_GETTIMEOFDAY(ptv) gettimeofday(ptv)
#else
#define PyCOND_GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL)
#endif
#include <pthread.h>

/* The following functions return 0 on success, nonzero on error */
#define PyMUTEX_INIT(mut) pthread_mutex_init((mut), NULL)
#define PyMUTEX_FINI(mut) pthread_mutex_destroy(mut)
#define PyMUTEX_LOCK(mut) pthread_mutex_lock(mut)
#define PyMUTEX_UNLOCK(mut) pthread_mutex_unlock(mut)

#define PyCOND_INIT(cond) pthread_cond_init((cond), NULL)
#define PyCOND_T pthread_cond_t
#define PyCOND_FINI(cond) pthread_cond_destroy(cond)
#define PyCOND_SIGNAL(cond) pthread_cond_signal(cond)
#define PyCOND_BROADCAST(cond) pthread_cond_broadcast(cond)
#define PyCOND_WAIT(cond, mut) pthread_cond_wait((cond), (mut))

#define MONOTONIC

Py_LOCAL_INLINE(int)
PyCOND_INIT(PyCOND_T *cond)
{
pthread_condattr_t attr;
int err;

(void)pthread_condattr_init(&attr);
#ifdef MONOTONIC
err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
if (err)
return err;
#endif
err = pthread_cond_init(cond, &attr);
(void)pthread_condattr_destroy(&attr);
return err;
}

/* return 0 for success, 1 on timeout, -1 on error */
Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)
PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, PY_TIMEOUT_T us)
{
int r;
struct timespec ts;
struct timeval deadline;
_PyTime_t deadline;

#ifdef MONOTONIC
deadline = _PyTime_GetMonotonicClock();
#else
deadline = _PyTime_GetSystemClock();
#endif

PyCOND_GETTIMEOFDAY(&deadline);
PyCOND_ADD_MICROSECONDS(deadline, us);
ts.tv_sec = deadline.tv_sec;
ts.tv_nsec = deadline.tv_usec * 1000;
deadline += _PyTime_FromNanoseconds(us * 1000);
_PyTime_AsTimespec(deadline, &ts);

r = pthread_cond_timedwait((cond), (mut), &ts);
if (r == ETIMEDOUT)
Expand Down
31 changes: 15 additions & 16 deletions Python/thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
defined(HAVE_SEM_TIMEDWAIT))
# define USE_SEMAPHORES
#else
# define MONOTONIC
# undef USE_SEMAPHORES
#endif

Expand All @@ -89,24 +90,16 @@
# define SET_THREAD_SIGMASK sigprocmask
#endif


/* We assume all modern POSIX systems have gettimeofday() */
#ifdef GETTIMEOFDAY_NO_TZ
#define GETTIMEOFDAY(ptv) gettimeofday(ptv)
#ifdef MONOTONIC
#define GETTIME _PyTime_GetMonotonicClock
#else
#define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL)
#define GETTIME _PyTime_GetSystemClock
#endif

#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \
#define MICROSECONDS_TO_TIMESPEC(us, 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; \
_PyTime_t t = GETTIME() + _PyTime_FromNanoseconds(us * 1000); \
_PyTime_AsTimespec(t, &ts); \
} while(0)


Expand Down Expand Up @@ -452,6 +445,7 @@ PyThread_allocate_lock(void)
{
pthread_lock *lock;
int status, error = 0;
pthread_condattr_t attr;

dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
Expand All @@ -472,9 +466,14 @@ PyThread_allocate_lock(void)
will cause errors. */
_Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);

status = pthread_cond_init(&lock->lock_released,
pthread_condattr_default);
pthread_condattr_init(&attr);
#ifdef MONOTONIC
status = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
CHECK_STATUS_PTHREAD("pthread_condattr_setclock");
#endif
status = pthread_cond_init(&lock->lock_released, &attr);
CHECK_STATUS_PTHREAD("pthread_cond_init");
pthread_condattr_destroy(&attr);

if (error) {
PyMem_RawFree((void *)lock);
Expand Down