diff --git a/include/uk/plat/lcpu.h b/include/uk/plat/lcpu.h index bae0f1f54a8914bf67ef9cd1c99c4a68366d9b48..1ccfec198ada361529b1478b913793b34398e58f 100644 --- a/include/uk/plat/lcpu.h +++ b/include/uk/plat/lcpu.h @@ -261,6 +261,8 @@ int ukplat_lcpu_wakeup(const __lcpuidx lcpuidx[], unsigned int *num); var_name[lcpu_idx][idx] #define ukplat_per_lcpu_array_current(var_name, idx) \ ukplat_per_lcpu_array(var_name, ukplat_lcpu_idx(), idx) +#define ukplat_per_lcpu_var_to_idx(var_name, var) \ + ((var)-&(var_name[0])) #ifdef __cplusplus } diff --git a/lib/tnschedprio/Config.uk b/lib/tnschedprio/Config.uk index 298d24ee7f4e5c116f29fdeac20ca462e3d39edc..758c01548cebcf387dd1d604249b785f292e72cc 100644 --- a/lib/tnschedprio/Config.uk +++ b/lib/tnschedprio/Config.uk @@ -21,4 +21,14 @@ if LIBTNSCHEDPRIO depends on LIBUKSCHED_RUNQ_LIST bool "Use double linked list based algorithm for run queue" endchoice + + config LIBTNSCHEDPRIO_ENABLE_TIMESLICING + depends on LIBUKSCHED_ENABLE_TICKANNOUNCE + bool "Enable time slice" + default n + + config LIBTNSCHEDPRIO_TIMESLICE_SIZE + depends on LIBTNSCHEDPRIO_ENABLE_TIMESLICING + int "Time slice size" + default 0 endif diff --git a/lib/tnschedprio/exportsyms.uk b/lib/tnschedprio/exportsyms.uk index c99178f77a9ad1bf2cd28649694901999e5424bf..1cf4ee4d46697e84007c281cc86363874f5f0a52 100644 --- a/lib/tnschedprio/exportsyms.uk +++ b/lib/tnschedprio/exportsyms.uk @@ -1 +1,2 @@ tn_schedprio_create +schedprio_tick_announce diff --git a/lib/tnschedprio/schedprio.c b/lib/tnschedprio/schedprio.c index 6e7333b0bd949dcd572862d666839fd821986f9f..fa6aaaeb567479c9b9a9f75b606fed7f14a9bf7c 100644 --- a/lib/tnschedprio/schedprio.c +++ b/lib/tnschedprio/schedprio.c @@ -19,8 +19,67 @@ #include #include #include +#include #include "schedprio.h" +#ifdef CONFIG_LIBTNSCHEDPRIO_ENABLE_TIMESLICING +UKPLAT_PER_LCPU_DEFINE(struct timer, __tn_sched_timeslice_timer); +UKPLAT_PER_LCPU_DEFINE(bool, __tn_sched_timeslice_expired); +UKPLAT_PER_LCPU_DEFINE(bool, __tn_sched_timeslice_run); +static int slice_ticks = CONFIG_LIBTNSCHEDPRIO_TIMESLICE_SIZE; + +static inline int slice_time(struct uk_thread *t) +{ + int ret = slice_ticks; + + return ret; +} + +bool sliceable(struct uk_thread *t) +{ + bool ret = uk_sched_idle_thread(t->sched, 0) != t + && uk_thread_is_runnable(t) + && slice_time(t) != 0; + + return ret; +} + +void slice_timeout(struct timer *t) +{ + int cpu = ukplat_per_lcpu_var_to_idx(__tn_sched_timeslice_timer, t); + + __tn_sched_timeslice_expired[cpu] = true; +} + +void reset_timeslice(struct uk_thread *t) +{ + int cpu = ukplat_lcpu_id(); + + if (__tn_sched_timeslice_run[cpu]) { + tn_timer_delete(&__tn_sched_timeslice_timer[cpu]); + __tn_sched_timeslice_run[cpu] = false; + } + __tn_sched_timeslice_expired[cpu] = false; + if (sliceable(t)) { + tn_timer_init(&__tn_sched_timeslice_timer[cpu], + slice_time(t), *slice_timeout, + &__tn_sched_timeslice_timer[cpu], + TN_TIMER_FLAG_ONE_SHOT); + tn_timer_start(&__tn_sched_timeslice_timer[cpu]); + __tn_sched_timeslice_run[cpu] = true; + } +} + +void schedprio_tick_announce(void) +{ + int cpu = ukplat_lcpu_id(); + struct uk_thread *curr = uk_thread_current(); + + if (__tn_sched_timeslice_expired[cpu] && sliceable(curr)) + reset_timeslice(curr); +} +#endif /* CONFIG_LIBTNSCHEDPRIO_ENABLE_TIMESLICING */ + static inline void schedprio_schedule(struct schedprio *c, bool yield) { struct uk_thread *prev, *next, *thread, *tmp; @@ -87,6 +146,27 @@ static inline void schedprio_schedule(struct schedprio *c, bool yield) switch_thread: if (next != prev) { +#ifdef CONFIG_LIBTNSCHEDPRIO_ENABLE_TIMESLICING + int cpu = ukplat_lcpu_id(); + + if (uk_sched_idle_thread(next->sched, 0) == next) { + if (__tn_sched_timeslice_run[cpu]) { + tn_timer_delete(&__tn_sched_timeslice_timer[cpu]); + __tn_sched_timeslice_run[cpu] = false; + } + } else { + if (__tn_sched_timeslice_run[cpu]) { + tn_timer_delete(&__tn_sched_timeslice_timer[cpu]); + __tn_sched_timeslice_run[cpu] = false; + } + tn_timer_init(&__tn_sched_timeslice_timer[cpu], + slice_time(next), *slice_timeout, + &__tn_sched_timeslice_timer[cpu], + TN_TIMER_FLAG_ONE_SHOT); + tn_timer_start(&__tn_sched_timeslice_timer[cpu]); + __tn_sched_timeslice_run[cpu] = true; + } +#endif /* CONFIG_LIBTNSCHEDPRIO_ENABLE_TIMESLICING */ /* * Schedule idle thread that will halt the CPU * We select the idle thread only if we do not @@ -245,6 +325,9 @@ static int schedprio_start(struct uk_sched *s __maybe_unused, */ ukplat_lcpu_enable_irq(); +#ifdef CONFIG_LIBTNSCHEDPRIO_ENABLE_TIMESLICING + reset_timeslice(main_thread); +#endif /* CONFIG_LIBTNSCHEDPRIO_ENABLE_TIMESLICING */ return 0; } diff --git a/lib/tnsystick/tnsystick.c b/lib/tnsystick/tnsystick.c index 80cf4424bd2f00c35ad742287946f26de1ab4231..c41ea4e3e1bb7e66ab7f9b7dcf75e30177fa16c2 100644 --- a/lib/tnsystick/tnsystick.c +++ b/lib/tnsystick/tnsystick.c @@ -101,8 +101,9 @@ int sys_timer_irq_handler(void *arg __unused) sysclock.ops->set_next(tot_counts_per_tick, 0); #endif /* CONFIG_LIBTNSYSTICK_TICKLESS */ tn_timer_announce(); - /* 3、todo :schedprio to check timeout threads */ - +#ifdef CONFIG_LIBUKSCHED_ENABLE_TICKANNOUNCE + uk_sched_tick_announce(); +#endif /* CONFIG_LIBUKSCHED_ENABLE_TICKANNOUNCE */ /* 4、set next time-base irq */ #ifdef CONFIG_LIBTNSYSTICK_TICKLESS systick_t timeout; diff --git a/lib/uksched/Config.uk b/lib/uksched/Config.uk index 1ce1f6914394de5b70ba480ad7db4650c5f0a5a6..1623e719218bf8fd87500314d8ea3ba8c43fd74b 100644 --- a/lib/uksched/Config.uk +++ b/lib/uksched/Config.uk @@ -60,4 +60,7 @@ if LIBUKSCHED config LIBUKSCHED_TEST bool "Enable unit tests" default n + config LIBUKSCHED_ENABLE_TICKANNOUNCE + bool "Enable tick announce" + default n endif diff --git a/lib/uksched/exportsyms.uk b/lib/uksched/exportsyms.uk index 7874cc6536d3eef88389139d8a98fdc8dea12b4e..dd424bdacd96888cb8bef5224e6100e9838f57f4 100644 --- a/lib/uksched/exportsyms.uk +++ b/lib/uksched/exportsyms.uk @@ -13,6 +13,7 @@ uk_sched_thread_exit2 uk_sched_dumpk_threads uk_sched_thread_gc uk_sched_thread_set_priority +uk_sched_tick_announce uk_thread_init_bare uk_thread_init_bare_fn0 uk_thread_init_bare_fn1 diff --git a/lib/uksched/sched.c b/lib/uksched/sched.c index 94fee4504953e3bfce5150d7db55b22ff4c0f034..22b5850126c22d6246bb60639f2c5e5c4d4fa1ea 100644 --- a/lib/uksched/sched.c +++ b/lib/uksched/sched.c @@ -460,3 +460,10 @@ void uk_sched_thread_set_priority(struct uk_thread *thread, int32_t priority) thread->sched->thread_set_prio(thread->sched, thread, priority); } #endif + +#ifdef CONFIG_LIBUKSCHED_ENABLE_TICKANNOUNCE +void uk_sched_tick_announce(void) +{ + schedprio_tick_announce(); +} +#endif /* CONFIG_LIBUKSCHED_ENABLE_TICKANNOUNCE */