- switch (timeout) {
- default:
- do {
- uint64_t nsec = _dispatch_timeout(timeout);
- _timeout.tv_sec = (typeof(_timeout.tv_sec))(nsec / NSEC_PER_SEC);
- _timeout.tv_nsec = (typeof(_timeout.tv_nsec))(nsec % NSEC_PER_SEC);
- kr = slowpath(semaphore_timedwait(dsema->dsema_waiter_port,
- _timeout));
- } while (kr == KERN_ABORTED);
-
- if (kr != KERN_OPERATION_TIMED_OUT) {
- DISPATCH_SEMAPHORE_VERIFY_KR(kr);
- break;
- }
- // Fall through and try to undo the earlier change to
- // dsema->dsema_group_waiters
- case DISPATCH_TIME_NOW:
- while ((orig = dsema->dsema_group_waiters)) {
- if (dispatch_atomic_cmpxchg2o(dsema, dsema_group_waiters, orig,
- orig - 1)) {
- return KERN_OPERATION_TIMED_OUT;
- }
- }
- // Another thread called semaphore_signal().
- // Fall through and drain the wakeup.
- case DISPATCH_TIME_FOREVER:
- do {
- kr = semaphore_wait(dsema->dsema_waiter_port);
- } while (kr == KERN_ABORTED);
- DISPATCH_SEMAPHORE_VERIFY_KR(kr);
- break;
+ (void)os_atomic_inc2o(dg, dg_waiters, relaxed);
+ // check the values again in case we need to wake any threads
+ value = os_atomic_load2o(dg, dg_value, ordered); // 19296565
+ if (value == 0) {
+ _dispatch_group_wake(dg, false);
+ // Fall through to consume the extra signal, forcing timeout to avoid
+ // useless setups as it won't block
+ timeout = DISPATCH_TIME_FOREVER;