| 133 | } |
| 134 | |
| 135 | error_code sys_mutex_lock(ppu_thread &ppu, u32 mutex_id, u64 timeout) { |
| 136 | ppu.state += cpu_flag::wait; |
| 137 | |
| 138 | sys_mutex.trace("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx)", mutex_id, |
| 139 | timeout); |
| 140 | |
| 141 | const auto mutex = idm::get<lv2_obj, lv2_mutex>( |
| 142 | mutex_id, [&, notify = lv2_obj::notify_all_t()](lv2_mutex &mutex) { |
| 143 | CellError result = mutex.try_lock(ppu); |
| 144 | |
| 145 | if (result == CELL_EBUSY && |
| 146 | !atomic_storage<ppu_thread *>::load(mutex.control.raw().sq)) { |
| 147 | // Try busy waiting a bit if advantageous |
| 148 | for (u32 i = 0, end = lv2_obj::has_ppus_in_running_state() ? 3 : 10; |
| 149 | id_manager::g_mutex.is_lockable() && i < end; i++) { |
| 150 | rx::busy_wait(300); |
| 151 | result = mutex.try_lock(ppu); |
| 152 | |
| 153 | if (!result || |
| 154 | atomic_storage<ppu_thread *>::load(mutex.control.raw().sq)) { |
| 155 | break; |
| 156 | } |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | if (result == CELL_EBUSY) { |
| 161 | lv2_obj::prepare_for_sleep(ppu); |
| 162 | |
| 163 | ppu.cancel_sleep = 1; |
| 164 | |
| 165 | if (mutex.try_own(ppu) || !mutex.sleep(ppu, timeout)) { |
| 166 | result = {}; |
| 167 | } |
| 168 | |
| 169 | if (ppu.cancel_sleep != 1) { |
| 170 | notify.cleanup(); |
| 171 | } |
| 172 | |
| 173 | ppu.cancel_sleep = 0; |
| 174 | } |
| 175 | |
| 176 | return result; |
| 177 | }); |
| 178 | |
| 179 | if (!mutex) { |
| 180 | return CELL_ESRCH; |
| 181 | } |
| 182 | |
| 183 | if (mutex.ret) { |
| 184 | if (mutex.ret != CELL_EBUSY) { |
| 185 | return mutex.ret; |
| 186 | } |
| 187 | } else { |
| 188 | return CELL_OK; |
| 189 | } |
| 190 | |
| 191 | ppu.gpr[3] = CELL_OK; |
| 192 |
no test coverage detected