12
12
#include " base/mac/mach_logging.h"
13
13
#include " base/mac/scoped_nsautorelease_pool.h"
14
14
#include " base/posix/eintr_wrapper.h"
15
- #include " base/time/time_override.h"
16
15
17
16
namespace base {
18
17
@@ -22,22 +21,10 @@ namespace {
22
21
// port sets. MessagePumpKqueue will directly use Mach ports in the kqueue if
23
22
// it is possible.
24
23
bool KqueueNeedsPortSet () {
25
- static const bool kqueue_needs_port_set = mac::IsAtMostOS10_11 ();
24
+ static bool kqueue_needs_port_set = mac::IsAtMostOS10_11 ();
26
25
return kqueue_needs_port_set;
27
26
}
28
27
29
- #if DCHECK_IS_ON()
30
- // Prior to macOS 10.14, kqueue timers may spuriously wake up, because earlier
31
- // wake ups race with timer resets in the kernel. As of macOS 10.14, updating a
32
- // timer from the thread that reads the kqueue does not cause spurious wakeups.
33
- // Note that updating a kqueue timer from one thread while another thread is
34
- // waiting in a kevent64 invocation is still (inherently) racy.
35
- bool KqueueTimersSpuriouslyWakeUp () {
36
- static const bool kqueue_timers_spuriously_wakeup = mac::IsAtMostOS10_13 ();
37
- return kqueue_timers_spuriously_wakeup;
38
- }
39
- #endif
40
-
41
28
int ChangeOneEvent (const ScopedFD& kqueue, kevent64_s* event) {
42
29
return HANDLE_EINTR (kevent64 (kqueue.get (), event, 1 , nullptr , 0 , 0 , nullptr ));
43
30
}
@@ -378,13 +365,25 @@ bool MessagePumpKqueue::DoInternalWork(Delegate* delegate,
378
365
379
366
bool poll = next_work_info == nullptr ;
380
367
int flags = poll ? KEVENT_FLAG_IMMEDIATE : 0 ;
381
- if (!poll && scheduled_wakeup_time_ != next_work_info->delayed_run_time ) {
382
- UpdateWakeupTimer (next_work_info->delayed_run_time );
383
- DCHECK_EQ (scheduled_wakeup_time_, next_work_info->delayed_run_time );
384
- }
385
-
386
- int rv = HANDLE_EINTR (kevent64 (kqueue_.get (), nullptr , 0 , events_.data (),
387
- events_.size (), flags, nullptr ));
368
+ bool indefinite =
369
+ next_work_info != nullptr && next_work_info->delayed_run_time .is_max ();
370
+
371
+ int rv = 0 ;
372
+ do {
373
+ timespec timeout{};
374
+ if (!indefinite && !poll) {
375
+ if (rv != 0 ) {
376
+ // The wait was interrupted and made |next_work_info|'s view of
377
+ // TimeTicks::Now() stale. Refresh it before doing another wait.
378
+ next_work_info->recent_now = TimeTicks::Now ();
379
+ }
380
+ timeout = next_work_info->remaining_delay ().ToTimeSpec ();
381
+ }
382
+ // This does not use HANDLE_EINTR, since retrying the syscall requires
383
+ // adjusting the timeout to account for time already waited.
384
+ rv = kevent64 (kqueue_.get (), nullptr , 0 , events_.data (), events_.size (),
385
+ flags, indefinite ? nullptr : &timeout);
386
+ } while (rv < 0 && errno == EINTR);
388
387
389
388
PCHECK (rv >= 0 ) << " kevent64" ;
390
389
return ProcessEvents (delegate, rv);
@@ -449,25 +448,6 @@ bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, int count) {
449
448
auto scoped_do_native_work = delegate->BeginNativeWork ();
450
449
controller->watcher ()->OnMachMessageReceived (port);
451
450
}
452
- } else if (event->filter == EVFILT_TIMER) {
453
- // The wakeup timer fired.
454
- #if DCHECK_IS_ON()
455
- // On macOS 10.13 and earlier, kqueue timers may spuriously wake up.
456
- // When this happens, the timer will be re-scheduled the next time
457
- // DoInternalWork is entered, which means this doesn't lead to a
458
- // spinning wait.
459
- // When clock overrides are active, TimeTicks::Now may be decoupled from
460
- // wall-clock time, and can therefore not be used to validate whether the
461
- // expected wall-clock time has passed.
462
- if (!KqueueTimersSpuriouslyWakeUp () &&
463
- !subtle::ScopedTimeClockOverrides::overrides_active ()) {
464
- // Given the caveats above, assert that the timer didn't fire early.
465
- DCHECK_LE (scheduled_wakeup_time_, base::TimeTicks::Now ());
466
- }
467
- #endif
468
- DCHECK_NE (scheduled_wakeup_time_, base::TimeTicks::Max ());
469
- scheduled_wakeup_time_ = base::TimeTicks::Max ();
470
- --event_count_;
471
451
} else {
472
452
NOTREACHED () << " Unexpected event for filter " << event->filter ;
473
453
}
@@ -476,47 +456,4 @@ bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, int count) {
476
456
return did_work;
477
457
}
478
458
479
- void MessagePumpKqueue::UpdateWakeupTimer (const base::TimeTicks& wakeup_time) {
480
- DCHECK_NE (wakeup_time, scheduled_wakeup_time_);
481
-
482
- // The ident of the wakeup timer. There's only the one timer as the pair
483
- // (ident, filter) is the identity of the event.
484
- constexpr uint64_t kWakeupTimerIdent = 0x0 ;
485
- if (wakeup_time == base::TimeTicks::Max ()) {
486
- // Clear the timer.
487
- kevent64_s timer{};
488
- timer.ident = kWakeupTimerIdent ;
489
- timer.filter = EVFILT_TIMER;
490
- timer.flags = EV_DELETE;
491
-
492
- int rv = ChangeOneEvent (kqueue_, &timer);
493
- PCHECK (rv == 0 ) << " kevent64, delete timer" ;
494
- --event_count_;
495
- } else {
496
- // Set/reset the timer.
497
- kevent64_s timer{};
498
- timer.ident = kWakeupTimerIdent ;
499
- timer.filter = EVFILT_TIMER;
500
- // This updates the timer if it already exists in |kqueue_|.
501
- timer.flags = EV_ADD | EV_ONESHOT;
502
- // Specify the sleep in microseconds to avoid undersleeping due to
503
- // numeric problems. The sleep is computed from TimeTicks::Now rather than
504
- // NextWorkInfo::recent_now because recent_now is strictly earlier than
505
- // current wall-clock. Using an earlier wall clock time to compute the
506
- // delta to the next wakeup wall-clock time would guarantee oversleep.
507
- // If wakeup_time is in the past, the delta below will be negative and the
508
- // timer is set immediately.
509
- timer.fflags = NOTE_USECONDS;
510
- timer.data = (wakeup_time - base::TimeTicks::Now ()).InMicroseconds ();
511
- int rv = ChangeOneEvent (kqueue_, &timer);
512
- PCHECK (rv == 0 ) << " kevent64, set timer" ;
513
-
514
- // Bump the event count if we just added the timer.
515
- if (scheduled_wakeup_time_ == base::TimeTicks::Max ())
516
- ++event_count_;
517
- }
518
-
519
- scheduled_wakeup_time_ = wakeup_time;
520
- }
521
-
522
459
} // namespace base
0 commit comments