unified: Add timeslice support
Change-Id: I5b6c1ef5c015d1ddaea21b1c5447336b1b04db39 Signed-off-by: Peter Mitsis <peter.mitsis@windriver.com>
This commit is contained in:
parent
bd69658571
commit
68d1f4b562
5 changed files with 88 additions and 9 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue