Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 if(_interval > INT32_MAX) { 00146 _still_left = _interval - INT32_MAX; 00147 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00148 M2MTimerPimpl::_tasklet_id, 00149 INT32_MAX); 00150 } 00151 else { 00152 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00153 M2MTimerPimpl::_tasklet_id, 00154 _interval); 00155 } 00156 assert(status == 0); 00157 } 00158 00159 void M2MTimerPimpl::cancel() 00160 { 00161 eventOS_event_timer_cancel(_timer_id, M2MTimerPimpl::_tasklet_id); 00162 } 00163 00164 void M2MTimerPimpl::stop_timer() 00165 { 00166 _interval = 0; 00167 _single_shot = true; 00168 _still_left = 0; 00169 cancel(); 00170 } 00171 00172 void M2MTimerPimpl::timer_expired() 00173 { 00174 _status++; 00175 _observer.timer_expired(_type); 00176 00177 if ((!_dtls_type) && (!_single_shot)) { 00178 // start next round of periodic timer 00179 start(); 00180 } else if ((_dtls_type) && (!is_total_interval_passed())) { 00181 // if only the intermediate time has passed, we need still wait up to total time 00182 _interval = _total_interval - _intermediate_interval; 00183 start(); 00184 } 00185 } 00186 00187 bool M2MTimerPimpl::is_intermediate_interval_passed() 00188 { 00189 if (_status > 0) { 00190 return true; 00191 } 00192 return false; 00193 } 00194 00195 bool M2MTimerPimpl::is_total_interval_passed() 00196 { 00197 if (_status > 1) { 00198 return true; 00199 } 00200 return false; 00201 } 00202 00203 uint64_t M2MTimerPimpl::get_still_left_time() const 00204 { 00205 return _still_left; 00206 } 00207 00208 void M2MTimerPimpl::start_still_left_timer() 00209 { 00210 if (_still_left > 0) { 00211 int status; 00212 if( _still_left > INT32_MAX) { 00213 _still_left = _still_left - INT32_MAX; 00214 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00215 M2MTimerPimpl::_tasklet_id, 00216 INT32_MAX); 00217 } 00218 else { 00219 status = eventOS_event_timer_request(_timer_id, MBED_CLIENT_TIMER_EVENT, 00220 M2MTimerPimpl::_tasklet_id, 00221 _still_left); 00222 _still_left = 0; 00223 } 00224 assert(status == 0); 00225 } else { 00226 _observer.timer_expired(_type); 00227 if(!_single_shot) { 00228 start_timer(_interval, _type, _single_shot); 00229 } 00230 } 00231 }
Generated on Tue Jul 12 2022 21:20:28 by
1.7.2