00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "simulator.h"
00020 #include "realtime-simulator-impl.h"
00021 #include "wall-clock-synchronizer.h"
00022 #include "scheduler.h"
00023 #include "event-impl.h"
00024 #include "synchronizer.h"
00025
00026 #include "ns3/ptr.h"
00027 #include "ns3/pointer.h"
00028 #include "ns3/assert.h"
00029 #include "ns3/fatal-error.h"
00030 #include "ns3/log.h"
00031 #include "ns3/system-mutex.h"
00032 #include "ns3/boolean.h"
00033 #include "ns3/enum.h"
00034
00035
00036 #include <math.h>
00037
00038 NS_LOG_COMPONENT_DEFINE ("RealtimeSimulatorImpl");
00039
00040 namespace ns3 {
00041
00042 NS_OBJECT_ENSURE_REGISTERED (RealtimeSimulatorImpl);
00043
00044 TypeId
00045 RealtimeSimulatorImpl::GetTypeId (void)
00046 {
00047 static TypeId tid = TypeId ("ns3::RealtimeSimulatorImpl")
00048 .SetParent<Object> ()
00049 .AddConstructor<RealtimeSimulatorImpl> ()
00050 .AddAttribute ("SynchronizationMode",
00051 "What to do if the simulation cannot keep up with real time.",
00052 EnumValue (SYNC_BEST_EFFORT),
00053 MakeEnumAccessor (&RealtimeSimulatorImpl::SetSynchronizationMode),
00054 MakeEnumChecker (SYNC_BEST_EFFORT, "BestEffort",
00055 SYNC_HARD_LIMIT, "HardLimit"))
00056 .AddAttribute ("HardLimit",
00057 "Maximum acceptable real-time jitter (used in conjunction with SynchronizationMode=HardLimit)",
00058 TimeValue (Seconds (0.1)),
00059 MakeTimeAccessor (&RealtimeSimulatorImpl::m_hardLimit),
00060 MakeTimeChecker ())
00061 ;
00062 return tid;
00063 }
00064
00065
00066 RealtimeSimulatorImpl::RealtimeSimulatorImpl ()
00067 {
00068 NS_LOG_FUNCTION_NOARGS ();
00069
00070 m_stop = false;
00071 m_running = false;
00072
00073
00074
00075
00076 m_uid = 4;
00077
00078 m_currentUid = 0;
00079 m_currentTs = 0;
00080 m_unscheduledEvents = 0;
00081
00082
00083
00084 m_synchronizer = CreateObject<WallClockSynchronizer> ();
00085 }
00086
00087 RealtimeSimulatorImpl::~RealtimeSimulatorImpl ()
00088 {
00089 NS_LOG_FUNCTION_NOARGS ();
00090 while (m_events->IsEmpty () == false)
00091 {
00092 Scheduler::Event next = m_events->RemoveNext ();
00093 next.impl->Unref ();
00094 }
00095 m_events = 0;
00096 m_synchronizer = 0;
00097 }
00098
00099 void
00100 RealtimeSimulatorImpl::Destroy ()
00101 {
00102 NS_LOG_FUNCTION_NOARGS ();
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 while (m_destroyEvents.empty () == false)
00113 {
00114 Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
00115 m_destroyEvents.pop_front ();
00116 NS_LOG_LOGIC ("handle destroy " << ev);
00117 if (ev->IsCancelled () == false)
00118 {
00119 ev->Invoke ();
00120 }
00121 }
00122 }
00123
00124 void
00125 RealtimeSimulatorImpl::SetScheduler (Ptr<Scheduler> scheduler)
00126 {
00127 NS_LOG_FUNCTION_NOARGS ();
00128
00129 {
00130 CriticalSection cs (m_mutex);
00131
00132 if (m_events != 0)
00133 {
00134 while (m_events->IsEmpty () == false)
00135 {
00136 Scheduler::Event next = m_events->RemoveNext ();
00137 scheduler->Insert (next);
00138 }
00139 }
00140 m_events = scheduler;
00141 }
00142 }
00143
00144 Ptr<Scheduler>
00145 RealtimeSimulatorImpl::GetScheduler (void) const
00146 {
00147 NS_LOG_FUNCTION_NOARGS ();
00148 return m_events;
00149 }
00150
00151 void
00152 RealtimeSimulatorImpl::ProcessOneEvent (void)
00153 {
00154 NS_LOG_FUNCTION_NOARGS ();
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 for (;;)
00176 {
00177 uint64_t tsDelay = 0;
00178 uint64_t tsNext = 0;
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 uint64_t tsNow;
00193
00194 {
00195 CriticalSection cs (m_mutex);
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 NS_ASSERT_MSG (m_synchronizer->Realtime (),
00207 "RealtimeSimulatorImpl::ProcessOneEvent (): Synchronizer reports not Realtime ()");
00208
00209
00210
00211
00212
00213
00214
00215
00216 tsNow = m_synchronizer->GetCurrentRealtime ();
00217 tsNext = NextTs ();
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 if (tsNext <= tsNow)
00229 {
00230 tsDelay = 0;
00231 }
00232 else
00233 {
00234 tsDelay = tsNext - tsNow;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244 m_synchronizer->SetCondition (false);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 if (m_synchronizer->Synchronize (tsNow, tsDelay))
00282 {
00283 NS_LOG_LOGIC ("Interrupted ...");
00284 break;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 Scheduler::Event next;
00304
00305 {
00306 CriticalSection cs (m_mutex);
00307
00308
00309
00310
00311
00312
00313
00314 NS_ASSERT_MSG (m_events->IsEmpty () == false,
00315 "RealtimeSimulatorImpl::ProcessOneEvent(): event queue is empty");
00316 next = m_events->RemoveNext ();
00317 --m_unscheduledEvents;
00318
00319
00320
00321
00322
00323
00324 NS_ASSERT_MSG (next.key.m_ts >= m_currentTs,
00325 "RealtimeSimulatorImpl::ProcessOneEvent(): "
00326 "next.GetTs() earlier than m_currentTs (list order error)");
00327 NS_LOG_LOGIC ("handle " << next.key.m_ts);
00328
00329
00330
00331
00332
00333
00334 m_currentTs = next.key.m_ts;
00335 m_currentUid = next.key.m_uid;
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 if (m_synchronizationMode == SYNC_HARD_LIMIT)
00347 {
00348 uint64_t tsFinal = m_synchronizer->GetCurrentRealtime ();
00349 uint64_t tsJitter;
00350
00351 if (tsFinal >= m_currentTs)
00352 {
00353 tsJitter = tsFinal - m_currentTs;
00354 }
00355 else
00356 {
00357 tsJitter = m_currentTs - tsFinal;
00358 }
00359
00360 if (tsJitter > static_cast<uint64_t>(m_hardLimit.GetTimeStep ()))
00361 {
00362 NS_FATAL_ERROR ("RealtimeSimulatorImpl::ProcessOneEvent (): "
00363 "Hard real-time limit exceeded (jitter = " << tsJitter << ")");
00364 }
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373 EventImpl *event = next.impl;
00374 m_synchronizer->EventStart ();
00375 event->Invoke ();
00376 m_synchronizer->EventEnd ();
00377 event->Unref ();
00378 }
00379
00380 bool
00381 RealtimeSimulatorImpl::IsFinished (void) const
00382 {
00383 NS_LOG_FUNCTION_NOARGS ();
00384 bool rc;
00385 {
00386 CriticalSection cs (m_mutex);
00387 rc = m_events->IsEmpty ();
00388 }
00389
00390 return rc;
00391 }
00392
00393
00394
00395
00396 uint64_t
00397 RealtimeSimulatorImpl::NextTs (void) const
00398 {
00399 NS_LOG_FUNCTION_NOARGS ();
00400 NS_ASSERT_MSG (m_events->IsEmpty () == false,
00401 "RealtimeSimulatorImpl::NextTs(): event queue is empty");
00402 Scheduler::Event ev = m_events->PeekNext ();
00403 return ev.key.m_ts;
00404 }
00405
00406
00407
00408
00409 Time
00410 RealtimeSimulatorImpl::Next (void) const
00411 {
00412 NS_LOG_FUNCTION_NOARGS ();
00413 return TimeStep (NextTs ());
00414 }
00415
00416 void
00417 RealtimeSimulatorImpl::Run (void)
00418 {
00419 NS_LOG_FUNCTION_NOARGS ();
00420
00421 NS_ASSERT_MSG (m_running == false,
00422 "RealtimeSimulatorImpl::Run(): Simulator already running");
00423
00424 m_stop = false;
00425 m_running = true;
00426 m_synchronizer->SetOrigin (m_currentTs);
00427
00428 for (;;)
00429 {
00430 bool done = false;
00431
00432 {
00433 CriticalSection cs (m_mutex);
00434
00435
00436
00437
00438
00439
00440 if (m_stop || m_events->IsEmpty ())
00441 {
00442 done = true;
00443 }
00444 }
00445
00446 if (done)
00447 {
00448 break;
00449 }
00450
00451 ProcessOneEvent ();
00452 }
00453
00454
00455
00456
00457
00458 {
00459 CriticalSection cs (m_mutex);
00460
00461 NS_ASSERT_MSG (m_events->IsEmpty () == false || m_unscheduledEvents == 0,
00462 "RealtimeSimulatorImpl::Run(): Empty queue and unprocessed events");
00463 }
00464
00465 m_running = false;
00466 }
00467
00468 bool
00469 RealtimeSimulatorImpl::Running (void) const
00470 {
00471 NS_LOG_FUNCTION_NOARGS ();
00472 return m_running;
00473 }
00474
00475 bool
00476 RealtimeSimulatorImpl::Realtime (void) const
00477 {
00478 NS_LOG_FUNCTION_NOARGS ();
00479 return m_synchronizer->Realtime ();
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 void
00495 RealtimeSimulatorImpl::RunOneEvent (void)
00496 {
00497 NS_LOG_FUNCTION_NOARGS ();
00498
00499 NS_ASSERT_MSG (m_running == false,
00500 "RealtimeSimulatorImpl::RunOneEvent(): An internal simulator event loop is running");
00501
00502 EventImpl *event = 0;
00503
00504
00505
00506
00507
00508 {
00509 CriticalSection cs (m_mutex);
00510
00511 Scheduler::Event next = m_events->RemoveNext ();
00512
00513 NS_ASSERT (next.key.m_ts >= m_currentTs);
00514 --m_unscheduledEvents;
00515
00516 NS_LOG_LOGIC ("handle " << next.key.m_ts);
00517 m_currentTs = next.key.m_ts;
00518 m_currentUid = next.key.m_ts;
00519 event = next.impl;
00520 }
00521 event->Invoke ();
00522 event->Unref ();
00523 }
00524
00525 void
00526 RealtimeSimulatorImpl::Stop (void)
00527 {
00528 NS_LOG_FUNCTION_NOARGS ();
00529 m_stop = true;
00530 }
00531
00532
00533
00534
00535 EventId
00536 RealtimeSimulatorImpl::Schedule (Time const &time, EventImpl *impl)
00537 {
00538 NS_LOG_FUNCTION (time << impl);
00539
00540 Scheduler::Event ev;
00541 {
00542 CriticalSection cs (m_mutex);
00543
00544
00545
00546
00547
00548
00549 Time tAbsolute = Simulator::Now () + time;
00550 NS_ASSERT_MSG (tAbsolute.IsPositive (), "RealtimeSimulatorImpl::Schedule(): Negative time");
00551 NS_ASSERT_MSG (tAbsolute >= TimeStep (m_currentTs), "RealtimeSimulatorImpl::Schedule(): time < m_currentTs");
00552 ev.impl = impl;
00553 ev.key.m_ts = (uint64_t) tAbsolute.GetTimeStep ();
00554 ev.key.m_uid = m_uid;
00555 m_uid++;
00556 ++m_unscheduledEvents;
00557 m_events->Insert (ev);
00558 m_synchronizer->Signal ();
00559 }
00560
00561 return EventId (impl, ev.key.m_ts, ev.key.m_uid);
00562 }
00563
00564 EventId
00565 RealtimeSimulatorImpl::ScheduleNow (EventImpl *impl)
00566 {
00567 NS_LOG_FUNCTION_NOARGS ();
00568 Scheduler::Event ev;
00569 {
00570 CriticalSection cs (m_mutex);
00571
00572 ev.impl = impl;
00573 ev.key.m_ts = m_currentTs;
00574 ev.key.m_uid = m_uid;
00575 m_uid++;
00576 ++m_unscheduledEvents;
00577 m_events->Insert (ev);
00578 m_synchronizer->Signal ();
00579 }
00580
00581 return EventId (impl, ev.key.m_ts, ev.key.m_uid);
00582 }
00583
00584 Time
00585 RealtimeSimulatorImpl::Now (void) const
00586 {
00587 return TimeStep (m_currentTs);
00588 }
00589
00590
00591
00592
00593 void
00594 RealtimeSimulatorImpl::ScheduleRealtime (Time const &time, EventImpl *impl)
00595 {
00596 NS_LOG_FUNCTION (time << impl);
00597
00598
00599 {
00600 CriticalSection cs (m_mutex);
00601
00602 uint64_t ts = m_synchronizer->GetCurrentRealtime () + time.GetTimeStep ();
00603 NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs");
00604 Scheduler::Event ev;
00605 ev.impl = impl;
00606 ev.key.m_ts = ts;
00607 ev.key.m_uid = m_uid;
00608 m_uid++;
00609 ++m_unscheduledEvents;
00610 m_events->Insert (ev);
00611 m_synchronizer->Signal ();
00612 }
00613
00614 }
00615
00616 void
00617 RealtimeSimulatorImpl::ScheduleRealtimeNow (EventImpl *impl)
00618 {
00619 NS_LOG_FUNCTION_NOARGS ();
00620 {
00621 CriticalSection cs (m_mutex);
00622
00623
00624
00625
00626
00627 uint64_t ts = m_running ? m_synchronizer->GetCurrentRealtime () : m_currentTs;
00628 NS_ASSERT_MSG (ts >= m_currentTs, "RealtimeSimulatorImpl::ScheduleRealtimeNow(): schedule for time < m_currentTs");
00629 Scheduler::Event ev;
00630 ev.impl = impl;
00631 ev.key.m_ts = ts;
00632 ev.key.m_uid = m_uid;
00633 m_uid++;
00634 ++m_unscheduledEvents;
00635 m_events->Insert (ev);
00636 m_synchronizer->Signal ();
00637 }
00638 }
00639
00640 Time
00641 RealtimeSimulatorImpl::RealtimeNow (void) const
00642 {
00643 return TimeStep (m_synchronizer->GetCurrentRealtime ());
00644 }
00645
00646 EventId
00647 RealtimeSimulatorImpl::ScheduleDestroy (EventImpl *impl)
00648 {
00649 NS_LOG_FUNCTION_NOARGS ();
00650
00651 EventId id;
00652 {
00653 CriticalSection cs (m_mutex);
00654
00655
00656
00657
00658
00659
00660 id = EventId (Ptr<EventImpl> (impl, false), m_currentTs, 2);
00661 m_destroyEvents.push_back (id);
00662 m_uid++;
00663 }
00664
00665 return id;
00666 }
00667
00668 Time
00669 RealtimeSimulatorImpl::GetDelayLeft (const EventId &id) const
00670 {
00671
00672
00673
00674
00675 if (IsExpired (id))
00676 {
00677 return TimeStep (0);
00678 }
00679
00680 return TimeStep (id.GetTs () - m_currentTs);
00681 }
00682
00683 void
00684 RealtimeSimulatorImpl::Remove (const EventId &id)
00685 {
00686 if (id.GetUid () == 2)
00687 {
00688
00689 for (DestroyEvents::iterator i = m_destroyEvents.begin ();
00690 i != m_destroyEvents.end ();
00691 i++)
00692 {
00693 if (*i == id)
00694 {
00695 m_destroyEvents.erase (i);
00696 break;
00697 }
00698 }
00699 return;
00700 }
00701 if (IsExpired (id))
00702 {
00703 return;
00704 }
00705
00706 {
00707 CriticalSection cs (m_mutex);
00708
00709 Scheduler::Event event;
00710 event.impl = id.PeekEventImpl ();
00711 event.key.m_ts = id.GetTs ();
00712 event.key.m_uid = id.GetUid ();
00713
00714 m_events->Remove (event);
00715 --m_unscheduledEvents;
00716 event.impl->Cancel ();
00717 event.impl->Unref ();
00718 }
00719 }
00720
00721 void
00722 RealtimeSimulatorImpl::Cancel (const EventId &id)
00723 {
00724 if (IsExpired (id) == false)
00725 {
00726 id.PeekEventImpl ()->Cancel ();
00727 }
00728 }
00729
00730 bool
00731 RealtimeSimulatorImpl::IsExpired (const EventId &ev) const
00732 {
00733 if (ev.GetUid () == 2)
00734 {
00735
00736 for (DestroyEvents::const_iterator i = m_destroyEvents.begin ();
00737 i != m_destroyEvents.end (); i++)
00738 {
00739 if (*i == ev)
00740 {
00741 return false;
00742 }
00743 }
00744 return true;
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 if (ev.PeekEventImpl () == 0 ||
00756 ev.GetTs () < m_currentTs ||
00757 (ev.GetTs () == m_currentTs && ev.GetUid () <= m_currentUid) ||
00758 ev.PeekEventImpl ()->IsCancelled ())
00759 {
00760 return true;
00761 }
00762 else
00763 {
00764 return false;
00765 }
00766 }
00767
00768 Time
00769 RealtimeSimulatorImpl::GetMaximumSimulationTime (void) const
00770 {
00771
00772
00773 return TimeStep (0x7fffffffffffffffLL);
00774 }
00775
00776 void
00777 RealtimeSimulatorImpl::SetSynchronizationMode (enum SynchronizationMode mode)
00778 {
00779 NS_LOG_FUNCTION (mode);
00780 m_synchronizationMode = mode;
00781 }
00782
00783 RealtimeSimulatorImpl::SynchronizationMode
00784 RealtimeSimulatorImpl::GetSynchronizationMode (void) const
00785 {
00786 NS_LOG_FUNCTION_NOARGS ();
00787 return m_synchronizationMode;
00788 }
00789
00790 void
00791 RealtimeSimulatorImpl::SetHardLimit (Time limit)
00792 {
00793 NS_LOG_FUNCTION (limit);
00794 m_hardLimit = limit;
00795 }
00796
00797 Time
00798 RealtimeSimulatorImpl::GetHardLimit (void) const
00799 {
00800 NS_LOG_FUNCTION_NOARGS ();
00801 return m_hardLimit;
00802 }
00803
00804 };