stats: Add support for hierarchical stats
[gem5.git] / src / base / time.cc
index 76ba355b78617253ae07ceb21088a6166187ac8e..80bc546e1c42839fee3e4f91d1e0c2c83a9a1795 100644 (file)
  * Authors: Nathan Binkert
  */
 
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
-#include <iostream>
-#include <string>
-
 #include "base/time.hh"
 
-using namespace std;
-
-struct _timeval
-{
-    timeval tv;
-};
-
-double
-convert(const timeval &tv)
-{
-    return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
-}
-
-Time::Time(bool set_now)
-{
-    time = new _timeval;
-    if (set_now)
-        set();
-}
-
-Time::Time(const timeval &val)
-{
-    time = new _timeval;
-    set(val);
-}
-
-Time::Time(const Time &val)
-{
-    time = new _timeval;
-    set(val.get());
-}
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <sstream>
 
-Time::~Time()
-{
-    delete time;
-}
+#include "base/logging.hh"
+#include "config/use_posix_clock.hh"
+#include "sim/core.hh"
+#include "sim/serialize.hh"
 
-const timeval &
-Time::get() const
-{
-    return time->tv;
-}
+using namespace std;
 
 void
-Time::set()
+Time::_set(bool monotonic)
 {
-    ::gettimeofday(&time->tv, NULL);
+#if USE_POSIX_CLOCK
+    ::clock_gettime(monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME, &_time);
+#else
+    timeval tv;
+    ::gettimeofday(&tv, NULL);
+    operator=(tv);
+#endif
 }
 
 void
-Time::set(const timeval &tv)
+Time::setTick(Tick ticks)
 {
-    memcpy(&time->tv, &tv, sizeof(timeval));
+    uint64_t secs = ticks / SimClock::Frequency;
+    ticks -= secs * SimClock::Frequency;
+    uint64_t nsecs = static_cast<uint64_t>(ticks * SimClock::Float::GHz);
+    set(secs, nsecs);
 }
 
-double
-Time::operator()() const
+Tick
+Time::getTick() const
 {
-    return convert(get());
+    return sec() * SimClock::Frequency +
+        static_cast<uint64_t>(nsec() * SimClock::Float::ns);
 }
 
 string
-Time::date(string format) const
+Time::date(const string &format) const
 {
-    const timeval &tv = get();
-    time_t sec = tv.tv_sec;
+    time_t sec = this->sec();
     char buf[256];
 
     if (format.empty()) {
 #ifdef __SUNPRO_CC
-        ctime_r(&sec, buf, 256);
+        ctime_r(&sec, buf, sizeof(buf));
 #else
         ctime_r(&sec, buf);
 #endif
@@ -119,19 +91,95 @@ Time::date(string format) const
     return buf;
 }
 
-ostream &
-operator<<(ostream &out, const Time &start)
+string
+Time::time() const
 {
-    out << start.date();
-    return out;
+    double time = double(*this);
+    double secs = fmod(time, 60.0);
+    double all_mins = floor(time / 60.0);
+    double mins = fmod(all_mins, 60.0);
+    double hours = floor(all_mins / 60.0);
+
+    stringstream str;
+
+    if (hours > 0.0) {
+        if (hours < 10.0)
+            str << '0';
+        str << hours << ':';
+    }
+
+    if (mins > 0.0) {
+        if (mins < 10.0)
+            str << '0';
+        str << mins << ':';
+    }
+
+    if (secs < 10.0 && !str.str().empty())
+        str << '0';
+    str << secs;
+
+    return str.str();
 }
 
-Time
-operator-(const Time &l, const Time &r)
+void
+Time::serialize(const std::string &base, CheckpointOut &cp) const
 {
-    timeval tv;
-    timersub(&l.get(), &r.get(), &tv);
-    return tv;
+    paramOut(cp, base + ".sec", sec());
+    paramOut(cp, base + ".nsec", nsec());
+}
+
+void
+Time::unserialize(const std::string &base, CheckpointIn &cp)
+{
+    time_t secs;
+    time_t nsecs;
+    paramIn(cp, base + ".sec", secs);
+    paramIn(cp, base + ".nsec", nsecs);
+    sec(secs);
+    nsec(nsecs);
+}
+
+void
+sleep(const Time &time)
+{
+    timespec ts = time;
+
+#if USE_POSIX_CLOCK
+    clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+#else
+    nanosleep(&ts, NULL);
+#endif
+}
+
+time_t
+mkutctime(struct tm *time)
+{
+    // get the current timezone
+    char *tz = getenv("TZ");
+
+    // copy the string as the pointer gets invalidated when updating
+    // the environment
+    if (tz) {
+        tz = strdup(tz);
+        if (!tz) {
+            fatal("Failed to reserve memory for UTC time conversion\n");
+        }
+    }
+
+    // change to UTC and get the time
+    setenv("TZ", "", 1);
+    tzset();
+    time_t ret = mktime(time);
+
+    // restore the timezone again
+    if (tz) {
+        setenv("TZ", tz, 1);
+        free(tz);
+    } else {
+        unsetenv("TZ");
+    }
+    tzset();
+
+    return ret;
 }
 
-const Time Time::start(true);