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