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 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