| 2419 | } |
| 2420 | |
| 2421 | void thread_ctrl::wait_for(u64 usec, [[maybe_unused]] bool alert /* true */) |
| 2422 | { |
| 2423 | if (!usec) |
| 2424 | { |
| 2425 | return; |
| 2426 | } |
| 2427 | |
| 2428 | auto _this = g_tls_this_thread; |
| 2429 | |
| 2430 | if (!alert && usec > 50000) |
| 2431 | { |
| 2432 | usec = 50000; |
| 2433 | } |
| 2434 | |
| 2435 | #ifdef __linux__ |
| 2436 | static thread_local struct linux_timer_handle_t |
| 2437 | { |
| 2438 | // Allocate timer only if needed (i.e. someone calls wait_for with alert and short period) |
| 2439 | const int m_timer = timerfd_create(CLOCK_MONOTONIC, 0); |
| 2440 | |
| 2441 | linux_timer_handle_t() noexcept |
| 2442 | { |
| 2443 | if (m_timer == -1) |
| 2444 | { |
| 2445 | sig_log.error("Linux timer allocation failed, using the fallback instead."); |
| 2446 | } |
| 2447 | } |
| 2448 | |
| 2449 | operator int() const |
| 2450 | { |
| 2451 | return m_timer; |
| 2452 | } |
| 2453 | |
| 2454 | ~linux_timer_handle_t() |
| 2455 | { |
| 2456 | if (m_timer != -1) |
| 2457 | { |
| 2458 | close(m_timer); |
| 2459 | } |
| 2460 | } |
| 2461 | } fd_timer; |
| 2462 | |
| 2463 | if (!alert && fd_timer != -1) |
| 2464 | { |
| 2465 | struct itimerspec timeout; |
| 2466 | u64 missed; |
| 2467 | |
| 2468 | timeout.it_value.tv_nsec = usec % 1'000'000 * 1'000ull; |
| 2469 | timeout.it_value.tv_sec = usec / 1'000'000; |
| 2470 | timeout.it_interval.tv_sec = 0; |
| 2471 | timeout.it_interval.tv_nsec = 0; |
| 2472 | timerfd_settime(fd_timer, 0, &timeout, NULL); |
| 2473 | if (read(fd_timer, &missed, sizeof(missed)) != sizeof(missed)) |
| 2474 | sig_log.error("timerfd: read() failed"); |
| 2475 | return; |
| 2476 | } |
| 2477 | #endif |
| 2478 |
no test coverage detected