| 1610 | } |
| 1611 | |
| 1612 | bool lv2_obj::sleep(cpu_thread &cpu, const u64 timeout) { |
| 1613 | // Should already be performed when using this flag |
| 1614 | if (!g_postpone_notify_barrier) { |
| 1615 | prepare_for_sleep(cpu); |
| 1616 | } |
| 1617 | |
| 1618 | if (cpu.get_class() == thread_class::ppu) { |
| 1619 | if (u32 addr = static_cast<ppu_thread &>(cpu).res_notify) { |
| 1620 | static_cast<ppu_thread &>(cpu).res_notify = 0; |
| 1621 | |
| 1622 | if (static_cast<ppu_thread &>(cpu).res_notify_time != |
| 1623 | vm::reservation_notifier_count_index(addr).second) { |
| 1624 | // Ignore outdated notification request |
| 1625 | } else if (auto it = std::find(g_to_notify, std::end(g_to_notify), |
| 1626 | std::add_pointer_t<const void>{}); |
| 1627 | it != std::end(g_to_notify)) { |
| 1628 | *it++ = vm::reservation_notifier_notify(addr, true); |
| 1629 | |
| 1630 | if (it < std::end(g_to_notify)) { |
| 1631 | // Null-terminate the list if it ends before last slot |
| 1632 | *it = nullptr; |
| 1633 | } |
| 1634 | } else { |
| 1635 | vm::reservation_notifier_notify(addr); |
| 1636 | } |
| 1637 | } |
| 1638 | } |
| 1639 | |
| 1640 | bool result = false; |
| 1641 | const u64 current_time = get_guest_system_time(); |
| 1642 | { |
| 1643 | std::lock_guard lock{g_mutex}; |
| 1644 | result = sleep_unlocked(cpu, timeout, current_time); |
| 1645 | |
| 1646 | if (!g_to_awake.empty()) { |
| 1647 | // Schedule pending entries |
| 1648 | awake_unlocked({}); |
| 1649 | } |
| 1650 | |
| 1651 | schedule_all(current_time); |
| 1652 | } |
| 1653 | |
| 1654 | if (!g_postpone_notify_barrier) { |
| 1655 | notify_all(); |
| 1656 | } |
| 1657 | |
| 1658 | g_to_awake.clear(); |
| 1659 | return result; |
| 1660 | } |
| 1661 | |
| 1662 | bool lv2_obj::awake(cpu_thread *thread, s32 prio) { |
| 1663 | if (ppu_thread *ppu = cpu_thread::get_current<ppu_thread>()) { |
no test coverage detected