/src/core/model/unix-system-wall-clock-ms.cc

https://github.com/nyuwireless-unipd/ns3-mmwave · C++ · 194 lines · 106 code · 26 blank · 62 comment · 1 complexity · 14e5c6e4466874f69b5964506d276a42 MD5 · raw file

  1. /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
  2. /*
  3. * Copyright (c) 2005 INRIA
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation;
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
  19. */
  20. #include "system-wall-clock-ms.h"
  21. #include "abort.h"
  22. #include "log.h"
  23. #include <sys/times.h>
  24. #include <unistd.h>
  25. /**
  26. * \file
  27. * \ingroup system
  28. * ns3::SystemWallClockMs and ns3::SystemWallClockMsPrivate implementation.
  29. */
  30. namespace ns3 {
  31. NS_LOG_COMPONENT_DEFINE ("SystemWallClockMs");
  32. /**
  33. * \ingroup system
  34. * \brief System-dependent implementation for SystemWallClockMs
  35. */
  36. class SystemWallClockMsPrivate
  37. {
  38. public:
  39. /** \copydoc SystemWallClockMs::Start() */
  40. void Start (void);
  41. /** \copydoc SystemWallClockMs::End() */
  42. int64_t End (void);
  43. /** \copydoc SystemWallClockMs::GetElapsedReal() */
  44. int64_t GetElapsedReal (void) const;
  45. /** \copydoc SystemWallClockMs::GetElapsedUser() */
  46. int64_t GetElapsedUser (void) const;
  47. /** \copydoc SystemWallClockMs::GetElapsedSystem() */
  48. int64_t GetElapsedSystem (void) const;
  49. private:
  50. struct tms m_startTimes; //!< The native time structure.
  51. clock_t m_startTime; //!< Native real time.
  52. int64_t m_elapsedReal; //!< Elapsed real time, in ms.
  53. int64_t m_elapsedUser; //!< Elapsed user time, in ms.
  54. int64_t m_elapsedSystem; //!< Elapsed system time, in ms.
  55. };
  56. void
  57. SystemWallClockMsPrivate::Start (void)
  58. {
  59. NS_LOG_FUNCTION (this);
  60. m_startTime = times (&m_startTimes);
  61. }
  62. int64_t
  63. SystemWallClockMsPrivate::End (void)
  64. {
  65. //
  66. // We need to return the number of milliseconds that have elapsed in some
  67. // reasonably portable way. The underlying function that we will use returns
  68. // a number of elapsed ticks. We can look up the number of ticks per second
  69. // from the system configuration.
  70. //
  71. // Conceptually, we need to find the number of elapsed clock ticks and then
  72. // multiply the result by the milliseconds per clock tick (or divide by clock
  73. // ticks per millisecond). Integer dividing by clock ticks per millisecond
  74. // is bad since this number is fractional on most machines and would result
  75. // in divide by zero errors due to integer rounding.
  76. //
  77. // Multiplying by milliseconds per clock tick works up to a clock resolution
  78. // of 1000 ticks per second. If we go past this point, we begin to get zero
  79. // elapsed times when millisecondsPerTick becomes fractional and another
  80. // rounding error appears.
  81. //
  82. // So rounding errors using integers can bite you from both direction. Since
  83. // all of our targets have math coprocessors, why not just use doubles
  84. // internally? Works fine, lasts a long time.
  85. //
  86. // If millisecondsPerTick becomes fractional, and an elapsed time greater than
  87. // a milliscond is measured, the function will work as expected. If an elapsed
  88. // time is measured that turns out to be less than a millisecond, we'll just
  89. // return zero which would, I think, also will be expected.
  90. //
  91. NS_LOG_FUNCTION (this);
  92. static int64_t ticksPerSecond = sysconf (_SC_CLK_TCK);
  93. static double millisecondsPerTick = 1000. / ticksPerSecond;
  94. //
  95. // If sysconf () fails, we have no idea how to do the required conversion to ms.
  96. //
  97. NS_ABORT_MSG_IF (ticksPerSecond == -1, "SystemWallClockMsPrivate(): Cannot sysconf (_SC_CLK_TCK)");
  98. struct tms endTimes;
  99. clock_t endTime = times (&endTimes);
  100. double tmp;
  101. tmp = static_cast<double> (endTime - m_startTime) * millisecondsPerTick;
  102. m_elapsedReal = static_cast<int64_t> (tmp);
  103. tmp = static_cast<double> (endTimes.tms_utime - m_startTimes.tms_utime) * millisecondsPerTick;
  104. m_elapsedUser = static_cast<int64_t> (tmp);
  105. tmp = static_cast<double> (endTimes.tms_stime - m_startTimes.tms_stime) * millisecondsPerTick;
  106. m_elapsedSystem = static_cast<int64_t> (tmp);
  107. return m_elapsedReal;
  108. }
  109. int64_t
  110. SystemWallClockMsPrivate::GetElapsedReal (void) const
  111. {
  112. NS_LOG_FUNCTION (this);
  113. return m_elapsedReal;
  114. }
  115. int64_t
  116. SystemWallClockMsPrivate::GetElapsedUser (void) const
  117. {
  118. NS_LOG_FUNCTION (this);
  119. return m_elapsedUser;
  120. }
  121. int64_t
  122. SystemWallClockMsPrivate::GetElapsedSystem (void) const
  123. {
  124. NS_LOG_FUNCTION (this);
  125. return m_elapsedSystem;
  126. }
  127. SystemWallClockMs::SystemWallClockMs ()
  128. : m_priv (new SystemWallClockMsPrivate ())
  129. {
  130. NS_LOG_FUNCTION (this);
  131. }
  132. SystemWallClockMs::~SystemWallClockMs ()
  133. {
  134. NS_LOG_FUNCTION (this);
  135. delete m_priv;
  136. m_priv = 0;
  137. }
  138. void
  139. SystemWallClockMs::Start (void)
  140. {
  141. NS_LOG_FUNCTION (this);
  142. m_priv->Start ();
  143. }
  144. int64_t
  145. SystemWallClockMs::End (void)
  146. {
  147. NS_LOG_FUNCTION (this);
  148. return m_priv->End ();
  149. }
  150. int64_t
  151. SystemWallClockMs::GetElapsedReal (void) const
  152. {
  153. NS_LOG_FUNCTION (this);
  154. return m_priv->GetElapsedReal ();
  155. }
  156. int64_t
  157. SystemWallClockMs::GetElapsedUser (void) const
  158. {
  159. NS_LOG_FUNCTION (this);
  160. return m_priv->GetElapsedUser ();
  161. }
  162. int64_t
  163. SystemWallClockMs::GetElapsedSystem (void) const
  164. {
  165. NS_LOG_FUNCTION (this);
  166. return m_priv->GetElapsedSystem ();
  167. }
  168. } // namespace ns3