kernel/sched: Close hole with cross-core timeslice expirations
Moving timeslice events to timeouts isn't quite enough on SMP, as it's still possible for systems that don't broadcast their timer interrupts to end up handling an expiration for a foreign CPU. There, we need an IPI, and a symmetric call to z_time_slice() (which is itempotent and fast) in the IPI ISR. Signed-off-by: Andy Ross <andyross@google.com>
This commit is contained in:
parent
f3afd5a4c9
commit
c5c3ad95de
|
@ -401,6 +401,15 @@ static void move_thread_to_end_of_prio_q(struct k_thread *thread)
|
|||
update_cache(thread == _current);
|
||||
}
|
||||
|
||||
static void flag_ipi(void)
|
||||
{
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED)
|
||||
if (arch_num_cpus() > 1) {
|
||||
_kernel.pending_ipi = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TIMESLICING
|
||||
|
||||
static int slice_ticks;
|
||||
|
@ -434,6 +443,14 @@ static void slice_timeout(struct _timeout *t)
|
|||
int cpu = ARRAY_INDEX(slice_timeouts, t);
|
||||
|
||||
slice_expired[cpu] = true;
|
||||
|
||||
/* We need an IPI if we just handled a timeslice expiration
|
||||
* for a different CPU. Ideally this would be able to target
|
||||
* the specific core, but that's not part of the API yet.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_SMP) && cpu != _current_cpu->id) {
|
||||
flag_ipi();
|
||||
}
|
||||
}
|
||||
|
||||
void z_reset_time_slice(struct k_thread *curr)
|
||||
|
@ -604,15 +621,6 @@ static bool thread_active_elsewhere(struct k_thread *thread)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void flag_ipi(void)
|
||||
{
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED)
|
||||
if (arch_num_cpus() > 1) {
|
||||
_kernel.pending_ipi = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ready_thread(struct k_thread *thread)
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_COHERENCE
|
||||
|
@ -1553,6 +1561,12 @@ void z_sched_ipi(void)
|
|||
#ifdef CONFIG_TRACE_SCHED_IPI
|
||||
z_trace_sched_ipi();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TIMESLICING
|
||||
if (slice_time(_current) && sliceable(_current)) {
|
||||
z_time_slice();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue