1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for the multiplexed timer service. 32 */ 33 34 #ifndef TIMER_HPP_ 35 #define TIMER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stddef.h> 40 #include <stdint.h> 41 42 #include <openthread/platform/alarm-micro.h> 43 #include <openthread/platform/alarm-milli.h> 44 45 #include "common/debug.hpp" 46 #include "common/linked_list.hpp" 47 #include "common/locator.hpp" 48 #include "common/non_copyable.hpp" 49 #include "common/tasklet.hpp" 50 #include "common/time.hpp" 51 52 namespace ot { 53 54 /** 55 * @addtogroup core-timer 56 * 57 * @brief 58 * This module includes definitions for the multiplexed timer service. 59 * 60 * @{ 61 * 62 */ 63 64 /** 65 * Represents an object tracking the next fire time along with the current time (now). 66 * 67 */ 68 class NextFireTime 69 { 70 public: 71 /** 72 * Initializes the `NextFireTime` with a given current time. 73 * 74 * @pram[in] aNow The current time. 75 * 76 */ 77 explicit NextFireTime(Time aNow); 78 79 /** 80 * Initializes the `NextFireTime` using `TimerMilli::GetNow()` for current time. 81 * 82 */ 83 NextFireTime(void); 84 85 /** 86 * Gets the current time (now) tracked by the `NextFireTime` object. 87 * 88 * @returns The current time. 89 * 90 */ GetNow(void) const91 Time GetNow(void) const { return mNow; } 92 93 /** 94 * Updates the tracked next fire time with a new given time only if it is earlier. 95 * 96 * If the given @p aTime is in the past relative to the tracked `GetNow()`, the `GetNow()` time is used instead. 97 * This ensures that the next fire time is never scheduled before the current time. 98 * 99 * @param[in] aTime The new time. 100 * 101 */ 102 void UpdateIfEarlier(Time aTime); 103 104 /** 105 * Indicates whether or not next fire time is set. 106 * 107 * @retval TRUE The next fire time is set. 108 * @retval FALSE The next fire time is not set. 109 * 110 */ IsSet(void) const111 bool IsSet(void) const { return (mNextTime != mNow.GetDistantFuture()); } 112 113 /** 114 * Gets the next fire time. 115 * 116 * If the next fire time is not, `GetNow().GetDistantFuture()` will be returned. 117 * 118 * @returns The next fire time. 119 * 120 */ GetNextTime(void) const121 Time GetNextTime(void) const { return mNextTime; } 122 123 private: 124 Time mNow; 125 Time mNextTime; 126 }; 127 128 /** 129 * Implements a timer. 130 * 131 */ 132 class Timer : public InstanceLocator, public LinkedListEntry<Timer> 133 { 134 friend class LinkedListEntry<Timer>; 135 136 public: 137 /** 138 * This constant defines maximum delay allowed when starting a timer. 139 * 140 */ 141 static const uint32_t kMaxDelay = (Time::kMaxDuration >> 1); 142 143 /** 144 * Defines a function reference which is invoked when the timer expires. 145 * 146 * @param[in] aTimer A reference to the expired timer instance. 147 * 148 */ 149 typedef void (&Handler)(Timer &aTimer); 150 151 /** 152 * Returns the fire time of the timer. 153 * 154 * @returns The fire time. 155 * 156 */ GetFireTime(void) const157 Time GetFireTime(void) const { return mFireTime; } 158 159 /** 160 * Indicates whether or not the timer instance is running. 161 * 162 * @retval TRUE If the timer is running. 163 * @retval FALSE If the timer is not running. 164 * 165 */ IsRunning(void) const166 bool IsRunning(void) const { return (mNext != this); } 167 168 protected: 169 class Scheduler : public InstanceLocator, private NonCopyable 170 { 171 friend class Timer; 172 173 protected: 174 struct AlarmApi 175 { 176 void (*AlarmStartAt)(otInstance *aInstance, uint32_t aT0, uint32_t aDt); 177 void (*AlarmStop)(otInstance *aInstance); 178 uint32_t (*AlarmGetNow)(void); 179 }; 180 Scheduler(Instance & aInstance)181 explicit Scheduler(Instance &aInstance) 182 : InstanceLocator(aInstance) 183 { 184 } 185 186 void Add(Timer &aTimer, const AlarmApi &aAlarmApi); 187 void Remove(Timer &aTimer, const AlarmApi &aAlarmApi); 188 void RemoveAll(const AlarmApi &aAlarmApi); 189 void ProcessTimers(const AlarmApi &aAlarmApi); 190 void SetAlarm(const AlarmApi &aAlarmApi); 191 192 LinkedList<Timer> mTimerList; 193 }; 194 Timer(Instance & aInstance,Handler aHandler)195 Timer(Instance &aInstance, Handler aHandler) 196 : InstanceLocator(aInstance) 197 , mHandler(aHandler) 198 , mNext(this) 199 { 200 } 201 202 bool DoesFireBefore(const Timer &aSecondTimer, Time aNow) const; Fired(void)203 void Fired(void) { mHandler(*this); } 204 205 Handler mHandler; 206 Time mFireTime; 207 Timer *mNext; 208 }; 209 210 extern "C" void otPlatAlarmMilliFired(otInstance *aInstance); 211 212 /** 213 * Implements the millisecond timer. 214 * 215 */ 216 class TimerMilli : public Timer 217 { 218 public: 219 /** 220 * Implements the millisecond timer scheduler. 221 * 222 */ 223 class Scheduler : private Timer::Scheduler 224 { 225 friend class TimerMilli; 226 friend void otPlatAlarmMilliFired(otInstance *aInstance); 227 228 public: 229 /** 230 * Initializes the object. 231 * 232 * @param[in] aInstance A reference to the instance object. 233 * 234 */ Scheduler(Instance & aInstance)235 explicit Scheduler(Instance &aInstance) 236 : Timer::Scheduler(aInstance) 237 { 238 } 239 240 private: Add(TimerMilli & aTimer)241 void Add(TimerMilli &aTimer) { Timer::Scheduler::Add(aTimer, sAlarmMilliApi); } Remove(TimerMilli & aTimer)242 void Remove(TimerMilli &aTimer) { Timer::Scheduler::Remove(aTimer, sAlarmMilliApi); } RemoveAll(void)243 void RemoveAll(void) { Timer::Scheduler::RemoveAll(sAlarmMilliApi); } ProcessTimers(void)244 void ProcessTimers(void) { Timer::Scheduler::ProcessTimers(sAlarmMilliApi); } 245 246 static const AlarmApi sAlarmMilliApi; 247 }; 248 249 /** 250 * Creates a millisecond timer instance. 251 * 252 * @param[in] aInstance A reference to the OpenThread instance. 253 * @param[in] aHandler A pointer to a function that is called when the timer expires. 254 * 255 */ TimerMilli(Instance & aInstance,Handler aHandler)256 TimerMilli(Instance &aInstance, Handler aHandler) 257 : Timer(aInstance, aHandler) 258 { 259 } 260 261 /** 262 * Schedules the timer to fire after a given delay (in milliseconds) from now. 263 * 264 * @param[in] aDelay The delay in milliseconds. It must not be longer than `kMaxDelay`. 265 * 266 */ 267 void Start(uint32_t aDelay); 268 269 /** 270 * Schedules the timer to fire after a given delay (in milliseconds) from a given start time. 271 * 272 * @param[in] aStartTime The start time. 273 * @param[in] aDelay The delay in milliseconds. It must not be longer than `kMaxDelay`. 274 * 275 */ 276 void StartAt(TimeMilli aStartTime, uint32_t aDelay); 277 278 /** 279 * Schedules the timer to fire at a given fire time. 280 * 281 * @param[in] aFireTime The fire time. 282 * 283 */ 284 void FireAt(TimeMilli aFireTime); 285 286 /** 287 * Schedules the timer to fire at a given fire time. 288 * 289 * Is @p aNextFireTime is not set, the timer is stopped. 290 * 291 * @param[in] aNextFireTime The fire time. 292 * 293 */ 294 void FireAt(const NextFireTime &aNextFireTime); 295 296 /** 297 * Re-schedules the timer with a given a fire time only if the timer is not running or the new given 298 * fire time is earlier than the current fire time. 299 * 300 * @param[in] aFireTime The fire time. 301 * 302 */ 303 void FireAtIfEarlier(TimeMilli aFireTime); 304 305 /** 306 * Re-schedules the timer with a given a fire time only if the timer is not running or the new given 307 * fire time is earlier than the current fire time. 308 * 309 * @param[in] aNextFireTime The fire time. 310 * 311 */ 312 void FireAtIfEarlier(const NextFireTime &aNextFireTime); 313 314 /** 315 * Stops the timer. 316 * 317 */ 318 void Stop(void); 319 320 /** 321 * Returns the current time in milliseconds. 322 * 323 * @returns The current time in milliseconds. 324 * 325 */ GetNow(void)326 static TimeMilli GetNow(void) { return TimeMilli(otPlatAlarmMilliGetNow()); } 327 328 protected: 329 static void RemoveAll(Instance &aInstance); 330 }; 331 332 /** 333 * Defines a timer owned by a specific type and using a method on owner type as the callback. 334 * 335 * @tparam Owner The type of the owner of this timer. 336 * @tparam HandleTimerPtr A pointer to a non-static member method of `Owner` to use as timer handler. 337 * 338 * The `Owner` MUST be a type that is accessible using `InstanceLocator::Get<Owner>()`. 339 * 340 */ 341 template <typename Owner, void (Owner::*HandleTimerPtr)(void)> class TimerMilliIn : public TimerMilli 342 { 343 public: 344 /** 345 * Initializes the timer. 346 * 347 * @param[in] aInstance The OpenThread instance. 348 * 349 */ TimerMilliIn(Instance & aInstance)350 explicit TimerMilliIn(Instance &aInstance) 351 : TimerMilli(aInstance, HandleTimer) 352 { 353 } 354 355 private: 356 static void HandleTimer(Timer &aTimer); // Implemented in `locator_getters.hpp` 357 }; 358 359 /** 360 * Implements a millisecond timer that also maintains a user context pointer. 361 * 362 * In typical `TimerMilli`/`TimerMicro` use, in the timer callback handler, the owner of the timer is determined using 363 * `GetOwner<Type>` method. This method works if there is a single instance of `Type` within OpenThread instance 364 * hierarchy. The `TimerMilliContext` is intended for cases where there may be multiple instances of the same class/type 365 * using a timer object. `TimerMilliContext` will store a context `void *` information. 366 * 367 */ 368 class TimerMilliContext : public TimerMilli 369 { 370 public: 371 /** 372 * Creates a millisecond timer that also maintains a user context pointer. 373 * 374 * @param[in] aInstance A reference to the OpenThread instance. 375 * @param[in] aHandler A pointer to a function that is called when the timer expires. 376 * @param[in] aContext A pointer to an arbitrary context information. 377 * 378 */ TimerMilliContext(Instance & aInstance,Handler aHandler,void * aContext)379 TimerMilliContext(Instance &aInstance, Handler aHandler, void *aContext) 380 : TimerMilli(aInstance, aHandler) 381 , mContext(aContext) 382 { 383 } 384 385 /** 386 * Returns the pointer to the arbitrary context information. 387 * 388 * @returns Pointer to the arbitrary context information. 389 * 390 */ GetContext(void)391 void *GetContext(void) { return mContext; } 392 393 private: 394 void *mContext; 395 }; 396 397 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 398 399 extern "C" void otPlatAlarmMicroFired(otInstance *aInstance); 400 401 /** 402 * Implements the microsecond timer. 403 * 404 */ 405 class TimerMicro : public Timer 406 { 407 public: 408 /** 409 * Implements the microsecond timer scheduler. 410 * 411 */ 412 class Scheduler : private Timer::Scheduler 413 { 414 friend class TimerMicro; 415 friend void otPlatAlarmMicroFired(otInstance *aInstance); 416 417 public: 418 /** 419 * Initializes the object. 420 * 421 * @param[in] aInstance A reference to the instance object. 422 * 423 */ Scheduler(Instance & aInstance)424 explicit Scheduler(Instance &aInstance) 425 : Timer::Scheduler(aInstance) 426 { 427 } 428 429 private: Add(TimerMicro & aTimer)430 void Add(TimerMicro &aTimer) { Timer::Scheduler::Add(aTimer, sAlarmMicroApi); } Remove(TimerMicro & aTimer)431 void Remove(TimerMicro &aTimer) { Timer::Scheduler::Remove(aTimer, sAlarmMicroApi); } RemoveAll(void)432 void RemoveAll(void) { Timer::Scheduler::RemoveAll(sAlarmMicroApi); } ProcessTimers(void)433 void ProcessTimers(void) { Timer::Scheduler::ProcessTimers(sAlarmMicroApi); } 434 435 static const AlarmApi sAlarmMicroApi; 436 }; 437 438 /** 439 * Creates a timer instance. 440 * 441 * @param[in] aInstance A reference to the OpenThread instance. 442 * @param[in] aHandler A pointer to a function that is called when the timer expires. 443 * 444 */ TimerMicro(Instance & aInstance,Handler aHandler)445 TimerMicro(Instance &aInstance, Handler aHandler) 446 : Timer(aInstance, aHandler) 447 { 448 } 449 450 /** 451 * Schedules the timer to fire after a given delay (in microseconds) from now. 452 * 453 * @param[in] aDelay The delay in microseconds. It must not be be longer than `kMaxDelay`. 454 * 455 */ 456 void Start(uint32_t aDelay); 457 458 /** 459 * Schedules the timer to fire after a given delay (in microseconds) from a given start time. 460 * 461 * @param[in] aStartTime The start time. 462 * @param[in] aDelay The delay in microseconds. It must not be longer than `kMaxDelay`. 463 * 464 */ 465 void StartAt(TimeMicro aStartTime, uint32_t aDelay); 466 467 /** 468 * Schedules the timer to fire at a given fire time. 469 * 470 * @param[in] aFireTime The fire time. 471 * 472 */ 473 void FireAt(TimeMicro aFireTime); 474 475 /** 476 * Stops the timer. 477 * 478 */ 479 void Stop(void); 480 481 /** 482 * Returns the current time in microseconds. 483 * 484 * @returns The current time in microseconds. 485 * 486 */ GetNow(void)487 static TimeMicro GetNow(void) { return Time(otPlatAlarmMicroGetNow()); } 488 489 protected: 490 static void RemoveAll(Instance &aInstance); 491 }; 492 493 /** 494 * Defines a timer owned by a specific type and using a method on owner type as the callback. 495 * 496 * @tparam Owner The type of the owner of this timer. 497 * @tparam HandleTimerPtr A pointer to a non-static member method of `Owner` to use as timer handler. 498 * 499 * The `Owner` MUST be a type that is accessible using `InstanceLocator::Get<Owner>()`. 500 * 501 */ 502 template <typename Owner, void (Owner::*HandleTimerPtr)(void)> class TimerMicroIn : public TimerMicro 503 { 504 public: 505 /** 506 * Initializes the timer. 507 * 508 * @param[in] aInstance The OpenThread instance. 509 * 510 */ TimerMicroIn(Instance & aInstance)511 explicit TimerMicroIn(Instance &aInstance) 512 : TimerMicro(aInstance, HandleTimer) 513 { 514 } 515 516 private: 517 static void HandleTimer(Timer &aTimer); // Implemented in `locator_getters.hpp` 518 }; 519 520 #endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 521 522 /** 523 * @} 524 * 525 */ 526 527 } // namespace ot 528 529 #endif // TIMER_HPP_ 530