| 509 | } |
| 510 | |
| 511 | inline bool erase_from_butex(ButexWaiter* bw, bool wakeup, WaiterState state) { |
| 512 | // `bw' is guaranteed to be valid inside this function because waiter |
| 513 | // will wait until this function being cancelled or finished. |
| 514 | // NOTE: This function must be no-op when bw->container is NULL. |
| 515 | bool erased = false; |
| 516 | Butex* b; |
| 517 | int saved_errno = errno; |
| 518 | while ((b = bw->container.load(butil::memory_order_acquire))) { |
| 519 | // b can be NULL when the waiter is scheduled but queued. |
| 520 | BAIDU_SCOPED_LOCK(b->waiter_lock); |
| 521 | if (b == bw->container.load(butil::memory_order_relaxed)) { |
| 522 | bw->RemoveFromList(); |
| 523 | bw->container.store(NULL, butil::memory_order_relaxed); |
| 524 | if (bw->tid) { |
| 525 | static_cast<ButexBthreadWaiter*>(bw)->waiter_state = state; |
| 526 | } |
| 527 | erased = true; |
| 528 | break; |
| 529 | } |
| 530 | } |
| 531 | if (erased && wakeup) { |
| 532 | if (bw->tid) { |
| 533 | ButexBthreadWaiter* bbw = static_cast<ButexBthreadWaiter*>(bw); |
| 534 | get_task_group(bbw->control, bbw->tag)->ready_to_run_general(bbw->task_meta); |
| 535 | } else { |
| 536 | ButexPthreadWaiter* pw = static_cast<ButexPthreadWaiter*>(bw); |
| 537 | wakeup_pthread(pw); |
| 538 | } |
| 539 | } |
| 540 | errno = saved_errno; |
| 541 | return erased; |
| 542 | } |
| 543 | |
| 544 | struct WaitForButexArgs { |
| 545 | ButexBthreadWaiter* bw; |
no test coverage detected