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-08-03 02:19:58 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             :  */
       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             : 
      18          11 : TaskMonitor::TaskMonitor(TaskScheduler *scheduler,
      19             :                          uint64_t tbb_keepawake_time_msec,
      20             :                          uint64_t inactivity_time_msec,
      21          11 :                          uint64_t poll_interval_msec) :
      22          11 :     scheduler_(scheduler), cancelled_(false), timer_impl_(nullptr),
      23          11 :     inactivity_time_usec_(inactivity_time_msec * 1000),
      24          11 :     poll_interval_msec_(poll_interval_msec),
      25          11 :     tbb_keepawake_time_msec_(tbb_keepawake_time_msec),
      26          11 :     last_activity_(ClockMonotonicUsec()),
      27          11 :     last_enqueue_count_(0), last_done_count_(0), poll_count_(0) {
      28          11 : }
      29             : 
      30          11 : TaskMonitor::~TaskMonitor() {
      31          11 : }
      32             : 
      33           8 : void TaskMonitor::UpdateTimers() {
      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
      37           8 :     if ((tbb_keepawake_time_msec_ * kPollIntervalMultiplier) > poll_interval_msec_) {
      38           6 :         poll_interval_msec_ =
      39           6 :             kPollIntervalMultiplier * tbb_keepawake_time_msec_;
      40             :     }
      41             : 
      42             :     // Ensure monitor timeout is atleast 50 * poll-interval
      43           8 :     if ((poll_interval_msec_ * kInactivityMultiplier * 1000) >
      44           8 :         inactivity_time_usec_) {
      45           7 :         inactivity_time_usec_ =
      46           7 :             poll_interval_msec_ * kInactivityMultiplier * 1000;
      47             :     }
      48           8 :     return;
      49             : }
      50             : 
      51           3 : void TaskMonitor::Start(EventManager *evm) {
      52           3 :     if (inactivity_time_usec_ == 0 || poll_interval_msec_ == 0)
      53           0 :         return;
      54             : 
      55           3 :     UpdateTimers();
      56           3 :     timer_impl_.reset(new TimerImpl(*evm->io_service()));
      57           3 :     Restart();
      58           3 :     return;
      59             : }
      60             : 
      61           3 : void TaskMonitor::Terminate() {
      62           3 :     cancelled_ = true;
      63           3 : }
      64             : 
      65           3 : void TaskMonitor::Restart() {
      66           3 :     boost::system::error_code ec;
      67           3 :     timer_impl_->expires_from_now(poll_interval_msec_, ec);
      68           3 :     if (ec) {
      69           0 :         assert(0);
      70             :     }
      71           3 :     timer_impl_->async_wait(boost::bind(&TaskMonitor::Run, this,
      72             :                                         boost::asio::placeholders::error));
      73           3 : }
      74             : 
      75          22 : 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          22 :     if (done_count != last_done_count_) {
      79           9 :         last_done_count_ = done_count;
      80           9 :         last_enqueue_count_ = enqueue_count;
      81           9 :         last_activity_ = t;
      82           9 :         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          13 :     if (enqueue_count == last_enqueue_count_) {
      93           7 :         last_done_count_ = done_count;
      94           7 :         last_enqueue_count_ = enqueue_count;
      95           7 :         last_activity_ = t;
      96           7 :         return true;
      97             :     }
      98             : 
      99             :     // Enqueues are happening, check if inactivity exceeds configured time
     100           6 :     return ((t - last_activity_) <= inactivity_time_usec_);
     101             : }
     102             : 
     103           0 : void TaskMonitor::Run(const boost::system::error_code &ec) {
     104           0 :     poll_count_++;
     105             : 
     106             :     // ASIO API aborted. Just restart ASIO timer again
     107           0 :     if (ec && ec.value() == boost::asio::error::operation_aborted) {
     108           0 :         Restart();
     109           0 :         return;
     110             :     }
     111             : 
     112           0 :     if (cancelled_)
     113           0 :         return;
     114             : 
     115           0 :     if (Monitor(ClockMonotonicUsec(), scheduler_->enqueue_count(),
     116           0 :                 scheduler_->done_count())) {
     117           0 :         Restart();
     118           0 :         return;
     119             :     }
     120           0 :     LOG(ERROR, "!!!! ERROR !!!! Task Monitor failed");
     121           0 :     assert(0);
     122             : }

Generated by: LCOV version 1.14