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