Skip to content
Permalink
Browse files

tests: test_sched_timeslice_reset: Fix slice time measurement

The time measurement based on k_uptime_delta() might be not accurate
for some values of CONFIG_SYS_CLOCK_TICKS_PER_SEC. This commit
introduces measurement based on k_cycle_get_32(), which is more
precise.

Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no>
  • Loading branch information...
pizi-nordic authored and nashif committed May 16, 2019
1 parent 62c71dc commit ba4eae14ddea910777e11b1ac139fc147dc192c6
Showing with 51 additions and 15 deletions.
  1. +51 −15 tests/kernel/sched/schedule_api/src/test_sched_timeslice_reset.c
@@ -19,29 +19,53 @@ BUILD_ASSERT(NUM_THREAD <= MAX_NUM_THREAD);
#define BUSY_MS (SLICE_SIZE + 20)
/* a half timeslice*/
#define HALF_SLICE_SIZE (SLICE_SIZE >> 1)
#define HALF_SLICE_SIZE_CYCLES \
((u64_t)(HALF_SLICE_SIZE) * sys_clock_hw_cycles_per_sec() / 1000)

K_SEM_DEFINE(sema, 0, NUM_THREAD);
/*elapsed_slice taken by last thread*/
static s64_t elapsed_slice;
static u32_t elapsed_slice;
static int thread_idx;

static u32_t cycles_delta(u32_t *reftime)
{
u32_t now, delta;

now = k_cycle_get_32();
delta = now - *reftime;
*reftime = now;

return delta;
}

static void thread_tslice(void *p1, void *p2, void *p3)
{
s64_t t = k_uptime_delta(&elapsed_slice);
s64_t expected_slice_min, expected_slice_max;
u32_t t = cycles_delta(&elapsed_slice);
u32_t expected_slice_min, expected_slice_max;

if (thread_idx == 0) {
/*thread number 0 releases CPU after HALF_SLICE_SIZE*/
expected_slice_min = HALF_SLICE_SIZE;
expected_slice_max = HALF_SLICE_SIZE;
/*
* Thread number 0 releases CPU after HALF_SLICE_SIZE,
* and we expect that task switch will not take more than 1 ms.
*/
expected_slice_min = (u64_t)(HALF_SLICE_SIZE - 1) *
sys_clock_hw_cycles_per_sec() / 1000;
expected_slice_max = (u64_t)(HALF_SLICE_SIZE + 1) *
sys_clock_hw_cycles_per_sec() / 1000;
} else {
/*other threads are sliced with tick granulity*/
expected_slice_min = __ticks_to_ms(z_ms_to_ticks(SLICE_SIZE));
expected_slice_max = __ticks_to_ms(z_ms_to_ticks(SLICE_SIZE)+1);
/*
* Other threads are sliced with tick granulity. Here, we
* also expecting task switch time below 1 ms.
*/
expected_slice_min = (z_ms_to_ticks(SLICE_SIZE) - 1) *
sys_clock_hw_cycles_per_tick();
expected_slice_max = (z_ms_to_ticks(SLICE_SIZE) *
sys_clock_hw_cycles_per_tick()) +
(sys_clock_hw_cycles_per_sec() / 1000);
}

#ifdef CONFIG_DEBUG
TC_PRINT("thread[%d] elapsed slice: %lld, expected: <%lld, %lld>\n",
TC_PRINT("thread[%d] elapsed slice: %d, expected: <%d, %d>\n",
thread_idx, t, expected_slice_min, expected_slice_max);
#endif

@@ -66,8 +90,8 @@ static void thread_tslice(void *p1, void *p2, void *p3)
* priorities and few with same priorities and enable the time slice.
* Ensure that each thread is given the time slice period to execute.
*
* @see k_sched_time_slice_set(), k_sem_reset(), k_uptime_delta(),
* k_uptime_get_32()
* @see k_sched_time_slice_set(), k_sem_reset(), k_cycle_get_32(),
* k_uptime_get_32()
*
* @ingroup kernel_sched_tests
*/
@@ -94,11 +118,23 @@ void test_slice_reset(void)
}
/* enable time slice*/
k_sched_time_slice_set(SLICE_SIZE, K_PRIO_PREEMPT(0));
k_uptime_delta(&elapsed_slice);

/* current thread (ztest native) consumed a half timeslice*/
/*synchronize to tick boundary*/
t32 = k_uptime_get_32();
while (k_uptime_get_32() - t32 < HALF_SLICE_SIZE) {
while (k_uptime_get_32() == t32) {
#if defined(CONFIG_ARCH_POSIX)
k_busy_wait(50);
#else
;
#endif
}

/*set reference time*/
cycles_delta(&elapsed_slice);

/* current thread (ztest native) consumed a half timeslice*/
t32 = k_cycle_get_32();
while (k_cycle_get_32() - t32 < HALF_SLICE_SIZE_CYCLES) {
#if defined(CONFIG_ARCH_POSIX)
k_busy_wait(50);
#else

0 comments on commit ba4eae1

Please sign in to comment.
You can’t perform that action at this time.