A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wall-clock-synchronizer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 University of Washington
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18#ifndef WALL_CLOCK_CLOCK_SYNCHRONIZER_H
19#define WALL_CLOCK_CLOCK_SYNCHRONIZER_H
20
21#include "synchronizer.h"
22
23#include <condition_variable>
24#include <mutex>
25
26/**
27 * @file
28 * @ingroup realtime
29 * ns3::WallClockSynchronizer declaration.
30 */
31
32namespace ns3
33{
34
35/**
36 * @ingroup realtime
37 * @brief Class used for synchronizing the simulation events to a real-time
38 * "wall clock" using Posix clock functions.
39 *
40 * This synchronizer is used as part of the RealtimeSimulatorImpl. It is
41 * typically not explicitly enabled by users but instead is implicitly
42 * enabled when the simulator implementation type is set to real-time; e.g.:
43 *
44 * @code
45 * GlobalValue::Bind ("SimulatorImplementationType",
46 * StringValue ("ns3::RealtimeSimulatorImpl"));
47 * @endcode
48 *
49 * before calling any simulator functions.
50 *
51 * There are a couple of more issues at this level. Posix clocks provide
52 * access to several clocks we could use as a wall clock. We don't care about
53 * time in the sense of 04:30 CEST, we care about some piece of hardware that
54 * ticks at some regular period. The most accurate posix clock in this
55 * respect is the @c CLOCK_PROCESS_CPUTIME_ID clock. This is a high-resolution
56 * register in the CPU. For example, on Intel machines this corresponds to
57 * the timestamp counter (TSC) register. The resolution of this counter will
58 * be on the order of nanoseconds.
59 *
60 * Now, just because we can measure time in nanoseconds doesn't mean we can
61 * put our process to sleep to nanosecond resolution. We are eventually going
62 * to use the function @c clock_nanosleep() to sleep until a simulation Time
63 * specified by the caller.
64 *
65 * @todo Add more on jiffies, sleep, processes, etc.
66 *
67 */
69{
70 public:
71 /**
72 * Get the registered TypeId for this class.
73 * @returns The TypeId.
74 */
75 static TypeId GetTypeId();
76
77 /** Constructor. */
79 /** Destructor. */
80 ~WallClockSynchronizer() override;
81
82 /** Conversion constant between &mu;s and ns. */
83 static const uint64_t US_PER_NS = (uint64_t)1000;
84 /** Conversion constant between &mu;s and seconds. */
85 static const uint64_t US_PER_SEC = (uint64_t)1000000;
86 /** Conversion constant between ns and s. */
87 static const uint64_t NS_PER_SEC = (uint64_t)1000000000;
88
89 protected:
90 /**
91 * @brief Do a busy-wait until the normalized realtime equals the argument
92 * or the condition variable becomes @c true.
93
94 * The condition becomes @c true if an outside entity (a network device
95 * receives a packet), sets the condition and signals the scheduler
96 * it needs to re-evaluate.
97 *
98 * @param [in] ns The target normalized real time we should wait for.
99 * @returns @c true if we reached the target time,
100 * @c false if we returned because the condition was set.
101 */
102 bool SpinWait(uint64_t ns);
103 /**
104 * Put our process to sleep for some number of nanoseconds.
105 *
106 * Typically this will be some time equal to an integral number of jiffies.
107 * We will usually follow a call to SleepWait with a call to SpinWait
108 * to get the kind of accuracy we want.
109 *
110 * We have to have some mechanism to wake up this sleep in case an external
111 * event happens that causes a Schedule event in the simulator. This newly
112 * scheduled event might be before the time we are waiting until, so we have
113 * to break out of both the SleepWait and the following SpinWait to go back
114 * and reschedule/resynchronize taking the new event into account. The
115 * condition we have saved in m_condition, along with the condition variable
116 * m_conditionVariable take care of this for us.
117 *
118 * This call will return if the timeout expires OR if the condition is
119 * set @c true by a call to SetCondition (true) followed by a call to
120 * Signal(). In either case, we are done waiting. If the timeout happened,
121 * we return @c true; if a Signal happened we return @c false.
122 *
123 * @param [in] ns The target normalized real time we should wait for.
124 * @returns @c true if we reached the target time,
125 * @c false if we returned because the condition was set.
126 */
127 bool SleepWait(uint64_t ns);
128
129 // Inherited from Synchronizer
130 void DoSetOrigin(uint64_t ns) override;
131 bool DoRealtime() override;
132 uint64_t DoGetCurrentRealtime() override;
133 bool DoSynchronize(uint64_t nsCurrent, uint64_t nsDelay) override;
134 void DoSignal() override;
135 void DoSetCondition(bool cond) override;
136 int64_t DoGetDrift(uint64_t ns) override;
137 void DoEventStart() override;
138 uint64_t DoEventEnd() override;
139
140 /**
141 * @brief Compute a correction to the nominal delay to account for
142 * realtime drift since the last DoSynchronize.
143 *
144 * @param [in] nsNow The current simulation time (in nanosecond units).
145 * @param [in] nsDelay The simulation time we need to wait for (normalized to
146 * nanosecond units).
147 * @returns The corrected delay.
148 */
149 uint64_t DriftCorrect(uint64_t nsNow, uint64_t nsDelay);
150
151 /**
152 * @brief Get the current absolute real time (in ns since the epoch).
153 *
154 * @returns The current real time, in ns.
155 */
156 uint64_t GetRealtime();
157 /**
158 * @brief Get the current normalized real time, in ns.
159 *
160 * @returns The current normalized real time, in ns.
161 */
162 uint64_t GetNormalizedRealtime();
163
164 /** Size of the system clock tick, as reported by @c clock_getres, in ns. */
165 uint64_t m_jiffy;
166 /** Time recorded by DoEventStart. */
168
169 /** Condition variable for thread synchronizer. */
170 std::condition_variable m_conditionVariable;
171 /** Mutex controlling access to the condition variable. */
172 std::mutex m_mutex;
173 /** The condition state. */
175};
176
177} // namespace ns3
178
179#endif /* WALL_CLOCK_SYNCHRONIZER_H */
Base class used for synchronizing the simulation events to some real time "wall clock....
Definition: synchronizer.h:53
a unique identifier for an interface.
Definition: type-id.h:59
Class used for synchronizing the simulation events to a real-time "wall clock" using Posix clock func...
uint64_t GetNormalizedRealtime()
Get the current normalized real time, in ns.
static const uint64_t NS_PER_SEC
Conversion constant between ns and s.
int64_t DoGetDrift(uint64_t ns) override
Get the drift between the real time clock used to synchronize the simulation and the current simulati...
bool SleepWait(uint64_t ns)
Put our process to sleep for some number of nanoseconds.
void DoEventStart() override
Record the normalized real time at which the current event is starting execution.
bool DoSynchronize(uint64_t nsCurrent, uint64_t nsDelay) override
Wait until the real time is in sync with the specified simulation time.
void DoSetOrigin(uint64_t ns) override
Establish a correspondence between a simulation time and a wall-clock (real) time.
uint64_t m_jiffy
Size of the system clock tick, as reported by clock_getres, in ns.
void DoSignal() override
Tell a possible simulator thread waiting in the DoSynchronize method that an event has happened which...
uint64_t DoGetCurrentRealtime() override
Retrieve the value of the origin of the underlying normalized wall clock time in Time resolution unit...
static TypeId GetTypeId()
Get the registered TypeId for this class.
bool m_condition
The condition state.
static const uint64_t US_PER_NS
Conversion constant between μs and ns.
void DoSetCondition(bool cond) override
Set the condition variable to tell a possible simulator thread waiting in the Synchronize method that...
uint64_t m_nsEventStart
Time recorded by DoEventStart.
bool SpinWait(uint64_t ns)
Do a busy-wait until the normalized realtime equals the argument or the condition variable becomes tr...
static const uint64_t US_PER_SEC
Conversion constant between μs and seconds.
std::condition_variable m_conditionVariable
Condition variable for thread synchronizer.
uint64_t GetRealtime()
Get the current absolute real time (in ns since the epoch).
~WallClockSynchronizer() override
Destructor.
bool DoRealtime() override
Return true if this synchronizer is actually synchronizing to a realtime clock.
uint64_t DoEventEnd() override
Return the amount of real time elapsed since the last call to EventStart.
uint64_t DriftCorrect(uint64_t nsNow, uint64_t nsDelay)
Compute a correction to the nominal delay to account for realtime drift since the last DoSynchronize.
std::mutex m_mutex
Mutex controlling access to the condition variable.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::Synchronizer declaration.