OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
task_monitor.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3  */
4 #include <boost/bind.hpp>
5 #include "logging.h"
6 #include "io/event_manager.h"
7 #include "timer_impl.h"
8 #include "time_util.h"
9 #include "task.h"
10 #include "task_monitor.h"
11 #include "task_tbbkeepawake.h"
12 
13 #define kPollIntervalMultiplier 2
14 #define kInactivityMultiplier 50
15 
17  uint64_t tbb_keepawake_time_msec,
18  uint64_t inactivity_time_msec,
19  uint64_t poll_interval_msec) :
20  scheduler_(scheduler), cancelled_(false), timer_impl_(nullptr),
21  inactivity_time_usec_(inactivity_time_msec * 1000),
22  poll_interval_msec_(poll_interval_msec),
23  tbb_keepawake_time_msec_(tbb_keepawake_time_msec),
24  last_activity_(ClockMonotonicUsec()),
25  last_enqueue_count_(0), last_done_count_(0), poll_count_(0) {
26 }
27 
29 }
30 
32  // Ensure polling interval for monitor is atleast 2*keep-awake-time
33  // It ensures when monitor is invoked, there is some job enqueued
34  // and executed
37  kPollIntervalMultiplier * tbb_keepawake_time_msec_;
38  }
39 
40  // Ensure monitor timeout is atleast 50 * poll-interval
44  poll_interval_msec_ * kInactivityMultiplier * 1000;
45  }
46  return;
47 }
48 
51  return;
52 
53  UpdateTimers();
54  timer_impl_.reset(new TimerImpl(*evm->io_service()));
55  Restart();
56  return;
57 }
58 
60  cancelled_ = true;
61 }
62 
64  boost::system::error_code ec;
65  timer_impl_->expires_from_now(poll_interval_msec_, ec);
66  if (ec) {
67  assert(0);
68  }
69  timer_impl_->async_wait(boost::bind(&TaskMonitor::Run, this,
70  boost::asio::placeholders::error));
71 }
72 
73 bool TaskMonitor::Monitor(uint64_t t, uint64_t enqueue_count,
74  uint64_t done_count) {
75  // New tasks were spawned by TBB. Treat as activity seen
76  if (done_count != last_done_count_) {
77  last_done_count_ = done_count;
78  last_enqueue_count_ = enqueue_count;
79  last_activity_ = t;
80  return true;
81  }
82 
83  // No change in done_count_. Now validate enqueue_count.
84  // Note: We cannot match enqueue_count_ and done_count_. Both these numbers
85  // are updated by multiple threads and are not atomic numbers. As a result
86  // they can potentially be out-of-sync
87  //
88  // If no new tasks are enqueued, then assume there is no more tasks
89  // to run. Treat it similar to seeing activity
90  if (enqueue_count == last_enqueue_count_) {
91  last_done_count_ = done_count;
92  last_enqueue_count_ = enqueue_count;
93  last_activity_ = t;
94  return true;
95  }
96 
97  // Enqueues are happening, check if inactivity exceeds configured time
98  return ((t - last_activity_) <= inactivity_time_usec_);
99 }
100 
101 void TaskMonitor::Run(const boost::system::error_code &ec) {
102  poll_count_++;
103 
104  // ASIO API aborted. Just restart ASIO timer again
105  if (ec && ec.value() == boost::asio::error::operation_aborted) {
106  Restart();
107  return;
108  }
109 
110  if (cancelled_)
111  return;
112 
114  scheduler_->done_count())) {
115  Restart();
116  return;
117  }
118  LOG(ERROR, "!!!! ERROR !!!! Task Monitor failed");
119  assert(0);
120 }
uint64_t last_enqueue_count_
Definition: task_monitor.h:66
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
uint64_t inactivity_time_usec_
Definition: task_monitor.h:58
uint64_t poll_interval_msec_
Definition: task_monitor.h:60
uint64_t last_activity_
Definition: task_monitor.h:64
void Run(const boost::system::error_code &ec)
boost::asio::io_context * io_service()
Definition: event_manager.h:42
void Restart()
Definition: task_monitor.cc:63
uint64_t poll_count_
Definition: task_monitor.h:70
uint64_t last_done_count_
Definition: task_monitor.h:68
void Terminate()
Definition: task_monitor.cc:59
#define kPollIntervalMultiplier
Definition: task_monitor.cc:13
bool cancelled_
Definition: task_monitor.h:53
TaskScheduler * scheduler_
Definition: task_monitor.h:51
void UpdateTimers()
Definition: task_monitor.cc:31
void Start(EventManager *evm)
Definition: task_monitor.cc:49
std::unique_ptr< TimerImpl > timer_impl_
Definition: task_monitor.h:55
#define kInactivityMultiplier
Definition: task_monitor.cc:14
#define LOG(_Level, _Msg)
Definition: logging.h:33
static uint64_t ClockMonotonicUsec()
Definition: time_util.h:29
uint64_t done_count() const
Definition: task.h:286
uint64_t tbb_keepawake_time_msec_
Definition: task_monitor.h:62
TaskMonitor(TaskScheduler *scheduler, uint64_t tbb_keepawake_time_msec, uint64_t inactivity_time_msec, uint64_t poll_interval_msec)
Definition: task_monitor.cc:16
uint64_t enqueue_count() const
Definition: task.h:285
static EventManager evm
bool Monitor(uint64_t t, uint64_t enqueue_count, uint64_t done_count)
Definition: task_monitor.cc:73