00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2008 University of Washington 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation; 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 #ifndef WALL_CLOCK_CLOCK_SYNCHRONIZER_H 00020 #define WALL_CLOCK_CLOCK_SYNCHRONIZER_H 00021 00022 #include "ns3/system-condition.h" 00023 #include "synchronizer.h" 00024 00025 namespace ns3 { 00026 00027 /** 00028 * @brief Class used for synchronizing the simulation events to a real-time 00029 * "wall clock" using Posix Clock functions. 00030 * 00031 * Enable this synchronizer using: 00032 * 00033 * DefaultValue::Bind ("Synchronizer", "WallClockSynchronizer"); 00034 * 00035 * before calling any simulator functions. 00036 * 00037 * The simulation clock is maintained as a 64-bit integer in a unit specified 00038 * by the user through the TimeStepPrecision::Set function. This means that 00039 * it is not possible to specify event expiration times with anything better 00040 * than this user-specified accuracy. 00041 * 00042 * There are a couple of more issues at this level. Posix clocks provide 00043 * access to several clocks we could use as a wall clock. We don't care about 00044 * time in the sense of 0430 CEST, we care about some piece of hardware that 00045 * ticks at some regular period. The most accurate posix clock in this 00046 * respect is the CLOCK_PROCESS_CPUTIME_ID clock. This is a high-resolution 00047 * register in the CPU. For example, on Intel machines this corresponds to 00048 * the timestamp counter (TSC) register. The resolution of this counter will 00049 * be on the order of nanoseconds. 00050 * 00051 * Now, just because we can measure time in nanoseconds doesn't mean we can 00052 * put our process to sleep to nanosecond resolution. We are eventualy going 00053 * to use the function clock_nanosleep () to sleep until a simulation Time 00054 * specified by the caller. 00055 * 00056 * MORE ON JIFFIES, SLEEP, PROCESSES, etc., as required 00057 * 00058 * Nanosleep takes a struct timespec as an input so we have to deal with 00059 * conversion between Time and struct timespec here. They are both 00060 * interpreted as elapsed times. 00061 */ 00062 class WallClockSynchronizer : public Synchronizer 00063 { 00064 public: 00065 WallClockSynchronizer (); 00066 virtual ~WallClockSynchronizer (); 00067 00068 static const uint64_t US_PER_NS = (uint64_t)1000; 00069 static const uint64_t US_PER_SEC = (uint64_t)1000000; 00070 static const uint64_t NS_PER_SEC = (uint64_t)1000000000; 00071 00072 protected: 00073 /** 00074 * @brief Return true if this synchronizer is actually synchronizing to a 00075 * realtime clock. The simulator sometimes needs to know this. 00076 * 00077 * @internal 00078 * 00079 * Subclasses are expected to implement this method to tell the outside world 00080 * whether or not they are synchronizing to a realtime clock. 00081 * 00082 * @returns True if locked with realtime, false if not. 00083 */ 00084 virtual bool DoRealtime (void); 00085 00086 /** 00087 * @brief Retrieve the value of the origin of the underlying normalized wall 00088 * clock time in nanosecond units. 00089 * 00090 * @internal 00091 * 00092 * Subclasses are expected to implement this method to do the actual 00093 * real-time-clock-specific work of getting the current time. 00094 * 00095 * @returns The normalized wall clock time (in nanosecond units). 00096 * @see TimeStepPrecision::Get 00097 * @see Synchronizer::SetOrigin 00098 */ 00099 virtual uint64_t DoGetCurrentRealtime (void); 00100 00101 /** 00102 * @brief Establish a correspondence between a simulation time and a 00103 * wall-clock (real) time. 00104 * 00105 * @internal 00106 * 00107 * There are three timelines involved here: the simulation time, the 00108 * (absolute) wall-clock time and the (relative) synchronizer real time. 00109 * Calling this method makes a correspondence between the origin of the 00110 * synchronizer time and the current wall-clock time. 00111 * 00112 * This method is expected to be called at the "instant" before simulation 00113 * begins. At this point, simulation time = 0, and synchronizer time is 00114 * set = 0 in this method. We then associate this time with the current 00115 * value of the real time clock that will be used to actually perform the 00116 * synchronization. 00117 * 00118 * Subclasses are expected to implement this method to do the actual 00119 * real-time-clock-specific work of making the correspondence mentioned above. 00120 * for example, this is where the differences between Time parameters and 00121 * parameters to clock_nanosleep would be dealt with. 00122 * 00123 * @param ns The simulation time we need to use as the origin (normalized to 00124 * nanosecond units). 00125 */ 00126 virtual void DoSetOrigin (uint64_t ns); 00127 00128 /** 00129 * @brief Declaration of method used to retrieve drift between the real time 00130 * clock used to synchronize the simulation and the current simulation time. 00131 * 00132 * @internal 00133 * 00134 * @param ns Simulation timestep from the simulator normalized to nanosecond 00135 * steps. 00136 * @returns Drift in nanosecond units. 00137 * @see TimeStepPrecision::Get 00138 * @see Synchronizer::SetOrigin 00139 * @see Synchronizer::GetDrift 00140 */ 00141 virtual int64_t DoGetDrift (uint64_t ns); 00142 00143 /** 00144 * @brief Wait until the real time is in sync with the specified simulation 00145 * time. 00146 * 00147 * @internal 00148 * 00149 * This is where the real work of synchronization is done. The Time passed 00150 * in as a parameter is the simulation time. The job of Synchronize is to 00151 * translate from simulation time to synchronizer time (in a perfect world 00152 * this is the same time) and then figure out how long in real-time it needs 00153 * to wait until that synchronizer / simulation time comes around. 00154 * 00155 * Subclasses are expected to implement this method to do the actual 00156 * real-time-clock-specific work of waiting (either busy-waiting or sleeping, 00157 * or some combination) until the requested simulation time. 00158 * 00159 * @param ns The simulation time we need to wait for (normalized to nanosecond 00160 * units). 00161 * @see TimeStepPrecision::Get 00162 */ 00163 virtual bool DoSynchronize (uint64_t nsCurrent, uint64_t nsDelay); 00164 virtual void DoSignal (void); 00165 virtual void DoSetCondition (bool cond); 00166 00167 virtual void DoEventStart (void); 00168 virtual uint64_t DoEventEnd (void); 00169 00170 bool SpinWait (uint64_t); 00171 bool SleepWait (uint64_t); 00172 00173 uint64_t DriftCorrect (uint64_t nsNow, uint64_t nsDelay); 00174 00175 uint64_t GetRealtime (void); 00176 uint64_t GetNormalizedRealtime (void); 00177 00178 void NsToTimeval (int64_t ns, struct timeval *tv); 00179 uint64_t TimevalToNs (struct timeval *tv); 00180 00181 void TimevalAdd ( 00182 struct timeval *tv1, 00183 struct timeval *tv2, 00184 struct timeval *result); 00185 00186 uint64_t m_cpuTick; 00187 uint64_t m_realtimeTick; 00188 uint64_t m_jiffy; 00189 uint64_t m_nsEventStart; 00190 00191 SystemCondition m_condition; 00192 }; 00193 00194 }; // namespace ns3 00195 00196 #endif /* WALL_CLOCK_SYNCHRONIZER_H */