| 228 | } |
| 229 | |
| 230 | error_code _sys_timer_start(ppu_thread &ppu, u32 timer_id, u64 base_time, |
| 231 | u64 period) { |
| 232 | ppu.state += cpu_flag::wait; |
| 233 | |
| 234 | (period ? sys_timer.warning : sys_timer.trace)( |
| 235 | "_sys_timer_start(timer_id=0x%x, base_time=0x%llx, period=0x%llx)", |
| 236 | timer_id, base_time, period); |
| 237 | |
| 238 | const u64 start_time = get_guest_system_time(); |
| 239 | |
| 240 | if (period && period < 100) { |
| 241 | // Invalid periodic timer |
| 242 | return CELL_EINVAL; |
| 243 | } |
| 244 | |
| 245 | const auto timer = idm::check<lv2_obj, lv2_timer>( |
| 246 | timer_id, [&](lv2_timer &timer) -> CellError { |
| 247 | std::lock_guard lock(timer.mutex); |
| 248 | |
| 249 | // LV2 Disassembly: Simple nullptr check (assignment test, do not use |
| 250 | // lv2_obj::check here) |
| 251 | if (!timer.port) { |
| 252 | return CELL_ENOTCONN; |
| 253 | } |
| 254 | |
| 255 | timer.check_unlocked(start_time); |
| 256 | if (timer.state != SYS_TIMER_STATE_STOP) { |
| 257 | return CELL_EBUSY; |
| 258 | } |
| 259 | |
| 260 | if (!period && start_time >= base_time) { |
| 261 | // Invalid oneshot |
| 262 | return CELL_ETIMEDOUT; |
| 263 | } |
| 264 | |
| 265 | const u64 expire = |
| 266 | period == 0 ? base_time : // oneshot |
| 267 | base_time == 0 |
| 268 | ? rx::add_saturate(start_time, period) |
| 269 | : |
| 270 | // periodic timer with no base (using start time as base) |
| 271 | start_time < rx::add_saturate(base_time, period) |
| 272 | ? rx::add_saturate(base_time, period) |
| 273 | : |
| 274 | // periodic with base time over start time |
| 275 | [&]() -> u64 // periodic timer base before start time (align to |
| 276 | // be at least a period over start time) |
| 277 | { |
| 278 | // Optimized from a loop in LV2: |
| 279 | // do |
| 280 | // { |
| 281 | // base_time += period; |
| 282 | // } |
| 283 | // while (base_time < start_time); |
| 284 | |
| 285 | const u64 start_time_with_base_time_reminder = rx::add_saturate( |
| 286 | start_time - start_time % period, base_time % period); |
| 287 |
nothing calls this directly
no test coverage detected