Skip to content

Commit fb28c5a

Browse files
committed
Improve TimerHost::PushCommand() tolerance to multiple CMD_RESTART, CMD_START_OR_RESET commands which could be issued by ISR (e.g. debouncing button) within the kernel's tick period.
Cleanup TimerHost implementation. Replace STK_ALLOCATE_COUNT macro with template meta-programming. Wrap memcpy with re-definable STK_MEMCPY.
1 parent 3937867 commit fb28c5a

11 files changed

Lines changed: 297 additions & 198 deletions

stk/include/stk.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,10 @@ final
648648
Stack m_stack; //!< Stack descriptor (SP register value + access mode + optional tid).
649649
volatile uint32_t m_state; //!< Bitmask of EStateFlags. Written by task thread, read/cleared by kernel tick.
650650
volatile Timeout m_time_sleep; //!< Sleep countdown: negative while sleeping (absolute value = ticks remaining), zero when awake.
651-
SrtInfo m_srt[STK_ALLOCATE_COUNT(TMode, KERNEL_HRT, 0, 1)]; //!< SRT metadata. Zero-size (no memory) in KERNEL_HRT mode.
652-
HrtInfo m_hrt[STK_ALLOCATE_COUNT(TMode, KERNEL_HRT, 1, 0)]; //!< HRT metadata. Zero-size (no memory) in non-HRT mode.
653-
Weight m_rt_weight[STK_ALLOCATE_COUNT(TStrategy::WEIGHT_API, 1, 1, 0)]; //!< Run-time weight for weighted-round-robin scheduling. Zero-size for unweighted strategies.
654-
WaitObject m_wait_obj[STK_ALLOCATE_COUNT(TMode, KERNEL_SYNC, 1, 0)]; //!< Embedded wait object for synchronization. Zero-size (no memory) if KERNEL_SYNC is not set.
651+
SrtInfo m_srt[STK_ALLOCATE_COUNT<TMode, KERNEL_HRT, 0U, 1U>::Value]; //!< SRT metadata. Zero-size (no memory) in KERNEL_HRT mode.
652+
HrtInfo m_hrt[STK_ALLOCATE_COUNT<TMode, KERNEL_HRT, 1U, 0U>::Value]; //!< HRT metadata. Zero-size (no memory) in non-HRT mode.
653+
Weight m_rt_weight[STK_ALLOCATE_COUNT<TStrategy::WEIGHT_API, 1U, 1U, 0U>::Value]; //!< Run-time weight for weighted-round-robin scheduling. Zero-size for unweighted strategies.
654+
WaitObject m_wait_obj[STK_ALLOCATE_COUNT<TMode, KERNEL_SYNC, 1U, 0U>::Value]; //!< Embedded wait object for synchronization. Zero-size (no memory) if KERNEL_SYNC is not set.
655655
};
656656

657657
/*! \class KernelService
@@ -2226,11 +2226,11 @@ final
22262226
KernelTask *m_task_now; //!< Currently executing task, or \c nullptr before Start() or after all tasks exit.
22272227
TaskStorageType m_task_storage; //!< Static pool of TSize KernelTask slots (free slots have m_user == nullptr).
22282228
SleepTrapStack m_sleep_trap[1]; //!< Sleep trap (always present): executed when all tasks are sleeping.
2229-
ExitTrapStack m_exit_trap[STK_ALLOCATE_COUNT(TMode, KERNEL_DYNAMIC, 1, 0)]; //!< Exit trap: zero-size in KERNEL_STATIC mode; one entry in KERNEL_DYNAMIC mode.
2229+
ExitTrapStack m_exit_trap[STK_ALLOCATE_COUNT<TMode, KERNEL_DYNAMIC, 1U, 0U>::Value]; //!< Exit trap: zero-size in KERNEL_STATIC mode; one entry in KERNEL_DYNAMIC mode.
22302230
EFsmState m_fsm_state; //!< Current FSM state. Drives context-switch decision on every tick.
22312231
volatile uint8_t m_request; //!< Bitmask of pending ERequest flags from running tasks. Written by tasks, read/cleared by UpdateTaskRequest() in tick context.
22322232
volatile EState m_state; //!< Current kernel state.
2233-
SyncObjectList m_sync_list[STK_ALLOCATE_COUNT(TMode, KERNEL_SYNC, 1, 0)]; //!< List of active sync objects. Zero-size (no memory) if KERNEL_SYNC is not set.
2233+
SyncObjectList m_sync_list[STK_ALLOCATE_COUNT<TMode, KERNEL_SYNC, 1U, 0U>::Value]; //!< List of active sync objects. Zero-size (no memory) if KERNEL_SYNC is not set.
22342234

22352235
const EFsmState m_fsm[FSM_STATE_MAX][FSM_EVENT_MAX] = {
22362236
// FSM_EVENT_SWITCH FSM_EVENT_SLEEP FSM_EVENT_WAKE FSM_EVENT_EXIT

stk/include/stk_defs.h

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -521,23 +521,28 @@
521521
#define STK_SLEEP_TRAP_STACK_SIZE (STK_STACK_SIZE_MIN)
522522
#endif
523523

524-
/*! \def STK_ALLOCATE_COUNT
525-
\brief Selects a static array element count at compile time based on a mode flag.
526-
\note On GCC/Clang: expands to ONTRUE if (MODE & FLAG) is non-zero, otherwise ONFALSE.
527-
On MSVC/IAR: always expands to max(ONTRUE, ONFALSE) because these compilers do not support
528-
zero-sized arrays. This means MSVC and IAR builds may over-allocate when the flag is not set,
529-
but avoids a compile error. Configuration mistakes that would result in ONFALSE on other
530-
compilers will be silently masked.
531-
\param[in] MODE: Bitmask of active kernel modes (e.g. EKernelMode flags).
532-
\param[in] FLAG: The specific mode bit to test.
533-
\param[in] ONTRUE: Array count to use when FLAG is active.
534-
\param[in] ONFALSE: Array count to use when FLAG is inactive (may be 0 on GCC/Clang).
535-
*/
524+
/*! \struct STK_ALLOCATE_COUNT
525+
\brief Selects a static array element count at compile time based on a mode flag.
526+
\note On GCC/Clang: evaluates to ONTRUE if (MODE & FLAG) is non-zero, otherwise ONFALSE.
527+
On MSVC/IAR: always evaluates to the maximum of ONTRUE and ONFALSE because these
528+
compilers do not support zero-sized arrays.
529+
530+
\tparam MODE Bitmask of active kernel modes (e.g., EKernelMode flags).
531+
\tparam FLAG The specific mode bit to test.
532+
\tparam ONTRUE Array count to use when FLAG is active.
533+
\tparam ONFALSE Array count to use when FLAG is inactive (may be 0 on GCC/Clang).
534+
*/
535+
template <size_t MODE, size_t FLAG, size_t ONTRUE, size_t ONFALSE>
536+
struct STK_ALLOCATE_COUNT
537+
{
536538
#if defined(_MSC_VER) || defined(__ICCARM__)
537-
#define STK_ALLOCATE_COUNT(MODE, FLAG, ONTRUE, ONFALSE) ((ONTRUE) > (ONFALSE) ? (ONTRUE) : (ONFALSE))
539+
/* MSVC and IAR builds may over-allocate when the flag is not set to avoid compile errors. */
540+
static constexpr size_t Value = ((ONTRUE > ONFALSE) ? ONTRUE : ONFALSE);
538541
#else
539-
#define STK_ALLOCATE_COUNT(MODE, FLAG, ONTRUE, ONFALSE) ((((MODE) & (FLAG)) != 0U) ? (ONTRUE) : (ONFALSE))
542+
/* GCC and Clang support zero-sized array extensions natively. */
543+
static constexpr size_t Value = (((MODE & FLAG) != 0U) ? ONTRUE : ONFALSE);
540544
#endif
545+
};
541546

542547
/*! \def STK_ENDIAN_IDX_HI
543548
\brief Array index of the high 32-bit word when a 64-bit value is viewed as \c uint32_t[2].
@@ -577,6 +582,18 @@
577582
*/
578583
#define STK_UNUSED(X) static_cast<void>(X)
579584

585+
/*! \brief A wrapper for a built-in memcpy, redefine to your own if required.
586+
\note Can be overridden by defining _STK_CUSTOM_MEMCPY in system configuration.
587+
*/
588+
#ifndef _STK_CUSTOM_MEMCPY
589+
#include <string.h>
590+
static __stk_forceinline void STK_MEMCPY(void *const dest, const void *const src, const size_t size)
591+
{
592+
/* MISRA-compliant explicitly-typed call to underlying implementation */
593+
static_cast<void>(memcpy(dest, src, size));
594+
}
595+
#endif
596+
580597
/*! \namespace stk
581598
\brief Namespace of STK package.
582599
*/

stk/include/strategy/stk_strategy_edf.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ class SwitchStrategyEDF final : public ITaskSwitchStrategy
7979
/*! \brief Destructor.
8080
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
8181
*/
82-
~SwitchStrategyEDF()
83-
{}
82+
~SwitchStrategyEDF() = default;
8483

8584
/*! \brief Add task to the runnable set.
8685
\param[in] task: Task to add. Must not be \c NULL and must not already be in any list.

stk/include/strategy/stk_strategy_fpriority.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ class SwitchStrategyFixedPriority final : public ITaskSwitchStrategy
100100
/*! \brief Destructor.
101101
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
102102
*/
103-
~SwitchStrategyFixedPriority()
104-
{}
103+
~SwitchStrategyFixedPriority() = default;
105104

106105
/*! \brief Add task to the runnable set at its fixed priority level.
107106
\param[in] task: Task to add. Must not be \c NULL and must not already be in any list.

stk/include/strategy/stk_strategy_monotonic.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ class SwitchStrategyMonotonic final : public ITaskSwitchStrategy
8888
/*! \brief Destructor.
8989
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
9090
*/
91-
~SwitchStrategyMonotonic()
92-
{}
91+
~SwitchStrategyMonotonic() = default;
9392

9493
/*! \brief Add a task to the priority-sorted runnable list.
9594
\param[in] task: Task to add. Must not be \c NULL and must not already be in any list.

stk/include/strategy/stk_strategy_rrobin.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ class SwitchStrategyRoundRobin final : public ITaskSwitchStrategy
6060
/*! \brief Destructor.
6161
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
6262
*/
63-
~SwitchStrategyRoundRobin()
64-
{}
63+
~SwitchStrategyRoundRobin() = default;
6564

6665
/*! \brief Add task to the runnable set.
6766
\param[in] task: Task to add. Must not be \c nullptr and must not already be in any list.

stk/include/strategy/stk_strategy_swrrobin.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ class SwitchStrategySmoothWeightedRoundRobin final : public ITaskSwitchStrategy
8181
/*! \brief Destructor.
8282
\note MISRA deviation: [STK-DEV-005] Rule 10-3-2.
8383
*/
84-
~SwitchStrategySmoothWeightedRoundRobin()
85-
{}
84+
~SwitchStrategySmoothWeightedRoundRobin() = default;
8685

8786
/*! \brief Add task to the runnable set.
8887
\param[in] task: Task to add. Must not be \c nullptr.

stk/include/sync/stk_sync_msgqueue.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ inline bool MessageQueue::Put(const void *msg_ptr, Timeout timeout)
334334
return false;
335335
}
336336

337-
memcpy(Slot(m_head), msg_ptr, m_msg_size);
337+
STK_MEMCPY(Slot(m_head), msg_ptr, m_msg_size);
338338
m_head = Next(m_head);
339339
m_count++;
340340

@@ -364,7 +364,7 @@ inline bool MessageQueue::PutFront(const void *msg_ptr, Timeout timeout)
364364
// then write the message there. This makes the new message the head of
365365
// the logical sequence without touching m_head at all.
366366
m_tail = Prev(m_tail);
367-
memcpy(Slot(m_tail), msg_ptr, m_msg_size);
367+
STK_MEMCPY(Slot(m_tail), msg_ptr, m_msg_size);
368368
m_count++;
369369

370370
m_cv_not_empty.NotifyOne_CS();
@@ -415,7 +415,7 @@ inline bool MessageQueue::Peek(void *msg_ptr, Timeout timeout)
415415

416416
// Copy from the tail slot without advancing the index or decrementing
417417
// the count, so the message remains available for the next Get().
418-
memcpy(msg_ptr, Slot(m_tail), m_msg_size);
418+
STK_MEMCPY(msg_ptr, Slot(m_tail), m_msg_size);
419419

420420
return true;
421421
}
@@ -439,7 +439,7 @@ inline bool MessageQueue::PeekFront(void *msg_ptr, Timeout timeout)
439439
// The front-inserted message is at m_tail (PutFront retreats m_tail then
440440
// writes, so the newly placed message is always at the current m_tail).
441441
// For a pure-Put queue this is equally correct: m_tail is the oldest slot.
442-
memcpy(msg_ptr, Slot(m_tail), m_msg_size);
442+
STK_MEMCPY(msg_ptr, Slot(m_tail), m_msg_size);
443443

444444
return true;
445445
}

stk/include/sync/stk_sync_rwmutex.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
#ifndef STK_SYNC_RWMUTEX_H_
1111
#define STK_SYNC_RWMUTEX_H_
1212

13-
#include "stk_common.h"
14-
#include "stk_sync_cs.h"
1513
#include "stk_sync_cv.h"
1614

1715
/*! \file stk_sync_rwmutex.h

stk/include/sync/stk_sync_spinlock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#ifndef STK_SYNC_SPINLOCK_H_
1111
#define STK_SYNC_SPINLOCK_H_
1212

13-
#include "stk_common.h"
13+
#include "stk_helper.h"
1414

1515
/*! \file stk_sync_spinlock.h
1616
\brief Implementation of synchronization primitive: stk::sync::SpinLock.

0 commit comments

Comments
 (0)