1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <vector>
6 
7 #include <fbl/string_printf.h>
8 #include <lib/zx/timer.h>
9 #include <perftest/perftest.h>
10 
11 namespace {
12 
13 struct TimerState {
14     zx::duration wait_time;
15     zx::duration slack_time;
16 };
17 
SlackTypeToString(uint32_t slack_type)18 const char* SlackTypeToString(uint32_t slack_type) {
19     switch (slack_type) {
20     case ZX_TIMER_SLACK_LATE:
21         return "SlackLate";
22     case ZX_TIMER_SLACK_EARLY:
23         return "SlackEarly";
24     case ZX_TIMER_SLACK_CENTER:
25         return "SlackCenter";
26     default:
27         ZX_ASSERT_MSG(true, "Slack type unsupported\n");
28         return nullptr;
29     }
30 }
31 
32 // Measures how long a timer takes to fire based on the wait time, slack time,
33 // and slack type. This can be useful for measuring the overhead of sleeping.
34 // It can also be used to measure the variation in actual sleep times.
TimerWaitTest(perftest::RepeatState * state,TimerState timer_state,uint32_t slack_type)35 bool TimerWaitTest(perftest::RepeatState* state, TimerState timer_state, uint32_t slack_type) {
36     zx_status_t status;
37     zx::timer timer;
38 
39     status = zx::timer::create(slack_type, ZX_CLOCK_MONOTONIC, &timer);
40     ZX_ASSERT(status == ZX_OK);
41 
42     while (state->KeepRunning()) {
43         status = timer.set(zx::deadline_after(timer_state.wait_time),
44                            timer_state.slack_time);
45         ZX_ASSERT(status == ZX_OK);
46         zx_status_t status = timer.wait_one(
47             ZX_TIMER_SIGNALED, zx::time::infinite(), nullptr);
48         ZX_ASSERT(status == ZX_OK);
49     }
50 
51     return true;
52 }
53 
RegisterTests()54 void RegisterTests() {
55     const TimerState timers[] = {
56         TimerState{zx::msec(1), zx::usec(0)},
57         TimerState{zx::msec(1), zx::usec(500)}};
58     const uint32_t slack_types[] = {ZX_TIMER_SLACK_LATE,
59                                     ZX_TIMER_SLACK_EARLY, ZX_TIMER_SLACK_CENTER};
60 
61     for (auto timer : timers) {
62         for (auto slack_type : slack_types) {
63             auto name = fbl::StringPrintf("Timer/%lumsWait/%s%luus",
64                                           timer.wait_time.to_msecs(),
65                                           SlackTypeToString(slack_type),
66                                           timer.slack_time.to_usecs());
67             perftest::RegisterTest(name.c_str(), TimerWaitTest, timer, slack_type);
68         }
69     }
70 }
71 PERFTEST_CTOR(RegisterTests);
72 
73 } // namespace
74