| 811 | } |
| 812 | |
| 813 | orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem, |
| 814 | std::uint64_t ut) { |
| 815 | ORBIS_LOG_TRACE(__FUNCTION__, sem, ut); |
| 816 | auto [chain, key, lock] = umtxStorage->getUmtxChain0(thread, sem->flags, sem); |
| 817 | auto node = chain.enqueue(key, thread); |
| 818 | |
| 819 | std::uint32_t has_waiters = sem->has_waiters; |
| 820 | if (!has_waiters) |
| 821 | sem->has_waiters.compare_exchange_strong(has_waiters, 1); |
| 822 | |
| 823 | ErrorCode result = {}; |
| 824 | if (!sem->count) { |
| 825 | if (ut + 1 == 0) { |
| 826 | while (true) { |
| 827 | orbis::scoped_unblock unblock; |
| 828 | result = orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut)); |
| 829 | if ((result != ErrorCode{}) || node->second.thr != thread) |
| 830 | break; |
| 831 | } |
| 832 | } else { |
| 833 | auto start = std::chrono::steady_clock::now(); |
| 834 | std::uint64_t udiff = 0; |
| 835 | while (true) { |
| 836 | orbis::scoped_unblock unblock; |
| 837 | result = |
| 838 | orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut - udiff)); |
| 839 | if (node->second.thr != thread) |
| 840 | break; |
| 841 | udiff = std::chrono::duration_cast<std::chrono::microseconds>( |
| 842 | std::chrono::steady_clock::now() - start) |
| 843 | .count(); |
| 844 | if (udiff >= ut) { |
| 845 | result = ErrorCode::TIMEDOUT; |
| 846 | break; |
| 847 | } |
| 848 | if (result != ErrorCode{}) { |
| 849 | break; |
| 850 | } |
| 851 | } |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | if (node->second.thr != thread) { |
| 856 | result = {}; |
| 857 | } else { |
| 858 | chain.erase(node); |
| 859 | } |
| 860 | return result; |
| 861 | } |
| 862 | |
| 863 | orbis::ErrorCode orbis::umtx_sem_wake(Thread *thread, ptr<usem> sem) { |
| 864 | ORBIS_LOG_TRACE(__FUNCTION__, sem); |
nothing calls this directly
no test coverage detected