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