17ec681f3Smrg/*
27ec681f3Smrg * Copyright (C) 2005-2017 The Android Open Source Project
37ec681f3Smrg *
47ec681f3Smrg * Licensed under the Apache License, Version 2.0 (the "License");
57ec681f3Smrg * you may not use this file except in compliance with the License.
67ec681f3Smrg * You may obtain a copy of the License at
77ec681f3Smrg *
87ec681f3Smrg *      http://www.apache.org/licenses/LICENSE-2.0
97ec681f3Smrg *
107ec681f3Smrg * Unless required by applicable law or agreed to in writing, software
117ec681f3Smrg * distributed under the License is distributed on an "AS IS" BASIS,
127ec681f3Smrg * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ec681f3Smrg * See the License for the specific language governing permissions and
147ec681f3Smrg * limitations under the License.
157ec681f3Smrg */
167ec681f3Smrg
177ec681f3Smrg#pragma once
187ec681f3Smrg
197ec681f3Smrg#include <stdint.h>
207ec681f3Smrg#include <time.h>
217ec681f3Smrg
227ec681f3Smrg/* struct log_time is a wire-format variant of struct timespec */
237ec681f3Smrg#define NS_PER_SEC 1000000000ULL
247ec681f3Smrg#define US_PER_SEC 1000000ULL
257ec681f3Smrg#define MS_PER_SEC 1000ULL
267ec681f3Smrg
277ec681f3Smrg#define LOG_TIME_SEC(t) ((t)->tv_sec)
287ec681f3Smrg/* next power of two after NS_PER_SEC */
297ec681f3Smrg#define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
307ec681f3Smrg
317ec681f3Smrg#ifdef __cplusplus
327ec681f3Smrg
337ec681f3Smrgextern "C" {
347ec681f3Smrg
357ec681f3Smrgstruct log_time {
367ec681f3Smrg public:
377ec681f3Smrg  uint32_t tv_sec = 0; /* good to Feb 5 2106 */
387ec681f3Smrg  uint32_t tv_nsec = 0;
397ec681f3Smrg
407ec681f3Smrg  static constexpr timespec EPOCH = {0, 0};
417ec681f3Smrg
427ec681f3Smrg  log_time() {}
437ec681f3Smrg  explicit log_time(const timespec& T)
447ec681f3Smrg      : tv_sec(static_cast<uint32_t>(T.tv_sec)), tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {}
457ec681f3Smrg  explicit log_time(uint32_t sec, uint32_t nsec = 0)
467ec681f3Smrg      : tv_sec(sec), tv_nsec(nsec) {
477ec681f3Smrg  }
487ec681f3Smrg#ifdef __linux__
497ec681f3Smrg  explicit log_time(clockid_t id) {
507ec681f3Smrg    timespec T;
517ec681f3Smrg    clock_gettime(id, &T);
527ec681f3Smrg    tv_sec = static_cast<uint32_t>(T.tv_sec);
537ec681f3Smrg    tv_nsec = static_cast<uint32_t>(T.tv_nsec);
547ec681f3Smrg  }
557ec681f3Smrg#endif
567ec681f3Smrg  /* timespec */
577ec681f3Smrg  bool operator==(const timespec& T) const {
587ec681f3Smrg    return (tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
597ec681f3Smrg           (tv_nsec == static_cast<uint32_t>(T.tv_nsec));
607ec681f3Smrg  }
617ec681f3Smrg  bool operator!=(const timespec& T) const {
627ec681f3Smrg    return !(*this == T);
637ec681f3Smrg  }
647ec681f3Smrg  bool operator<(const timespec& T) const {
657ec681f3Smrg    return (tv_sec < static_cast<uint32_t>(T.tv_sec)) ||
667ec681f3Smrg           ((tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
677ec681f3Smrg            (tv_nsec < static_cast<uint32_t>(T.tv_nsec)));
687ec681f3Smrg  }
697ec681f3Smrg  bool operator>=(const timespec& T) const {
707ec681f3Smrg    return !(*this < T);
717ec681f3Smrg  }
727ec681f3Smrg  bool operator>(const timespec& T) const {
737ec681f3Smrg    return (tv_sec > static_cast<uint32_t>(T.tv_sec)) ||
747ec681f3Smrg           ((tv_sec == static_cast<uint32_t>(T.tv_sec)) &&
757ec681f3Smrg            (tv_nsec > static_cast<uint32_t>(T.tv_nsec)));
767ec681f3Smrg  }
777ec681f3Smrg  bool operator<=(const timespec& T) const {
787ec681f3Smrg    return !(*this > T);
797ec681f3Smrg  }
807ec681f3Smrg
817ec681f3Smrg  /* log_time */
827ec681f3Smrg  bool operator==(const log_time& T) const {
837ec681f3Smrg    return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
847ec681f3Smrg  }
857ec681f3Smrg  bool operator!=(const log_time& T) const {
867ec681f3Smrg    return !(*this == T);
877ec681f3Smrg  }
887ec681f3Smrg  bool operator<(const log_time& T) const {
897ec681f3Smrg    return (tv_sec < T.tv_sec) ||
907ec681f3Smrg           ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec));
917ec681f3Smrg  }
927ec681f3Smrg  bool operator>=(const log_time& T) const {
937ec681f3Smrg    return !(*this < T);
947ec681f3Smrg  }
957ec681f3Smrg  bool operator>(const log_time& T) const {
967ec681f3Smrg    return (tv_sec > T.tv_sec) ||
977ec681f3Smrg           ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec));
987ec681f3Smrg  }
997ec681f3Smrg  bool operator<=(const log_time& T) const {
1007ec681f3Smrg    return !(*this > T);
1017ec681f3Smrg  }
1027ec681f3Smrg
1037ec681f3Smrg  log_time operator-=(const log_time& T) {
1047ec681f3Smrg    // No concept of negative time, clamp to EPOCH
1057ec681f3Smrg    if (*this <= T) {
1067ec681f3Smrg      return *this = log_time(EPOCH);
1077ec681f3Smrg    }
1087ec681f3Smrg
1097ec681f3Smrg    if (this->tv_nsec < T.tv_nsec) {
1107ec681f3Smrg      --this->tv_sec;
1117ec681f3Smrg      this->tv_nsec = NS_PER_SEC + this->tv_nsec - T.tv_nsec;
1127ec681f3Smrg    } else {
1137ec681f3Smrg      this->tv_nsec -= T.tv_nsec;
1147ec681f3Smrg    }
1157ec681f3Smrg    this->tv_sec -= T.tv_sec;
1167ec681f3Smrg
1177ec681f3Smrg    return *this;
1187ec681f3Smrg  }
1197ec681f3Smrg  log_time operator-(const log_time& T) const {
1207ec681f3Smrg    log_time local(*this);
1217ec681f3Smrg    return local -= T;
1227ec681f3Smrg  }
1237ec681f3Smrg  log_time operator+=(const log_time& T) {
1247ec681f3Smrg    this->tv_nsec += T.tv_nsec;
1257ec681f3Smrg    if (this->tv_nsec >= NS_PER_SEC) {
1267ec681f3Smrg      this->tv_nsec -= NS_PER_SEC;
1277ec681f3Smrg      ++this->tv_sec;
1287ec681f3Smrg    }
1297ec681f3Smrg    this->tv_sec += T.tv_sec;
1307ec681f3Smrg
1317ec681f3Smrg    return *this;
1327ec681f3Smrg  }
1337ec681f3Smrg  log_time operator+(const log_time& T) const {
1347ec681f3Smrg    log_time local(*this);
1357ec681f3Smrg    return local += T;
1367ec681f3Smrg  }
1377ec681f3Smrg
1387ec681f3Smrg  uint64_t nsec() const {
1397ec681f3Smrg    return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
1407ec681f3Smrg  }
1417ec681f3Smrg  uint64_t usec() const {
1427ec681f3Smrg    return static_cast<uint64_t>(tv_sec) * US_PER_SEC +
1437ec681f3Smrg           tv_nsec / (NS_PER_SEC / US_PER_SEC);
1447ec681f3Smrg  }
1457ec681f3Smrg  uint64_t msec() const {
1467ec681f3Smrg    return static_cast<uint64_t>(tv_sec) * MS_PER_SEC +
1477ec681f3Smrg           tv_nsec / (NS_PER_SEC / MS_PER_SEC);
1487ec681f3Smrg  }
1497ec681f3Smrg
1507ec681f3Smrg  /* Add %#q for the fraction of a second to the standard library functions */
1517ec681f3Smrg  char* strptime(const char* s, const char* format);
1527ec681f3Smrg} __attribute__((__packed__));
1537ec681f3Smrg}
1547ec681f3Smrg
1557ec681f3Smrg#else /* __cplusplus */
1567ec681f3Smrg
1577ec681f3Smrgtypedef struct log_time {
1587ec681f3Smrg  uint32_t tv_sec;
1597ec681f3Smrg  uint32_t tv_nsec;
1607ec681f3Smrg} __attribute__((__packed__)) log_time;
1617ec681f3Smrg
1627ec681f3Smrg#endif /* __cplusplus */
163