Skip to content

Commit

Permalink
core: use steady_clock where monotonic clock is required
Browse files Browse the repository at this point in the history
Use steady_clock instead of high_resolution_clock where monotonic
clock is required. high_resolution_clock is essentially a
system_clock (Wall Clock) therefore may not be assumed monotonic
since Wall Clock may move backwards due to time/date adjustments.

Signed-off-by: Vlad Zolotarov <[email protected]>
  • Loading branch information
Vlad Zolotarov committed Dec 22, 2015
1 parent bb45cc6 commit 2578c34
Show file tree
Hide file tree
Showing 9 changed files with 27 additions and 17 deletions.
10 changes: 10 additions & 0 deletions apps/memcached/memcache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ struct expiration {
} else if (s <= seconds_in_a_month) {
_time = clock_type::now() + seconds(s); // from delta
} else {
//
// seastar::reactor supports only a monotonic clock at the moment
// therefore this may make the elements with the absolute expiration
// time expire at the wrong time if the wall clock has been updated
// during the expiration period. However the original memcached has
// the same weakness.
//
// TODO: Fix this when a support for system_clock-based timers is
// added to the seastar::reactor.
//
_time = time_point(seconds(s + wc_to_clock_type_delta)); // from real time
}
}
Expand Down
4 changes: 2 additions & 2 deletions apps/seawreck/seawreck.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ int main(int ac, char** av) {
auto http_clients = new distributed<http_client>;

// Start http requests on all the cores
auto started = std::chrono::high_resolution_clock::now();
auto started = std::chrono::steady_clock::now();
print("========== http_client ============\n");
print("Server: %s\n", server);
print("Connections: %u\n", total_conn);
Expand All @@ -202,7 +202,7 @@ int main(int ac, char** av) {
return http_clients->map_reduce(adder<uint64_t>(), &http_client::total_reqs);
}).then([http_clients, started] (auto total_reqs) {
// All the http requests are finished
auto finished = std::chrono::high_resolution_clock::now();
auto finished = std::chrono::steady_clock::now();
auto elapsed = finished - started;
auto secs = static_cast<double>(elapsed.count() / 1000000000.0);
print("Total cpus: %u\n", smp::count);
Expand Down
12 changes: 6 additions & 6 deletions core/reactor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ reactor::reactor()
sev.sigev_notify = SIGEV_THREAD_ID;
sev._sigev_un._tid = syscall(SYS_gettid);
sev.sigev_signo = alarm_signal();
r = timer_create(CLOCK_REALTIME, &sev, &_timer);
r = timer_create(CLOCK_MONOTONIC, &sev, &_timer);
assert(r >= 0);
sev.sigev_signo = task_quota_signal();
r = timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &_task_quota_timer);
Expand Down Expand Up @@ -1584,10 +1584,10 @@ int reactor::run() {

using namespace std::chrono_literals;
timer<lowres_clock> load_timer;
std::chrono::high_resolution_clock::rep idle_count = 0;
auto idle_start = std::chrono::high_resolution_clock::now(), idle_end = idle_start;
std::chrono::steady_clock::rep idle_count = 0;
auto idle_start = std::chrono::steady_clock::now(), idle_end = idle_start;
load_timer.set_callback([this, &idle_count, &idle_start, &idle_end] () mutable {
auto load = double(idle_count + (idle_end - idle_start).count()) / double(std::chrono::duration_cast<std::chrono::high_resolution_clock::duration>(1s).count());
auto load = double(idle_count + (idle_end - idle_start).count()) / double(std::chrono::duration_cast<std::chrono::steady_clock::duration>(1s).count());
load = std::min(load, 1.0);
idle_count = 0;
idle_start = idle_end;
Expand Down Expand Up @@ -1636,7 +1636,7 @@ int reactor::run() {
}

if (!poll_once() && _pending_tasks.empty()) {
idle_end = std::chrono::high_resolution_clock::now();
idle_end = std::chrono::steady_clock::now();
if (!idle) {
idle_start = idle_end;
idle = true;
Expand All @@ -1645,7 +1645,7 @@ int reactor::run() {
if (idle_end - idle_start > _max_poll_time) {
sleep();
// We may have slept for a while, so freshen idle_end
idle_end = std::chrono::high_resolution_clock::now();
idle_end = std::chrono::steady_clock::now();
}
} else {
if (idle) {
Expand Down
6 changes: 3 additions & 3 deletions core/scollectd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ bool scollectd::type_instance_id::operator==(
namespace scollectd {

using namespace std::chrono_literals;
using clock_type = std::chrono::high_resolution_clock;
using clock_type = std::chrono::steady_clock;


static const ipv4_addr default_addr("239.192.74.66:25826");
Expand Down Expand Up @@ -353,7 +353,7 @@ class impl {
};
// append as many values as we can fit into a packet (1024 bytes)
auto send_packet = [this, ctxt]() {
auto start = std::chrono::high_resolution_clock::now();
auto start = std::chrono::steady_clock::now();
auto & i = std::get<iterator>(*ctxt);
auto & out = std::get<cpwriter>(*ctxt);

Expand All @@ -378,7 +378,7 @@ class impl {
}
return _chan.send(_addr, net::packet(out.data(), out.size())).then([start, ctxt, this]() {
auto & out = std::get<cpwriter>(*ctxt);
auto now = std::chrono::high_resolution_clock::now();
auto now = std::chrono::steady_clock::now();
// dogfood stats
++_num_packets;
_millis += std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
Expand Down
2 changes: 1 addition & 1 deletion core/sleep.hh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "core/reactor.hh"
#include "core/future.hh"

template <typename Clock = std::chrono::high_resolution_clock, typename Rep, typename Period>
template <typename Clock = std::chrono::steady_clock, typename Rep, typename Period>
future<> sleep(std::chrono::duration<Rep, Period> dur) {
struct sleeper {
promise<> done;
Expand Down
2 changes: 1 addition & 1 deletion core/thread.hh
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class thread_attributes;
class thread_scheduling_group;

/// Clock used for scheduling threads
using thread_clock = std::chrono::high_resolution_clock; // FIXME: tsc-based clock?
using thread_clock = std::chrono::steady_clock;

/// \cond internal
class thread_context;
Expand Down
4 changes: 2 additions & 2 deletions core/timer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
#include "future.hh"
#include "timer-set.hh"

using clock_type = std::chrono::high_resolution_clock;
using clock_type = std::chrono::steady_clock;

template <typename Clock = std::chrono::high_resolution_clock>
template <typename Clock = std::chrono::steady_clock>
class timer {
public:
typedef typename Clock::time_point time_point;
Expand Down
2 changes: 1 addition & 1 deletion tests/allocator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int main(int ac, char** av) {
}
} else {
auto time = vm["time"].as<float>();
using clock = std::chrono::high_resolution_clock;
using clock = std::chrono::steady_clock;
auto end = clock::now() + std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1) * time);
while (clock::now() < end) {
for (unsigned i = 0; i < 1000; ++i) {
Expand Down
2 changes: 1 addition & 1 deletion tests/timertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ struct timer_test {

int main(int ac, char** av) {
app_template app;
timer_test<std::chrono::high_resolution_clock> t1;
timer_test<std::chrono::steady_clock> t1;
timer_test<lowres_clock> t2;
return app.run_deprecated(ac, av, [&t1, &t2] {
print("=== Start High res clock test\n");
Expand Down

0 comments on commit 2578c34

Please sign in to comment.