Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
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
67 changes: 46 additions & 21 deletions Python/condvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,44 +48,69 @@
* 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))

#if HAVE_PTHREAD_CONDATTR_SETCLOCK
#define MONOTONIC
#else
#undef MONOTONIC
#endif

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;
}

# ifdef MONOTONIC
# define GETTIME _PyTime_GetMonotonicClock
# else
# define GETTIME _PyTime_GetSystemClock
# endif

# define MAXIMUM_TIMEOUT 100

/* 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;

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

while (1) {
_PyTime_t delta;
deadline = GETTIME() + _PyTime_FromNanoseconds(us * 1000);
if (us < MAXIMUM_TIMEOUT && ((delta=(GETTIME() - deadline)) > 0)) {
us += _PyTime_AsMicroseconds(delta, _PyTime_ROUND_CEILING);
continue;
}
_PyTime_AsTimespec(deadline, &ts);
break;
}

r = pthread_cond_timedwait((cond), (mut), &ts);
if (r == ETIMEDOUT)
Expand Down
35 changes: 19 additions & 16 deletions Python/thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
# define USE_SEMAPHORES
#else
# undef USE_SEMAPHORES
# if HAVE_PTHREAD_CONDATTR_SETCLOCK
# define MONOTONIC
# else
# undef MONOTONIC
# endif
#endif


Expand All @@ -89,24 +94,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 +449,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 +470,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
9 changes: 5 additions & 4 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -10878,12 +10878,13 @@ $as_echo "#define HAVE_BROKEN_PTHREAD_SIGMASK 1" >>confdefs.h
fi
done

for ac_func in pthread_getcpuclockid
for ac_func in pthread_getcpuclockid pthread_condattr_setclock
do :
ac_fn_c_check_func "$LINENO" "pthread_getcpuclockid" "ac_cv_func_pthread_getcpuclockid"
if test "x$ac_cv_func_pthread_getcpuclockid" = xyes; then :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PTHREAD_GETCPUCLOCKID 1
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3157,7 +3157,7 @@ if test "$posix_threads" = "yes"; then
[Define if pthread_sigmask() does not work on your system.])
;;
esac])
AC_CHECK_FUNCS(pthread_getcpuclockid)
AC_CHECK_FUNCS([pthread_getcpuclockid pthread_condattr_setclock])
fi


Expand Down