Line data Source code
1 : /* 2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include <string> 6 : #include "base/timer.h" 7 : 8 : #include "task_map.h" 9 : #include "task_timer_map.h" 10 : 11 : #ifdef __cplusplus 12 : extern "C" { 13 : #endif 14 : #include "task_timer_api.h" 15 : #ifdef __cplusplus 16 : } 17 : #endif 18 : 19 : extern bool task_timer_callback(void *agent_timer_map); 20 : extern bool task_timer_cleanup(void *data); 21 : 22 1 : void task_timer_init(task *tp) 23 : { 24 1 : tp->cleanup_timer = NULL; 25 1 : thread_new_circular_thread(&tp->deleted_timers); 26 1 : } 27 : 28 1 : void task_timer_cleanup_deleted(task *tp) 29 : { 30 1 : TaskMap *agent_task = (TaskMap *)tp->agent_task; 31 : 32 : Timer * cleanup_timer; 33 1 : cleanup_timer = TimerManager::CreateTimer(agent_task->io_, 34 : "Cleanup Timer", 35 : TaskScheduler::GetInstance()-> 36 : GetTaskId(agent_task->name_), 37 : agent_task->instance_, true); 38 1 : tp->cleanup_timer = (void *)cleanup_timer; 39 1 : cleanup_timer->Start(0, boost::bind(task_timer_cleanup, tp)); 40 1 : } 41 : 42 8 : task_timer *task_timer_create_idle_leaf(task *tp, const char *name, 43 : flag_t flags, task_timer *parent, 44 : timer_callback tjob, void *data) 45 : { 46 8 : task_timer *timer = (task_timer *)malloc(sizeof(task_timer)); 47 8 : if (!timer) { 48 0 : return NULL; 49 : } 50 : 51 8 : TaskMap *agent_task = (TaskMap *)tp->agent_task; 52 8 : TimerMap *timer_map = new TimerMap(); 53 : 54 8 : timer_map->timer_name_ = name; 55 8 : timer_map->timer_ = timer; 56 8 : timer_map->agent_timer_ = TimerManager::CreateTimer(agent_task->io_, 57 8 : timer_map->timer_name_, 58 : TaskScheduler::GetInstance()-> 59 : GetTaskId(agent_task->name_), 60 : agent_task->instance_, false); 61 : 62 8 : timer->tp = tp; 63 8 : timer->callback = tjob; 64 8 : timer->agent_timer_map = timer_map; 65 8 : timer->tdata = data; 66 : 67 8 : return timer; 68 : } 69 : 70 8 : void task_timer_delete(task_timer *timer) 71 : { 72 8 : TimerMap *timer_map = (TimerMap *)timer->agent_timer_map; 73 : 74 8 : if (!TimerManager::DeleteTimer(timer_map->agent_timer_)) { 75 1 : thread_circular_add_top(&timer->tp->deleted_timers, 76 : &timer->deleted_entry); 77 1 : task_timer_cleanup_deleted(timer->tp); 78 1 : return; 79 : } 80 : 81 7 : delete timer_map; 82 : 83 7 : free(timer); 84 : 85 7 : return; 86 : } 87 : 88 0 : void task_timer_smear_auto_parent_timers(task_timer_root *root) 89 : { 90 0 : return; 91 : } 92 : 93 4 : void task_timer_uset_alt_root_auto_parent_oneshot(task_timer_root *root, 94 : task_timer *timer, utime_t *offset, u_int jitter) 95 : { 96 4 : TimerMap *timer_map = (TimerMap *)timer->agent_timer_map; 97 : 98 4 : Timer *agent_timer = timer_map->agent_timer_; 99 : 100 4 : timer->timeout = offset->ut_sec*1000 + offset->ut_usec/1000; 101 : 102 4 : task_timer_reset(timer); 103 : // If running in the timer context, Agent Timer cannot be started 104 : // again. Will inform Agent Timer to restart based on the 'oneshot' 105 : // and 'rescheduled' flags in the function 'task_timer_callback'. 106 4 : if (agent_timer->fired()) { 107 0 : agent_timer->Reschedule(timer->timeout); 108 0 : timer->rescheduled = TRUE; 109 : } else { 110 4 : agent_timer->Start(timer->timeout, 111 : boost::bind(task_timer_callback, timer_map)); 112 : } 113 : 114 4 : timer->oneshot = TRUE; 115 : 116 4 : return; 117 : } 118 : 119 5 : void task_timer_reset(task_timer *timer) 120 : { 121 5 : TimerMap *timer_map = (TimerMap *)timer->agent_timer_map; 122 5 : Timer *agent_timer = (Timer *)timer_map->agent_timer_; 123 : 124 5 : agent_timer->Cancel(); 125 : 126 5 : return; 127 : } 128 : 129 4 : task_timer_root *task_timer_get_auto_parent_root(void) 130 : { 131 4 : return NULL; 132 : } 133 : 134 1 : void *task_timer_data(task_timer *timer) 135 : { 136 1 : return timer->tdata; 137 : } 138 : 139 0 : void task_timer_utime_left(task_timer *timer, utime_t *remaining) 140 : { 141 0 : TimerMap *timer_map = (TimerMap *)timer->agent_timer_map; 142 0 : Timer *agent_timer = (Timer *)timer_map->agent_timer_; 143 : 144 0 : int elapsed = timer->timeout - agent_timer->GetElapsedTime(); 145 : 146 0 : remaining->ut_usec = elapsed*1000; 147 0 : remaining->ut_sec = 0; 148 : 149 0 : return; 150 : } 151 : 152 0 : boolean task_timer_running(task_timer *timer) 153 : { 154 0 : TimerMap *timer_map = (TimerMap *)timer->agent_timer_map; 155 0 : Timer *agent_timer = (Timer *)timer_map->agent_timer_; 156 : 157 0 : return agent_timer->running() ? TRUE : FALSE; 158 : } 159 : 160 1 : bool task_timer_callback(void *agent_timer_map) 161 : { 162 1 : TimerMap *timer_map = (TimerMap *)agent_timer_map; 163 1 : task_timer *timer = (task_timer *)timer_map->timer_; 164 : 165 1 : timer->callback(timer, 0); 166 1 : bool reschedule = false; 167 1 : if (timer->rescheduled == TRUE) { 168 0 : reschedule = true; 169 0 : timer->rescheduled = FALSE; 170 : } 171 1 : if (!reschedule) { 172 1 : reschedule = (!timer->oneshot ? true : false); 173 : } 174 : 175 1 : return reschedule; 176 : } 177 : 178 1 : bool task_timer_cleanup(void *data) 179 : { 180 1 : task *tp = (task *)data; 181 1 : task_timer *timer = NULL; 182 1 : task_thread *thread_ptr = NULL; 183 : 184 : while (TRUE) { 185 2 : thread_ptr = thread_circular_top(&tp->deleted_timers); 186 2 : if (!thread_ptr) break; 187 : 188 1 : timer = task_timer_list_entry(thread_ptr); 189 1 : thread_remove(thread_ptr); 190 1 : TimerMap *timer_map = (TimerMap *)timer->agent_timer_map; 191 1 : if (!TimerManager::DeleteTimer(timer_map->agent_timer_)) { 192 0 : assert(0); 193 : } 194 1 : delete timer_map; 195 : 196 1 : free(timer); 197 1 : } 198 : 199 1 : tp->cleanup_timer = NULL; 200 1 : return false; 201 : } 202 :