1/*
2 * Copyright (C) 2005-2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <stdint.h>
20#include <time.h>
21
22/* struct log_time is a wire-format variant of struct timespec */
23#define NS_PER_SEC 1000000000ULL
24#define US_PER_SEC 1000000ULL
25#define MS_PER_SEC 1000ULL
26
27#define LOG_TIME_SEC(t) ((t)->tv_sec)
28/* next power of two after NS_PER_SEC */
29#define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
30
31#ifdef __cplusplus
32
33extern "C" {
34
35struct log_time {
36 public:
37  uint32_t tv_sec = 0; /* good to Feb 5 2106 */
38  uint32_t tv_nsec = 0;
39
40  static constexpr timespec EPOCH = {0, 0};
41
42  log_time() {}
43  explicit log_time(const timespec& T)
44      : tv_sec(static_cast<uint32_t>(T.tv_sec)), tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {}
45  explicit log_time(uint32_t sec, uint32_t nsec = 0)
46      : tv_sec(sec), tv_nsec(nsec) {
47  }
48#ifdef __linux__
49  explicit log_time(clockid_t id) {
50    timespec T;
51    clock_gettime(id, &T);
52    tv_sec = static_cast<uint32_t>(T.tv_sec);
53    tv_nsec = static_cast<uint32_t>(T.tv_nsec);
54  }
55#endif
56  /* timespec */
57  bool operator==(const timespec& T) const {
58    return (tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
59           (tv_nsec == static_cast<uint32_t>(T.tv_nsec));
60  }
61  bool operator!=(const timespec& T) const {
62    return !(*this == T);
63  }
64  bool operator<(const timespec& T) const {
65    return (tv_sec < static_cast<uint32_t>(T.tv_sec)) ||
66           ((tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
67            (tv_nsec < static_cast<uint32_t>(T.tv_nsec)));
68  }
69  bool operator>=(const timespec& T) const {
70    return !(*this < T);
71  }
72  bool operator>(const timespec& T) const {
73    return (tv_sec > static_cast<uint32_t>(T.tv_sec)) ||
74           ((tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
75            (tv_nsec > static_cast<uint32_t>(T.tv_nsec)));
76  }
77  bool operator<=(const timespec& T) const {
78    return !(*this > T);
79  }
80
81  /* log_time */
82  bool operator==(const log_time& T) const {
83    return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
84  }
85  bool operator!=(const log_time& T) const {
86    return !(*this == T);
87  }
88  bool operator<(const log_time& T) const {
89    return (tv_sec < T.tv_sec) ||
90           ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec));
91  }
92  bool operator>=(const log_time& T) const {
93    return !(*this < T);
94  }
95  bool operator>(const log_time& T) const {
96    return (tv_sec > T.tv_sec) ||
97           ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec));
98  }
99  bool operator<=(const log_time& T) const {
100    return !(*this > T);
101  }
102
103  log_time operator-=(const log_time& T) {
104    // No concept of negative time, clamp to EPOCH
105    if (*this <= T) {
106      return *this = log_time(EPOCH);
107    }
108
109    if (this->tv_nsec < T.tv_nsec) {
110      --this->tv_sec;
111      this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
112    } else {
113      this->tv_nsec -= T.tv_nsec;
114    }
115    this->tv_sec -= T.tv_sec;
116
117    return *this;
118  }
119  log_time operator-(const log_time& T) const {
120    log_time local(*this);
121    return local -= T;
122  }
123  log_time operator+=(const log_time& T) {
124    this->tv_nsec += T.tv_nsec;
125    if (this->tv_nsec >= NS_PER_SEC) {
126      this->tv_nsec -= NS_PER_SEC;
127      ++this->tv_sec;
128    }
129    this->tv_sec += T.tv_sec;
130
131    return *this;
132  }
133  log_time operator+(const log_time& T) const {
134    log_time local(*this);
135    return local += T;
136  }
137
138  uint64_t nsec() const {
139    return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
140  }
141  uint64_t usec() const {
142    return static_cast<uint64_t>(tv_sec) * US_PER_SEC +
143           tv_nsec / (NS_PER_SEC / US_PER_SEC);
144  }
145  uint64_t msec() const {
146    return static_cast<uint64_t>(tv_sec) * MS_PER_SEC +
147           tv_nsec / (NS_PER_SEC / MS_PER_SEC);
148  }
149
150  /* Add %#q for the fraction of a second to the standard library functions */
151  char* strptime(const char* s, const char* format);
152} __attribute__((__packed__));
153}
154
155#else /* __cplusplus */
156
157typedef struct log_time {
158  uint32_t tv_sec;
159  uint32_t tv_nsec;
160} __attribute__((__packed__)) log_time;
161
162#endif /* __cplusplus */
163