| 152 | } |
| 153 | |
| 154 | orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id, |
| 155 | std::uint64_t ut, bool is32, bool ipc) { |
| 156 | ORBIS_LOG_NOTICE(__FUNCTION__, thread->tid, addr, id, ut, is32); |
| 157 | auto [chain, key, lock] = umtxStorage->getUmtxChain0(thread, ipc, addr); |
| 158 | auto node = chain.enqueue(key, thread); |
| 159 | ErrorCode result = {}; |
| 160 | ulong val = 0; |
| 161 | if (is32) |
| 162 | val = reinterpret_cast<ptr<std::atomic<uint>>>(addr)->load(); |
| 163 | else |
| 164 | val = reinterpret_cast<ptr<std::atomic<ulong>>>(addr)->load(); |
| 165 | if (val == id) { |
| 166 | if (ut + 1 == 0) { |
| 167 | while (true) { |
| 168 | orbis::scoped_unblock unblock; |
| 169 | result = orbis::toErrorCode(node->second.cv.wait(chain.mtx)); |
| 170 | if ((result != ErrorCode{}) || node->second.thr != thread) |
| 171 | break; |
| 172 | } |
| 173 | } else { |
| 174 | auto start = std::chrono::steady_clock::now(); |
| 175 | std::uint64_t udiff = 0; |
| 176 | while (true) { |
| 177 | orbis::scoped_unblock unblock; |
| 178 | result = |
| 179 | orbis::toErrorCode(node->second.cv.wait(chain.mtx, ut - udiff)); |
| 180 | if (node->second.thr != thread) |
| 181 | break; |
| 182 | udiff = std::chrono::duration_cast<std::chrono::microseconds>( |
| 183 | std::chrono::steady_clock::now() - start) |
| 184 | .count(); |
| 185 | if (udiff >= ut) { |
| 186 | result = ErrorCode::TIMEDOUT; |
| 187 | break; |
| 188 | } |
| 189 | if (result != ErrorCode{}) { |
| 190 | break; |
| 191 | } |
| 192 | } |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | ORBIS_LOG_NOTICE(__FUNCTION__, "wakeup", thread->tid, addr); |
| 197 | if (node->second.thr == thread) |
| 198 | chain.erase(node); |
| 199 | return result; |
| 200 | } |
| 201 | |
| 202 | orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> addr, sint n_wake) { |
| 203 | ORBIS_LOG_NOTICE(__FUNCTION__, thread->tid, addr, n_wake); |
nothing calls this directly
no test coverage detected