LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/base - task_monitor.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 47 62 75.8 %
Date: 2026-11-09 02:10:49 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14