kernel: optimize ms-to-ticks for certain tick frequencies

Some tick frequencies lend themselves to optimized conversions from ms
to ticks and vice-versa.

- 1000Hz which does not need any conversion
- 500Hz, 250Hz, 125Hz where the division/multiplication are a straight
  shift since they are power-of-two factors of 1000.

In addition, some more generally used values are made to use optimized
conversion equations rather than the generic one that uses 64-bit math,
and often results in calling compiler intrinsics.

These values are: 100Hz, 50Hz, 25Hz, 20Hz, 10Hz, 1Hz (the last one used
in some testing).

Avoiding the 64-bit math intrisics has the additional benefit, in
addition to increased performance, of using a significant lower amount
of stack space: 52 bytes on ARM Cortex-M and 80 bytes on x86.

Change-Id: I080eb338a2637d6b1c6838c119af1a9fa37fe869
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
This commit is contained in:
Benjamin Walsh 2016-12-20 14:39:08 -05:00 committed by Anas Nashif
commit 6209218f40
6 changed files with 73 additions and 10 deletions

View file

@ -32,6 +32,7 @@
#include <misc/__assert.h>
#include <misc/dlist.h>
#include <misc/slist.h>
#include <misc/util.h>
#ifdef __cplusplus
extern "C" {
@ -634,13 +635,47 @@ extern void *k_thread_custom_data_get(void);
* @cond INTERNAL_HIDDEN
*/
/* kernel clocks */
#if (sys_clock_ticks_per_sec == 1000) || \
(sys_clock_ticks_per_sec == 500) || \
(sys_clock_ticks_per_sec == 250) || \
(sys_clock_ticks_per_sec == 125) || \
(sys_clock_ticks_per_sec == 100) || \
(sys_clock_ticks_per_sec == 50) || \
(sys_clock_ticks_per_sec == 25) || \
(sys_clock_ticks_per_sec == 20) || \
(sys_clock_ticks_per_sec == 10) || \
(sys_clock_ticks_per_sec == 1)
#define _ms_per_tick (MSEC_PER_SEC / sys_clock_ticks_per_sec)
#else
/* yields horrible 64-bit math on many architectures: try to avoid */
#define _NON_OPTIMIZED_TICKS_PER_SEC
#endif
#ifdef _NON_OPTIMIZED_TICKS_PER_SEC
extern int32_t _ms_to_ticks(int32_t ms);
#else
static ALWAYS_INLINE int32_t _ms_to_ticks(int32_t ms)
{
return (int32_t)ceiling_fraction((uint32_t)ms, _ms_per_tick);
}
#endif
/* added tick needed to account for tick in progress */
#define _TICK_ALIGN 1
static int64_t __ticks_to_ms(int64_t ticks)
static inline int64_t __ticks_to_ms(int64_t ticks)
{
#if CONFIG_SYS_CLOCK_EXISTS
#ifdef CONFIG_SYS_CLOCK_EXISTS
#ifdef _NON_OPTIMIZED_TICKS_PER_SEC
return (MSEC_PER_SEC * (uint64_t)ticks) / sys_clock_ticks_per_sec;
#else
return (uint64_t)ticks * _ms_per_tick;
#endif
#else
__ASSERT(ticks == 0, "");
return 0;