unified: Add timeslice support

Change-Id: I5b6c1ef5c015d1ddaea21b1c5447336b1b04db39
Signed-off-by: Peter Mitsis <peter.mitsis@windriver.com>
This commit is contained in:
Peter Mitsis 2016-09-12 11:35:26 -04:00 committed by Benjamin Walsh
commit 68d1f4b562
5 changed files with 88 additions and 9 deletions

View file

@ -38,7 +38,7 @@ GTEXT(_IntExit)
GDATA(_nanokernel)
#ifdef CONFIG_KERNEL_V2
GTEXT(__must_switch_threads)
GTEXT(_is_next_thread_current)
#endif
#if CONFIG_GDB_INFO
@ -113,11 +113,11 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, _ExcExit)
bxgt lr
push {lr}
blx __must_switch_threads
blx _is_next_thread_current
pop {lr}
cmp r0, #0
it eq
bxeq lr
it ne
bxne lr
#else

View file

@ -46,7 +46,7 @@
GTEXT(_Swap)
#ifdef CONFIG_KERNEL_V2
GTEXT(__must_switch_threads)
GTEXT(_is_next_thread_current)
#endif
#ifdef CONFIG_SYS_POWER_MANAGEMENT
@ -357,9 +357,9 @@ _IntExitWithCli:
/* reschedule only if the scheduler says that we must do so */
call __must_switch_threads
cmpl $0, %eax
je noReschedule
call _is_next_thread_current
testl %eax, %eax
jnz noReschedule
#else
/*
* Determine whether the execution of the ISR requires a context
@ -386,7 +386,10 @@ _IntExitWithCli:
#if defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO)
#ifdef CONFIG_KERNEL_V2
/* reload _nanokernel.current: __must_switch_threads may clobber it */
/*
* Reload _nanokernel.current as _is_next_thread_current()
* might have clobbered it.
*/
movl _nanokernel + __tNANO_current_OFFSET, %edx
#endif
orl $INT_ACTIVE, __tTCS_flags_OFFSET(%edx)

View file

@ -245,4 +245,36 @@ config ATOMIC_OPERATIONS_C
set, or haven't been implemented yet during bring-up, and also
the compiler does not have support for the atomic __sync_* builtins.
menu "Timer API Options"
config TIMESLICING
bool "Thread time slicing"
default y
depends on SYS_CLOCK_EXISTS && (NUM_PREEMPT_PRIORITIES != 0)
help
This option enables time slicing between preemptible threads of
equal priority.
config TIMESLICE_SIZE
int "Time slice size (in ms)"
default 0
range 0 2147483647
depends on TIMESLICING
help
This option specifies the maximum amount of time a thread can execute
before other threads of equal priority are given an opportunity to run.
A time slice size of zero means "no limit" (i.e. an infinitely large
time slice).
config TIMESLICE_PRIORITY
int "Time slicing thread priority ceiling"
default 0
range 0 NUM_PREEMPT_PRIORITIES
depends on TIMESLICING
help
This option specifies the thread priority level at which time slicing
takes effect; threads having a higher priority than this ceiling are
not subject to time slicing.
endmenu
endmenu

View file

@ -285,3 +285,19 @@ void _dump_ready_q(void)
sys_dlist_peek_head(&_ready_q.q[prio]));
}
}
#ifdef CONFIG_TIMESLICING
extern int32_t _time_slice_duration; /* Measured in ms */
extern int32_t _time_slice_elapsed; /* Measured in ms */
extern int _time_slice_prio_ceiling;
void k_sched_time_slice_set(int32_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_elapsed = 0;
_time_slice_prio_ceiling = prio;
}
#endif /* CONFIG_TIMESLICING */

View file

@ -169,6 +169,31 @@ static inline void handle_expired_timeouts(int32_t ticks)
#define handle_expired_timeouts(ticks) do { } while ((0))
#endif
#ifdef CONFIG_TIMESLICING
int32_t _time_slice_elapsed;
int32_t _time_slice_duration = CONFIG_TIMESLICE_SIZE;
int _time_slice_prio_ceiling = CONFIG_TIMESLICE_PRIORITY;
static void handle_time_slicing(int32_t ticks)
{
if (_time_slice_duration == 0) {
return;
}
if (_is_prio_higher(_current->prio, _time_slice_prio_ceiling)) {
return;
}
_time_slice_elapsed += _ticks_to_ms(ticks);
if (_time_slice_elapsed >= _time_slice_duration) {
_time_slice_elapsed = 0;
_remove_thread_from_ready_q(_current);
_add_thread_to_ready_q(_current);
}
}
#else
#define handle_time_slicing(ticks) do { } while (0)
#endif
/**
*
* @brief Announce a tick to the nanokernel
@ -188,6 +213,9 @@ void _nano_sys_clock_tick_announce(int32_t ticks)
key = irq_lock();
_sys_clock_tick_count += ticks;
handle_expired_timeouts(ticks);
handle_time_slicing(ticks);
irq_unlock(key);
}