Skip to content

Commit e0cff58

Browse files
author
bluebox
committed
Revert "Reland "Use a timer instead of a sleep loop.""
This reverts commit 162efe9.
1 parent e5450fa commit e0cff58

File tree

2 files changed

+20
-91
lines changed

2 files changed

+20
-91
lines changed

base/message_loop/message_pump_kqueue.cc

+20-83
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "base/mac/mach_logging.h"
1313
#include "base/mac/scoped_nsautorelease_pool.h"
1414
#include "base/posix/eintr_wrapper.h"
15-
#include "base/time/time_override.h"
1615

1716
namespace base {
1817

@@ -22,22 +21,10 @@ namespace {
2221
// port sets. MessagePumpKqueue will directly use Mach ports in the kqueue if
2322
// it is possible.
2423
bool KqueueNeedsPortSet() {
25-
static const bool kqueue_needs_port_set = mac::IsAtMostOS10_11();
24+
static bool kqueue_needs_port_set = mac::IsAtMostOS10_11();
2625
return kqueue_needs_port_set;
2726
}
2827

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-
4128
int ChangeOneEvent(const ScopedFD& kqueue, kevent64_s* event) {
4229
return HANDLE_EINTR(kevent64(kqueue.get(), event, 1, nullptr, 0, 0, nullptr));
4330
}
@@ -378,13 +365,25 @@ bool MessagePumpKqueue::DoInternalWork(Delegate* delegate,
378365

379366
bool poll = next_work_info == nullptr;
380367
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);
388387

389388
PCHECK(rv >= 0) << "kevent64";
390389
return ProcessEvents(delegate, rv);
@@ -449,25 +448,6 @@ bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, int count) {
449448
auto scoped_do_native_work = delegate->BeginNativeWork();
450449
controller->watcher()->OnMachMessageReceived(port);
451450
}
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_;
471451
} else {
472452
NOTREACHED() << "Unexpected event for filter " << event->filter;
473453
}
@@ -476,47 +456,4 @@ bool MessagePumpKqueue::ProcessEvents(Delegate* delegate, int count) {
476456
return did_work;
477457
}
478458

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-
522459
} // namespace base

base/message_loop/message_pump_kqueue.h

-8
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ class BASE_EXPORT MessagePumpKqueue : public MessagePump,
137137
// true if work was done, or false if no work was done.
138138
bool ProcessEvents(Delegate* delegate, int count);
139139

140-
// Sets the wakeup timer to |wakeup_time|, or clears it if |wakeup_time| is
141-
// base::TimeTicks::Max(). Updates |scheduled_wakeup_time_| to follow.
142-
void UpdateWakeupTimer(const base::TimeTicks& wakeup_time);
143-
144140
// Receive right to which an empty Mach message is sent to wake up the pump
145141
// in response to ScheduleWork().
146142
mac::ScopedMachReceiveRight wakeup_;
@@ -164,10 +160,6 @@ class BASE_EXPORT MessagePumpKqueue : public MessagePump,
164160
// Whether the pump has been Quit() or not.
165161
bool keep_running_ = true;
166162

167-
// The currently scheduled wakeup, if any. If no wakeup is scheduled,
168-
// contains base::TimeTicks::Max().
169-
base::TimeTicks scheduled_wakeup_time_{base::TimeTicks::Max()};
170-
171163
// The number of events scheduled on the |kqueue_|. There is always at least
172164
// 1, for the |wakeup_| port (or |port_set_|).
173165
size_t event_count_ = 1;

0 commit comments

Comments
 (0)