| 459 | } |
| 460 | |
| 461 | int butex_requeue(void* arg, void* arg2) { |
| 462 | Butex* b = container_of(static_cast<butil::atomic<int>*>(arg), Butex, value); |
| 463 | Butex* m = container_of(static_cast<butil::atomic<int>*>(arg2), Butex, value); |
| 464 | |
| 465 | ButexWaiter* front = NULL; |
| 466 | { |
| 467 | std::unique_lock<FastPthreadMutex> lck1(b->waiter_lock, std::defer_lock); |
| 468 | std::unique_lock<FastPthreadMutex> lck2(m->waiter_lock, std::defer_lock); |
| 469 | butil::double_lock(lck1, lck2); |
| 470 | if (b->waiters.empty()) { |
| 471 | return 0; |
| 472 | } |
| 473 | |
| 474 | front = b->waiters.head()->value(); |
| 475 | front->RemoveFromList(); |
| 476 | front->container.store(NULL, butil::memory_order_relaxed); |
| 477 | |
| 478 | while (!b->waiters.empty()) { |
| 479 | ButexWaiter* bw = b->waiters.head()->value(); |
| 480 | bw->RemoveFromList(); |
| 481 | m->waiters.Append(bw); |
| 482 | bw->container.store(m, butil::memory_order_relaxed); |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | if (front->tid == 0) { // which is a pthread |
| 487 | wakeup_pthread(static_cast<ButexPthreadWaiter*>(front)); |
| 488 | return 1; |
| 489 | } |
| 490 | ButexBthreadWaiter* bbw = static_cast<ButexBthreadWaiter*>(front); |
| 491 | unsleep_if_necessary(bbw, get_global_timer_thread()); |
| 492 | auto g = is_same_tag(bbw->tag) ? tls_task_group : NULL; |
| 493 | if (g) { |
| 494 | TaskGroup::exchange(&g, bbw->task_meta); |
| 495 | } else { |
| 496 | bbw->control->choose_one_group(bbw->tag)->ready_to_run_remote(bbw->task_meta); |
| 497 | } |
| 498 | return 1; |
| 499 | } |
| 500 | |
| 501 | // Callable from multiple threads, at most one thread may wake up the waiter. |
| 502 | static void erase_from_butex_and_wakeup(void* arg) { |
no test coverage detected