Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
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
5 changes: 3 additions & 2 deletions 5 Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,8 @@ 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
Comment thread
methane marked this conversation as resolved.
Outdated
Expand Down Expand Up @@ -1838,7 +1839,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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Use monotonic clock for ``pthread_cond_timedwait`` when
``pthread_condattr_setclock`` and ``CLOCK_MONOTONIC`` are available.
1 change: 1 addition & 0 deletions 1 Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ PyEval_InitThreads(void)
{
if (gil_created())
return;
PyThread_init_thread();
create_gil();
take_gil(_PyThreadState_GET());
_PyRuntime.ceval.pending.main_thread = PyThread_get_thread_ident();
Expand Down
40 changes: 12 additions & 28 deletions 40 Python/condvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,17 @@
* 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
/* These private functions are implemented in Python/thread_pthread.h */
int _PyThread_cond_init(PyCOND_T *cond);
void _PyThread_cond_after(long long us, struct timespec *abs);

/* 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_INIT(cond) _PyThread_cond_init(cond)
#define PyCOND_FINI(cond) pthread_cond_destroy(cond)
#define PyCOND_SIGNAL(cond) pthread_cond_signal(cond)
#define PyCOND_BROADCAST(cond) pthread_cond_broadcast(cond)
Expand All @@ -78,22 +68,16 @@ do { /* TODO: add overflow and truncation checks */ \
Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long 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;

r = pthread_cond_timedwait((cond), (mut), &ts);
if (r == ETIMEDOUT)
struct timespec abs;
_PyThread_cond_after(us, &abs);
int ret = pthread_cond_timedwait(cond, mut, &abs);
if (ret == ETIMEDOUT) {
return 1;
else if (r)
}
if (ret) {
return -1;
else
return 0;
}
return 0;
}

#elif defined(NT_THREADS)
Expand Down
81 changes: 62 additions & 19 deletions 81 Python/thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,6 @@
#endif
#endif

#if !defined(pthread_attr_default)
# define pthread_attr_default ((pthread_attr_t *)NULL)
#endif
#if !defined(pthread_mutexattr_default)
# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
#endif
#if !defined(pthread_condattr_default)
# define pthread_condattr_default ((pthread_condattr_t *)NULL)
#endif


/* Whether or not to use semaphores directly rather than emulating them with
* mutexes and condition variables:
Expand Down Expand Up @@ -110,6 +100,56 @@ do { \
} while(0)


/*
* pthread_cond support
*/

#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
// monotonic is supported statically. It doesn't mean it works on runtime.
#define CONDATTR_MONOTONIC
#endif

// NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported.
static pthread_condattr_t *condattr_monotonic = NULL;

static void
init_condattr()
{
#ifdef CONDATTR_MONOTONIC
static pthread_condattr_t ca;
pthread_condattr_init(&ca);
if (pthread_condattr_setclock(&ca, CLOCK_MONOTONIC) == 0) {
condattr_monotonic = &ca; // Use monotonic clock
}
#endif
}

int
_PyThread_cond_init(PyCOND_T *cond)
{
return pthread_cond_init(cond, condattr_monotonic);
}

void
_PyThread_cond_after(long long us, struct timespec *abs)
{
#ifdef CONDATTR_MONOTONIC
if (condattr_monotonic) {
clock_gettime(CLOCK_MONOTONIC, abs);
abs->tv_sec += us / 1000000;
abs->tv_nsec += (us % 1000000) * 1000;
abs->tv_sec += abs->tv_nsec / 1000000000;
abs->tv_nsec %= 1000000000;
return;
}
#endif

struct timespec ts;
MICROSECONDS_TO_TIMESPEC(us, ts);
*abs = ts;
}


/* 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:
Expand Down Expand Up @@ -146,6 +186,7 @@ PyThread__init_thread(void)
extern void pthread_init(void);
pthread_init();
#endif
init_condattr();
}

/*
Expand Down Expand Up @@ -462,8 +503,7 @@ PyThread_allocate_lock(void)
memset((void *)lock, '\0', sizeof(pthread_lock));
lock->locked = 0;

status = pthread_mutex_init(&lock->mut,
pthread_mutexattr_default);
status = pthread_mutex_init(&lock->mut, NULL);
CHECK_STATUS_PTHREAD("pthread_mutex_init");
/* Mark the pthread mutex underlying a Python mutex as
pure happens-before. We can't simply mark the
Expand All @@ -472,8 +512,7 @@ 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);
status = _PyThread_cond_init(&lock->lock_released);
CHECK_STATUS_PTHREAD("pthread_cond_init");

if (error) {
Expand Down Expand Up @@ -532,9 +571,10 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
success = PY_LOCK_ACQUIRED;
}
else if (microseconds != 0) {
struct timespec ts;
if (microseconds > 0)
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
struct timespec abs;
if (microseconds > 0) {
_PyThread_cond_after(microseconds, &abs);
}
/* continue trying until we get the lock */

/* mut must be locked by me -- part of the condition
Expand All @@ -543,10 +583,13 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
if (microseconds > 0) {
status = pthread_cond_timedwait(
&thelock->lock_released,
&thelock->mut, &ts);
&thelock->mut, &abs);
if (status == 1) {
break;
}
if (status == ETIMEDOUT)
break;
CHECK_STATUS_PTHREAD("pthread_cond_timed_wait");
CHECK_STATUS_PTHREAD("pthread_cond_timedwait");
}
else {
status = pthread_cond_wait(
Expand Down
3 changes: 2 additions & 1 deletion 3 configure
Original file line number Diff line number Diff line change
Expand Up @@ -11448,7 +11448,8 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
memrchr mbrtowc mkdirat mkfifo \
mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
pthread_condattr_setclock pthread_init pthread_kill putenv pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \
setgid sethostname \
setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \
Expand Down
3 changes: 2 additions & 1 deletion 3 configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3506,7 +3506,8 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
memrchr mbrtowc mkdirat mkfifo \
mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
posix_fallocate posix_fadvise posix_spawn posix_spawnp pread preadv preadv2 \
pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
pthread_condattr_setclock pthread_init pthread_kill putenv pwrite pwritev pwritev2 \
readlink readlinkat readv realpath renameat \
sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \
setgid sethostname \
setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \
Expand Down
3 changes: 3 additions & 0 deletions 3 pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,9 @@
/* Define if your compiler supports function prototype */
#undef HAVE_PROTOTYPES

/* Define to 1 if you have the `pthread_condattr_setclock' function. */
#undef HAVE_PTHREAD_CONDATTR_SETCLOCK

/* Defined for Solaris 2.6 bug in pthread header. */
#undef HAVE_PTHREAD_DESTRUCTOR

Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.