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 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#ifndef WALL_CLOCK_CLOCK_SYNCHRONIZER_H
8#define WALL_CLOCK_CLOCK_SYNCHRONIZER_H
9
10#include "synchronizer.h"
11
12#include <condition_variable>
13#include <mutex>
14
15/**
16 * @file
17 * @ingroup realtime
18 * ns3::WallClockSynchronizer declaration.
19 */
20
21namespace ns3
22{
23
24/**
25 * @ingroup realtime
26 * @brief Class used for synchronizing the simulation events to a real-time
27 * "wall clock" using Posix clock functions.
28 *
29 * This synchronizer is used as part of the RealtimeSimulatorImpl. It is
30 * typically not explicitly enabled by users but instead is implicitly
31 * enabled when the simulator implementation type is set to real-time; e.g.:
32 *
33 * @code
34 * GlobalValue::Bind ("SimulatorImplementationType",
35 * StringValue ("ns3::RealtimeSimulatorImpl"));
36 * @endcode
37 *
38 * before calling any simulator functions.
39 *
40 * There are a couple of more issues at this level. Posix clocks provide
41 * access to several clocks we could use as a wall clock. We don't care about
42 * time in the sense of 04:30 CEST, we care about some piece of hardware that
43 * ticks at some regular period. The most accurate posix clock in this
44 * respect is the @c CLOCK_PROCESS_CPUTIME_ID clock. This is a high-resolution
45 * register in the CPU. For example, on Intel machines this corresponds to
46 * the timestamp counter (TSC) register. The resolution of this counter will
47 * be on the order of nanoseconds.
48 *
49 * Now, just because we can measure time in nanoseconds doesn't mean we can
50 * put our process to sleep to nanosecond resolution. We are eventually going
51 * to use the function @c clock_nanosleep() to sleep until a simulation Time
52 * specified by the caller.
53 *
54 * @todo Add more on jiffies, sleep, processes, etc.
55 *
56 */
58{
59 public:
60 /**
61 * Get the registered TypeId for this class.
62 * @returns The TypeId.
63 */
64 static TypeId GetTypeId();
65
66 /** Constructor. */
68 /** Destructor. */
69 ~WallClockSynchronizer() override;
70
71 /** Conversion constant between &mu;s and ns. */
72 static const uint64_t US_PER_NS = (uint64_t)1000;
73 /** Conversion constant between &mu;s and seconds. */
74 static const uint64_t US_PER_SEC = (uint64_t)1000000;
75 /** Conversion constant between ns and s. */
76 static const uint64_t NS_PER_SEC = (uint64_t)1000000000;
77
78 protected:
79 /**
80 * @brief Do a busy-wait until the normalized realtime equals the argument
81 * or the condition variable becomes @c true.
82
83 * The condition becomes @c true if an outside entity (a network device
84 * receives a packet), sets the condition and signals the scheduler
85 * it needs to re-evaluate.
86 *
87 * @param [in] ns The target normalized real time we should wait for.
88 * @returns @c true if we reached the target time,
89 * @c false if we returned because the condition was set.
90 */
91 bool SpinWait(uint64_t ns);
92 /**
93 * Put our process to sleep for some number of nanoseconds.
94 *
95 * Typically this will be some time equal to an integral number of jiffies.
96 * We will usually follow a call to SleepWait with a call to SpinWait
97 * to get the kind of accuracy we want.
98 *
99 * We have to have some mechanism to wake up this sleep in case an external
100 * event happens that causes a Schedule event in the simulator. This newly
101 * scheduled event might be before the time we are waiting until, so we have
102 * to break out of both the SleepWait and the following SpinWait to go back
103 * and reschedule/resynchronize taking the new event into account. The
104 * condition we have saved in m_condition, along with the condition variable
105 * m_conditionVariable take care of this for us.
106 *
107 * This call will return if the timeout expires OR if the condition is
108 * set @c true by a call to SetCondition (true) followed by a call to
109 * Signal(). In either case, we are done waiting. If the timeout happened,
110 * we return @c true; if a Signal happened we return @c false.
111 *
112 * @param [in] ns The target normalized real time we should wait for.
113 * @returns @c true if we reached the target time,
114 * @c false if we returned because the condition was set.
115 */
116 bool SleepWait(uint64_t ns);
117
118 // Inherited from Synchronizer
119 void DoSetOrigin(uint64_t ns) override;
120 bool DoRealtime() override;
121 uint64_t DoGetCurrentRealtime() override;
122 bool DoSynchronize(uint64_t nsCurrent, uint64_t nsDelay) override;
123 void DoSignal() override;
124 void DoSetCondition(bool cond) override;
125 int64_t DoGetDrift(uint64_t ns) override;
126 void DoEventStart() override;
127 uint64_t DoEventEnd() override;
128
129 /**
130 * @brief Compute a correction to the nominal delay to account for
131 * realtime drift since the last DoSynchronize.
132 *
133 * @param [in] nsNow The current simulation time (in nanosecond units).
134 * @param [in] nsDelay The simulation time we need to wait for (normalized to
135 * nanosecond units).
136 * @returns The corrected delay.
137 */
138 uint64_t DriftCorrect(uint64_t nsNow, uint64_t nsDelay);
139
140 /**
141 * @brief Get the current absolute real time (in ns since the epoch).
142 *
143 * @returns The current real time, in ns.
144 */
145 uint64_t GetRealtime();
146 /**
147 * @brief Get the current normalized real time, in ns.
148 *
149 * @returns The current normalized real time, in ns.
150 */
151 uint64_t GetNormalizedRealtime();
152
153 /** Size of the system clock tick, as reported by @c clock_getres, in ns. */
154 uint64_t m_jiffy;
155 /** Time recorded by DoEventStart. */
157
158 /** Condition variable for thread synchronizer. */
159 std::condition_variable m_conditionVariable;
160 /** Mutex controlling access to the condition variable. */
161 std::mutex m_mutex;
162 /** The condition state. */
164};
165
166} // namespace ns3
167
168#endif /* WALL_CLOCK_SYNCHRONIZER_H */
Base class used for synchronizing the simulation events to some real time "wall clock....
a unique identifier for an interface.
Definition type-id.h:48
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.