Skip to content
Merged
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
108 changes: 62 additions & 46 deletions Python/thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,63 +619,79 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,

if (microseconds == 0) {
status = pthread_mutex_trylock( &thelock->mut );
if (status != EBUSY)
if (status != EBUSY) {
CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]");
}
}
else {
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]");
}
if (status == 0) {
if (thelock->locked == 0) {
success = PY_LOCK_ACQUIRED;
}
else if (microseconds != 0) {
struct timespec abs;
if (microseconds > 0) {
_PyThread_cond_after(microseconds, &abs);
if (status != 0) {
goto done;
}

if (thelock->locked == 0) {
success = PY_LOCK_ACQUIRED;
goto unlock;
}
if (microseconds == 0) {
goto unlock;
}

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 protocol
while (1) {
if (microseconds > 0) {
status = pthread_cond_timedwait(&thelock->lock_released,
&thelock->mut, &abs);
if (status == 1) {
break;
}
/* continue trying until we get the lock */

/* mut must be locked by me -- part of the condition
* protocol */
while (success == PY_LOCK_FAILURE) {
if (microseconds > 0) {
status = pthread_cond_timedwait(
&thelock->lock_released,
&thelock->mut, &abs);
if (status == 1) {
break;
}
if (status == ETIMEDOUT)
break;
CHECK_STATUS_PTHREAD("pthread_cond_timedwait");
}
else {
status = pthread_cond_wait(
&thelock->lock_released,
&thelock->mut);
CHECK_STATUS_PTHREAD("pthread_cond_wait");
}

if (intr_flag && status == 0 && thelock->locked) {
/* We were woken up, but didn't get the lock. We probably received
* a signal. Return PY_LOCK_INTR to allow the caller to handle
* it and retry. */
success = PY_LOCK_INTR;
break;
}
else if (status == 0 && !thelock->locked) {
success = PY_LOCK_ACQUIRED;
}
if (status == ETIMEDOUT) {
break;
}
CHECK_STATUS_PTHREAD("pthread_cond_timedwait");
}
else {
status = pthread_cond_wait(
&thelock->lock_released,
&thelock->mut);
CHECK_STATUS_PTHREAD("pthread_cond_wait");
}

if (intr_flag && status == 0 && thelock->locked) {
// We were woken up, but didn't get the lock. We probably received
// a signal. Return PY_LOCK_INTR to allow the caller to handle
// it and retry.
success = PY_LOCK_INTR;
break;
}

if (status == 0 && !thelock->locked) {
success = PY_LOCK_ACQUIRED;
break;
}
if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]");

// Wait got interrupted by a signal: retry
}

unlock:
if (success == PY_LOCK_ACQUIRED) {
thelock->locked = 1;
}
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]");

if (error) success = PY_LOCK_FAILURE;
done:
if (error) {
success = PY_LOCK_FAILURE;
}
return success;
}

Expand Down