[3.5] bpo-30765: Avoid blocking when PyThread_acquire_lock() is asked… · python/cpython@85b34ed (original) (raw)
`@@ -464,61 +464,66 @@ PyLockStatus
`
464
464
`PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
`
465
465
`int intr_flag)
`
466
466
`{
`
467
``
`-
PyLockStatus success;
`
``
467
`+
PyLockStatus success = PY_LOCK_FAILURE;
`
468
468
`pthread_lock *thelock = (pthread_lock *)lock;
`
469
469
`int status, error = 0;
`
470
470
``
471
471
`dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n",
`
472
472
`lock, microseconds, intr_flag));
`
473
473
``
474
``
`-
status = pthread_mutex_lock( &thelock->mut );
`
475
``
`-
CHECK_STATUS("pthread_mutex_lock[1]");
`
476
``
-
477
``
`-
if (thelock->locked == 0) {
`
478
``
`-
success = PY_LOCK_ACQUIRED;
`
479
``
`-
} else if (microseconds == 0) {
`
480
``
`-
success = PY_LOCK_FAILURE;
`
481
``
`-
} else {
`
482
``
`-
struct timespec ts;
`
483
``
`-
if (microseconds > 0)
`
484
``
`-
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
`
485
``
`-
/* continue trying until we get the lock */
`
486
``
-
487
``
`-
/* mut must be locked by me -- part of the condition
`
488
``
`-
- protocol */
`
489
``
`-
success = PY_LOCK_FAILURE;
`
490
``
`-
while (success == PY_LOCK_FAILURE) {
`
491
``
`-
if (microseconds > 0) {
`
492
``
`-
status = pthread_cond_timedwait(
`
493
``
`-
&thelock->lock_released,
`
494
``
`-
&thelock->mut, &ts);
`
495
``
`-
if (status == ETIMEDOUT)
`
``
474
`+
if (microseconds == 0) {
`
``
475
`+
status = pthread_mutex_trylock( &thelock->mut );
`
``
476
`+
if (status != EBUSY)
`
``
477
`+
CHECK_STATUS("pthread_mutex_trylock[1]");
`
``
478
`+
}
`
``
479
`+
else {
`
``
480
`+
status = pthread_mutex_lock( &thelock->mut );
`
``
481
`+
CHECK_STATUS("pthread_mutex_lock[1]");
`
``
482
`+
}
`
``
483
`+
if (status == 0) {
`
``
484
`+
if (thelock->locked == 0) {
`
``
485
`+
success = PY_LOCK_ACQUIRED;
`
``
486
`+
}
`
``
487
`+
else if (microseconds != 0) {
`
``
488
`+
struct timespec ts;
`
``
489
`+
if (microseconds > 0)
`
``
490
`+
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
`
``
491
`+
/* continue trying until we get the lock */
`
``
492
+
``
493
`+
/* mut must be locked by me -- part of the condition
`
``
494
`+
- protocol */
`
``
495
`+
while (success == PY_LOCK_FAILURE) {
`
``
496
`+
if (microseconds > 0) {
`
``
497
`+
status = pthread_cond_timedwait(
`
``
498
`+
&thelock->lock_released,
`
``
499
`+
&thelock->mut, &ts);
`
``
500
`+
if (status == ETIMEDOUT)
`
``
501
`+
break;
`
``
502
`+
CHECK_STATUS("pthread_cond_timed_wait");
`
``
503
`+
}
`
``
504
`+
else {
`
``
505
`+
status = pthread_cond_wait(
`
``
506
`+
&thelock->lock_released,
`
``
507
`+
&thelock->mut);
`
``
508
`+
CHECK_STATUS("pthread_cond_wait");
`
``
509
`+
}
`
``
510
+
``
511
`+
if (intr_flag && status == 0 && thelock->locked) {
`
``
512
`+
/* We were woken up, but didn't get the lock. We probably received
`
``
513
`+
- a signal. Return PY_LOCK_INTR to allow the caller to handle
`
``
514
`+
- it and retry. */
`
``
515
`+
success = PY_LOCK_INTR;
`
496
516
`break;
`
497
``
`-
CHECK_STATUS("pthread_cond_timed_wait");
`
498
``
`-
}
`
499
``
`-
else {
`
500
``
`-
status = pthread_cond_wait(
`
501
``
`-
&thelock->lock_released,
`
502
``
`-
&thelock->mut);
`
503
``
`-
CHECK_STATUS("pthread_cond_wait");
`
504
``
`-
}
`
505
``
-
506
``
`-
if (intr_flag && status == 0 && thelock->locked) {
`
507
``
`-
/* We were woken up, but didn't get the lock. We probably received
`
508
``
`-
- a signal. Return PY_LOCK_INTR to allow the caller to handle
`
509
``
`-
- it and retry. */
`
510
``
`-
success = PY_LOCK_INTR;
`
511
``
`-
break;
`
512
``
`-
} else if (status == 0 && !thelock->locked) {
`
513
``
`-
success = PY_LOCK_ACQUIRED;
`
514
``
`-
} else {
`
515
``
`-
success = PY_LOCK_FAILURE;
`
``
517
`+
}
`
``
518
`+
else if (status == 0 && !thelock->locked) {
`
``
519
`+
success = PY_LOCK_ACQUIRED;
`
``
520
`+
}
`
516
521
` }
`
517
522
` }
`
``
523
`+
if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
`
``
524
`+
status = pthread_mutex_unlock( &thelock->mut );
`
``
525
`+
CHECK_STATUS("pthread_mutex_unlock[1]");
`
518
526
` }
`
519
``
`-
if (success == PY_LOCK_ACQUIRED) thelock->locked = 1;
`
520
``
`-
status = pthread_mutex_unlock( &thelock->mut );
`
521
``
`-
CHECK_STATUS("pthread_mutex_unlock[1]");
`
522
527
``
523
528
`if (error) success = PY_LOCK_FAILURE;
`
524
529
`dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n",
`