Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
m2mtimerpimpl.cpp
00001 /* 00002 * Copyright (c) 2015-2016 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include <assert.h> 00018 #include <time.h> 00019 00020 #include "mbed-client-classic/m2mtimerpimpl.h" 00021 #include "mbed-client/m2mtimerobserver.h" 00022 #include "mbed-client/m2mvector.h" 00023 00024 #include "eventOS_event.h" 00025 #include "eventOS_event_timer.h" 00026 #include "eventOS_scheduler.h" 00027 #include "ns_hal_init.h" 00028 00029 #define MBED_CLIENT_TIMER_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet 00030 #define MBED_CLIENT_TIMER_EVENT 10 00031 00032 #ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE 00033 #define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE 00034 #else 00035 #define MBED_CLIENT_EVENT_LOOP_SIZE 1024 00036 #endif 00037 00038 int8_t M2MTimerPimpl::_tasklet_id = -1; 00039 00040 int8_t M2MTimerPimpl::_next_timer_id = 1; 00041 00042 static m2m::Vector<M2MTimerPimpl*> timer_impl_list; 00043 00044 extern "C" void tasklet_func(arm_event_s *event) 00045 { 00046 // skip the init event as there will be a timer event after 00047 if (event->event_type == MBED_CLIENT_TIMER_EVENT) { 00048 bool timer_found = false; 00049 eventOS_scheduler_mutex_wait(); 00050 int timer_count = timer_impl_list.size(); 00051 for (int index = 0; index < timer_count; index++) { 00052 M2MTimerPimpl* timer = timer_impl_list[index]; 00053 if (timer->get_timer_id() == event->event_id) { 00054 eventOS_scheduler_mutex_release(); 00055 timer_found = true; 00056 if (timer->get_still_left_time() > 0) { 00057 timer->start_still_left_timer(); 00058 }else { 00059 timer->timer_expired(); 00060 } 00061 break; 00062 } 00063 } 00064 if(!timer_found) { 00065 eventOS_scheduler_mutex_release(); 00066 } 00067 } 00068 } 00069 00070 M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer) 00071 : _observer(observer), 00072 _single_shot(true), 00073 _interval(0), 00074 _type(M2MTimerObserver::Notdefined), 00075 _intermediate_interval(0), 00076 _total_interval(0), 00077 _still_left(0), 00078 _status(0), 00079 _dtls_type(false) 00080 { 00081 ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL); 00082 eventOS_scheduler_mutex_wait(); 00083 if (_tasklet_id < 0) { 00084 _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_TASKLET_INIT_EVENT); 00085 assert(_tasklet_id >= 0); 00086 } 00087 00088 // XXX: this wraps over quite soon 00089 _timer_id = M2MTimerPimpl::_next_timer_id++; 00090 timer_impl_list.push_back(this); 00091 eventOS_scheduler_mutex_release(); 00092 } 00093 00094 M2MTimerPimpl::~M2MTimerPimpl() 00095 { 00096 // cancel the timer request, if any is pending 00097 cancel(); 00098 00099 // there is no turning back, event os does not have eventOS_event_handler_delete() or similar, 00100 // so the tasklet is lost forever. Same goes with timer_impl_list, which leaks now memory. 00101 00102 // remove the timer from object list 00103 eventOS_scheduler_mutex_wait(); 00104 int timer_count = timer_impl_list.size(); 00105 for (int index = 0; index < timer_count; index++) { 00106 const M2MTimerPimpl* timer = timer_impl_list[index]; 00107 if (timer->get_timer_id() == _timer_id) { 00108 timer_impl_list.erase(index); 00109 break; 00110 } 00111 } 00112 eventOS_scheduler_mutex_release(); 00113 } 00114 00115 void M2MTimerPimpl::start_timer( uint64_t interval, 00116 M2MTimerObserver::Type type, 00117 bool single_shot) 00118 { 00119 _dtls_type = false; 00120 _intermediate_interval = 0; 00121 _total_interval = 0; 00122 _status = 0; 00123 _single_shot = single_shot; 00124 _interval = interval; 00125 _type = type; 00126 _still_left = 0; 00127 start(); 00128 } 00129 00130 void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type) 00131 { 00132 _dtls_type = true; 00133 _intermediate_interval = intermediate_interval; 00134 _total_interval = total_interval; 00135 _interval = _intermediate_interval; 00136 _status = 0; 00137 _single_shot = false; 00138 _type = type; 00139 start(); 00140 } 00141 00142 void M2MTimerPimpl::start() 00143 { 00144 int status; 00145 00146 // Cancel ongoing events before creating a new one. 00147 // Otherwise it can happen that there are multiple events running at the same time. 00148 cancel(); 00149 00150 if(_interval > INT32_MAX) { 00151 _still_left = _interval - INT32_MAX; 00152 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00153 M2MTimerPimpl::_tasklet_id, 00154 INT32_MAX); 00155 } 00156 else { 00157 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00158 M2MTimerPimpl::_tasklet_id, 00159 _interval); 00160 } 00161 assert(status == 0); 00162 } 00163 00164 void M2MTimerPimpl::cancel() 00165 { 00166 eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id); 00167 } 00168 00169 void M2MTimerPimpl::stop_timer() 00170 { 00171 _interval = 0; 00172 _single_shot = true; 00173 _still_left = 0; 00174 cancel(); 00175 } 00176 00177 void M2MTimerPimpl::timer_expired() 00178 { 00179 _status++; 00180 _observer.timer_expired(_type); 00181 00182 if ((!_dtls_type) && (!_single_shot)) { 00183 // start next round of periodic timer 00184 start(); 00185 } else if ((_dtls_type) && (!is_total_interval_passed())) { 00186 // if only the intermediate time has passed, we need still wait up to total time 00187 _interval = _total_interval - _intermediate_interval; 00188 start(); 00189 } 00190 } 00191 00192 bool M2MTimerPimpl::is_intermediate_interval_passed() 00193 { 00194 if (_status > 0) { 00195 return true; 00196 } 00197 return false; 00198 } 00199 00200 bool M2MTimerPimpl::is_total_interval_passed() 00201 { 00202 if (_status > 1) { 00203 return true; 00204 } 00205 return false; 00206 } 00207 00208 uint64_t M2MTimerPimpl::get_still_left_time() const 00209 { 00210 return _still_left; 00211 } 00212 00213 void M2MTimerPimpl::start_still_left_timer() 00214 { 00215 if (_still_left > 0) { 00216 int status; 00217 if( _still_left > INT32_MAX) { 00218 _still_left = _still_left - INT32_MAX; 00219 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00220 M2MTimerPimpl::_tasklet_id, 00221 INT32_MAX); 00222 } 00223 else { 00224 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00225 M2MTimerPimpl::_tasklet_id, 00226 _still_left); 00227 _still_left = 0; 00228 } 00229 assert(status == 0); 00230 } else { 00231 _observer.timer_expired(_type); 00232 if(!_single_shot) { 00233 start_timer(_interval, _type, _single_shot); 00234 } 00235 } 00236 }
Generated on Tue Jul 12 2022 19:01:35 by 1.7.2