14 * You should have received a copy of the GNU General Public License |
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 |
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 |
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 */ |
17 */ |
18 |
18 |
19 #include <ctime> // for clock_getres |
19 |
20 #include <sys/time.h> |
20 #include <ctime> // clock_t |
|
21 #include <sys/time.h> // gettimeofday |
|
22 // clock_getres: glibc < 2.17, link with librt |
21 |
23 |
22 #include "log.h" |
24 #include "log.h" |
23 #include "system-condition.h" |
25 #include "system-condition.h" |
24 |
26 |
25 #include "wall-clock-synchronizer.h" |
27 #include "wall-clock-synchronizer.h" |
26 |
28 |
|
29 /** |
|
30 * \file |
|
31 * \ingroup realtime |
|
32 * ns3::WallClockSynchronizer implementation. |
|
33 */ |
|
34 |
27 namespace ns3 { |
35 namespace ns3 { |
28 |
36 |
29 NS_LOG_COMPONENT_DEFINE ("WallClockSynchronizer"); |
37 NS_LOG_COMPONENT_DEFINE ("WallClockSynchronizer"); |
|
38 |
|
39 NS_OBJECT_ENSURE_REGISTERED (WallClockSynchronizer); |
|
40 |
|
41 TypeId |
|
42 WallClockSynchronizer::GetTypeId (void) |
|
43 { |
|
44 static TypeId tid = TypeId ("ns3::WallClockSynchronizer") |
|
45 .SetParent<Synchronizer> () |
|
46 ; |
|
47 return tid; |
|
48 } |
30 |
49 |
31 WallClockSynchronizer::WallClockSynchronizer () |
50 WallClockSynchronizer::WallClockSynchronizer () |
32 { |
51 { |
33 NS_LOG_FUNCTION (this); |
52 NS_LOG_FUNCTION (this); |
34 // |
53 // |
293 |
312 |
294 bool |
313 bool |
295 WallClockSynchronizer::SpinWait (uint64_t ns) |
314 WallClockSynchronizer::SpinWait (uint64_t ns) |
296 { |
315 { |
297 NS_LOG_FUNCTION (this << ns); |
316 NS_LOG_FUNCTION (this << ns); |
298 // |
|
299 // Do a busy-wait until the normalized realtime equals the value passed in |
|
300 // or the condition variable becomes true. The condition becomes true if |
|
301 // an outside entity (a network device receives a packet, sets the condition |
|
302 // and signals the scheduler it needs to re-evaluate). |
|
303 // |
|
304 // We just sit here and spin, wasting CPU cycles until we get to the right |
317 // We just sit here and spin, wasting CPU cycles until we get to the right |
305 // time or are told to leave. |
318 // time or are told to leave. |
306 // |
|
307 for (;;) |
319 for (;;) |
308 { |
320 { |
309 if (GetNormalizedRealtime () >= ns) |
321 if (GetNormalizedRealtime () >= ns) |
310 { |
322 { |
311 return true; |
323 return true; |
321 |
333 |
322 bool |
334 bool |
323 WallClockSynchronizer::SleepWait (uint64_t ns) |
335 WallClockSynchronizer::SleepWait (uint64_t ns) |
324 { |
336 { |
325 NS_LOG_FUNCTION (this << ns); |
337 NS_LOG_FUNCTION (this << ns); |
326 // |
|
327 // Put our process to sleep for some number of nanoseconds. Typically this |
|
328 // will be some time equal to an integral number of jiffies. We will usually |
|
329 // follow a call to SleepWait with a call to SpinWait to get the kind of |
|
330 // accuracy we want. |
|
331 // |
|
332 // We have to have some mechanism to wake up this sleep in case an external |
|
333 // event happens that causes a schedule event in the simulator. This newly |
|
334 // scheduled event might be before the time we are waiting until, so we have |
|
335 // to break out of both the SleepWait and the following SpinWait to go back |
|
336 // and reschedule/resynchronize taking the new event into account. The |
|
337 // SystemCondition we have saved in m_condition takes care of this for us. |
|
338 // |
|
339 // This call will return if the timeout expires OR if the condition is |
|
340 // set true by a call to WallClockSynchronizer::SetCondition (true) followed |
|
341 // by a call to WallClockSynchronizer::Signal(). In either case, we are done |
|
342 // waiting. If the timeout happened, we TimedWait returns true; if a Signal |
|
343 // happened, false. |
|
344 // |
|
345 return m_condition.TimedWait (ns); |
338 return m_condition.TimedWait (ns); |
346 } |
339 } |
347 |
340 |
348 uint64_t |
341 uint64_t |
349 WallClockSynchronizer::DriftCorrect (uint64_t nsNow, uint64_t nsDelay) |
342 WallClockSynchronizer::DriftCorrect (uint64_t nsNow, uint64_t nsDelay) |