(
sem: *mut sem_t,
deadline: &libc::timespec,
vm: &VirtualMachine,
)
| 434 | /// Matches sem_timedwait_save in semaphore.c |
| 435 | #[cfg(target_vendor = "apple")] |
| 436 | fn sem_timedwait_polled( |
| 437 | sem: *mut sem_t, |
| 438 | deadline: &libc::timespec, |
| 439 | vm: &VirtualMachine, |
| 440 | ) -> Result<(), SemWaitError> { |
| 441 | let mut delay: u64 = 0; |
| 442 | |
| 443 | loop { |
| 444 | // poll: try to acquire |
| 445 | if unsafe { libc::sem_trywait(sem) } == 0 { |
| 446 | return Ok(()); |
| 447 | } |
| 448 | let err = Errno::last(); |
| 449 | if err != Errno::EAGAIN { |
| 450 | return Err(SemWaitError::OsError(err)); |
| 451 | } |
| 452 | |
| 453 | // get current time |
| 454 | let mut now = libc::timeval { |
| 455 | tv_sec: 0, |
| 456 | tv_usec: 0, |
| 457 | }; |
| 458 | if unsafe { libc::gettimeofday(&mut now, core::ptr::null_mut()) } < 0 { |
| 459 | return Err(SemWaitError::OsError(Errno::last())); |
| 460 | } |
| 461 | |
| 462 | // check for timeout |
| 463 | let deadline_usec = deadline.tv_sec * 1_000_000 + deadline.tv_nsec / 1000; |
| 464 | #[allow(clippy::unnecessary_cast)] |
| 465 | let now_usec = now.tv_sec as i64 * 1_000_000 + now.tv_usec as i64; |
| 466 | |
| 467 | if now_usec >= deadline_usec { |
| 468 | return Err(SemWaitError::Timeout); |
| 469 | } |
| 470 | |
| 471 | // calculate how much time is left |
| 472 | let difference = (deadline_usec - now_usec) as u64; |
| 473 | |
| 474 | // check delay not too long -- maximum is 20 msecs |
| 475 | delay += 1000; |
| 476 | if delay > 20000 { |
| 477 | delay = 20000; |
| 478 | } |
| 479 | if delay > difference { |
| 480 | delay = difference; |
| 481 | } |
| 482 | |
| 483 | // sleep using select |
| 484 | let mut tv_delay = libc::timeval { |
| 485 | tv_sec: (delay / 1_000_000) as _, |
| 486 | tv_usec: (delay % 1_000_000) as _, |
| 487 | }; |
| 488 | vm.allow_threads(|| unsafe { |
| 489 | libc::select( |
| 490 | 0, |
| 491 | core::ptr::null_mut(), |
| 492 | core::ptr::null_mut(), |
| 493 | core::ptr::null_mut(), |
no test coverage detected