Skip to content

kernel: Do not use sys_clock_ticks_per_sec in _ms_to_ticks() #9073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -1357,9 +1357,9 @@ static ALWAYS_INLINE s32_t _ms_to_ticks(s32_t ms)

#ifdef _NEED_PRECISE_TICK_MS_CONVERSION
/* use 64-bit math to keep precision */
s64_t ms_ticks_per_sec = (s64_t)ms * sys_clock_ticks_per_sec;

return (s32_t)ceiling_fraction(ms_ticks_per_sec, MSEC_PER_SEC);
return (s32_t)ceiling_fraction(
(s64_t)ms * sys_clock_hw_cycles_per_sec,
(s64_t)MSEC_PER_SEC * sys_clock_hw_cycles_per_tick);
#else
/* simple division keeps precision */
s32_t ms_per_tick = MSEC_PER_SEC / sys_clock_ticks_per_sec;
Expand Down
11 changes: 8 additions & 3 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,16 +591,16 @@ struct k_thread *_priq_mq_best(struct _priq_mq *pq)
}

#ifdef CONFIG_TIMESLICING
extern s32_t _time_slice_duration; /* Measured in ms */
extern s32_t _time_slice_elapsed; /* Measured in ms */
extern s32_t _time_slice_duration; /* Measured in ticks */
extern s32_t _time_slice_elapsed; /* Measured in ticks */
extern int _time_slice_prio_ceiling;

void k_sched_time_slice_set(s32_t duration_in_ms, int prio)
{
__ASSERT(duration_in_ms >= 0, "");
__ASSERT((prio >= 0) && (prio < CONFIG_NUM_PREEMPT_PRIORITIES), "");

_time_slice_duration = duration_in_ms;
_time_slice_duration = _ms_to_ticks(duration_in_ms);
_time_slice_elapsed = 0;
_time_slice_prio_ceiling = prio;
}
Expand Down Expand Up @@ -690,6 +690,11 @@ void _sched_init(void)
sys_dlist_init(&_kernel.ready_q.runq.queues[i]);
}
#endif

#ifdef CONFIG_TIMESLICING
k_sched_time_slice_set(CONFIG_TIMESLICE_SIZE,
CONFIG_TIMESLICE_PRIORITY);
#endif
}

int _impl_k_thread_priority_get(k_tid_t thread)
Expand Down
9 changes: 4 additions & 5 deletions kernel/sys_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ static inline void handle_timeouts(s32_t ticks)

#ifdef CONFIG_TIMESLICING
s32_t _time_slice_elapsed;
s32_t _time_slice_duration = CONFIG_TIMESLICE_SIZE;
int _time_slice_prio_ceiling = CONFIG_TIMESLICE_PRIORITY;
s32_t _time_slice_duration;
int _time_slice_prio_ceiling;

/*
* Always called from interrupt level, and always only from the system clock
Expand All @@ -285,7 +285,7 @@ static void handle_time_slicing(s32_t ticks)
return;
}

_time_slice_elapsed += __ticks_to_ms(ticks);
_time_slice_elapsed += ticks;
if (_time_slice_elapsed >= _time_slice_duration) {

unsigned int key;
Expand All @@ -297,8 +297,7 @@ static void handle_time_slicing(s32_t ticks)
irq_unlock(key);
}
#ifdef CONFIG_TICKLESS_KERNEL
next_ts =
_ms_to_ticks(_time_slice_duration - _time_slice_elapsed);
next_ts = _time_slice_duration - _time_slice_elapsed;
#endif
}
#else
Expand Down
25 changes: 16 additions & 9 deletions tests/kernel/sched/schedule_api/src/test_sched_timeslice_reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,31 @@ static K_THREAD_STACK_ARRAY_DEFINE(tstack, NUM_THREAD, STACK_SIZE);
K_SEM_DEFINE(sema, 0, NUM_THREAD);
/*elapsed_slice taken by last thread*/
static s64_t elapsed_slice;
/*expected elapsed duration*/
static s64_t expected_slice[NUM_THREAD] = {
HALF_SLICE_SIZE, /* the ztest native thread taking a half timeslice*/
SLICE_SIZE, /* the spawned thread taking a full timeslice, reset*/
SLICE_SIZE /* the spawned thread taking a full timeslice, reset*/
};
static int thread_idx;

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;

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;
} else {
/*other threads are sliced with tick granulity*/
expected_slice_min = __ticks_to_ms(_ms_to_ticks(SLICE_SIZE));
expected_slice_max = __ticks_to_ms(_ms_to_ticks(SLICE_SIZE)+1);
}

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

/** TESTPOINT: timeslice should be reset for each preemptive thread*/
zassert_true(t <= expected_slice[thread_idx], NULL);
zassert_true(t >= expected_slice_min, NULL);
zassert_true(t <= expected_slice_max, NULL);
thread_idx = (thread_idx + 1) % NUM_THREAD;

u32_t t32 = k_uptime_get_32();
Expand Down
16 changes: 11 additions & 5 deletions tests/kernel/sched/schedule_api/src/test_slice_scheduling.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,23 @@ static void thread_tslice(void *p1, void *p2, void *p3)
int thread_parameter = ((int)p1 == (NUM_THREAD - 1)) ? '\n' :
((int)p1 + 'A');

s64_t expected_slice_min = __ticks_to_ms(_ms_to_ticks(SLICE_SIZE));
s64_t expected_slice_max = __ticks_to_ms(_ms_to_ticks(SLICE_SIZE) + 1);

while (1) {
s64_t tdelta = k_uptime_delta(&elapsed_slice);

TC_PRINT("%c", thread_parameter);
/* Test Fails if thread exceed allocated time slice or
* Any thread is scheduled out of order.
*/
zassert_true(((tdelta <= SLICE_SIZE) &&
zassert_true(((tdelta >= expected_slice_min) &&
(tdelta <= expected_slice_max) &&
((int)p1 == thread_idx)), NULL);
thread_idx = (thread_idx + 1) % (NUM_THREAD);
u32_t t32 = k_uptime_get_32();

/* Keep the current thread busy for more than one slice,
* even though, when timeslice used up the next thread
* even though, when timeslice used up the next thread
* should be scheduled in.
*/
while (k_uptime_get_32() - t32 < BUSY_MS) {
Expand Down Expand Up @@ -102,9 +105,12 @@ void test_slice_scheduling(void)
while (count < ITRERATION_COUNT) {
k_uptime_delta(&elapsed_slice);

/* current thread (ztest native) consumed a half timeslice*/
/* Keep the current thread busy for more than one slice,
* even though, when timeslice used up the next thread
* should be scheduled in.
*/
t32 = k_uptime_get_32();
while (k_uptime_get_32() - t32 < SLICE_SIZE) {
while (k_uptime_get_32() - t32 < BUSY_MS) {
#if defined(CONFIG_ARCH_POSIX)
posix_halt_cpu(); /*sleep until next irq*/
#else
Expand Down
20 changes: 13 additions & 7 deletions tests/kernel/tickless/tickless_concept/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ static struct k_thread tdata[NUM_THREAD];
#ifndef CONFIG_TICKLESS_IDLE
#define CONFIG_TICKLESS_IDLE_THRESH 20
#endif
/*millisecond per tick*/
#define MSEC_PER_TICK (__ticks_to_ms(1))
/*sleep duration tickless*/
#define SLEEP_TICKLESS (CONFIG_TICKLESS_IDLE_THRESH * MSEC_PER_TICK)
#define SLEEP_TICKLESS __ticks_to_ms(CONFIG_TICKLESS_IDLE_THRESH)

/*sleep duration with tick*/
#define SLEEP_TICKFUL ((CONFIG_TICKLESS_IDLE_THRESH - 1) * MSEC_PER_TICK)
#define SLEEP_TICKFUL __ticks_to_ms(CONFIG_TICKLESS_IDLE_THRESH - 1)

/*slice size is set as half of the sleep duration*/
#define SLICE_SIZE ((CONFIG_TICKLESS_IDLE_THRESH >> 1) * MSEC_PER_TICK)
#define SLICE_SIZE __ticks_to_ms(CONFIG_TICKLESS_IDLE_THRESH >> 1)

/*maximum slice duration accepted by the test*/
#define SLICE_SIZE_LIMIT __ticks_to_ms((CONFIG_TICKLESS_IDLE_THRESH >> 1) + 1)

/*align to millisecond boundary*/
#if defined(CONFIG_ARCH_POSIX)
#define ALIGN_MS_BOUNDARY() \
Expand All @@ -46,11 +50,13 @@ static void thread_tslice(void *p1, void *p2, void *p3)
{
s64_t t = k_uptime_delta(&elapsed_slice);

TC_PRINT("elapsed slice %lld\n", t);
TC_PRINT("elapsed slice %lld, expected: <%lld, %lld>\n",
t, SLICE_SIZE, SLICE_SIZE_LIMIT);

/**TESTPOINT: verify slicing scheduler behaves as expected*/
zassert_true(t >= SLICE_SIZE, NULL);
/*less than one tick delay*/
zassert_true(t <= (SLICE_SIZE + MSEC_PER_TICK), NULL);
zassert_true(t <= SLICE_SIZE_LIMIT, NULL);

u32_t t32 = k_uptime_get_32();

Expand Down
16 changes: 10 additions & 6 deletions tests/kernel/workq/work_queue/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
/* Each work item takes 100ms */
#define WORK_ITEM_WAIT 100

/* In fact, each work item could take up to this value */
#define WORK_ITEM_WAIT_ALIGNED \
__ticks_to_ms(_ms_to_ticks(WORK_ITEM_WAIT) + _TICK_ALIGN)

/*
* Wait 50ms between work submissions, to ensure co-op and prempt
* preempt thread submit alternatively.
Expand Down Expand Up @@ -139,7 +143,7 @@ static void test_sequence(void)
test_items_submit();

TC_PRINT(" - Waiting for work to finish\n");
k_sleep((NUM_TEST_ITEMS + 1) * WORK_ITEM_WAIT);
k_sleep(NUM_TEST_ITEMS * WORK_ITEM_WAIT_ALIGNED);

check_results(NUM_TEST_ITEMS);
reset_results();
Expand Down Expand Up @@ -179,7 +183,7 @@ static void test_resubmit(void)
k_work_submit(&tests[0].work.work);

TC_PRINT(" - Waiting for work to finish\n");
k_sleep((NUM_TEST_ITEMS + 1) * WORK_ITEM_WAIT);
k_sleep(NUM_TEST_ITEMS * WORK_ITEM_WAIT_ALIGNED);

TC_PRINT(" - Checking results\n");
check_results(NUM_TEST_ITEMS);
Expand Down Expand Up @@ -294,7 +298,7 @@ static void test_delayed_cancel(void)
NULL, NULL, NULL, K_HIGHEST_THREAD_PRIO, 0, 0);

TC_PRINT(" - Waiting for work to finish\n");
k_sleep(2 * WORK_ITEM_WAIT);
k_sleep(WORK_ITEM_WAIT_ALIGNED);

TC_PRINT(" - Checking results\n");
check_results(0);
Expand Down Expand Up @@ -331,7 +335,7 @@ static void test_delayed_resubmit(void)
k_delayed_work_submit(&tests[0].work, WORK_ITEM_WAIT);

TC_PRINT(" - Waiting for work to finish\n");
k_sleep((NUM_TEST_ITEMS + 1) * WORK_ITEM_WAIT);
k_sleep(NUM_TEST_ITEMS * WORK_ITEM_WAIT_ALIGNED);

TC_PRINT(" - Checking results\n");
check_results(NUM_TEST_ITEMS);
Expand Down Expand Up @@ -378,7 +382,7 @@ static void test_delayed_resubmit_thread(void)
NULL, NULL, NULL, K_PRIO_COOP(10), 0, 0);

TC_PRINT(" - Waiting for work to finish\n");
k_sleep(WORK_ITEM_WAIT);
k_sleep(WORK_ITEM_WAIT_ALIGNED);

TC_PRINT(" - Checking results\n");
check_results(1);
Expand All @@ -403,7 +407,7 @@ static void test_delayed(void)
test_delayed_submit();

TC_PRINT(" - Waiting for delayed work to finish\n");
k_sleep((NUM_TEST_ITEMS + 2) * WORK_ITEM_WAIT);
k_sleep(NUM_TEST_ITEMS * WORK_ITEM_WAIT_ALIGNED);

TC_PRINT(" - Checking results\n");
check_results(NUM_TEST_ITEMS);
Expand Down