kernel: do not call swap if next ready thread is current thread

Check if next ready thread is same as current thread before calling
z_swap.
This avoids calling swap to just go back to the original thread.

Original code: thread 0x20000118 switches out and then in again...

>> 0x20000118 gives semaphore(signal): 0x20000104 (count: 0)
>> thread ready: 0x20000118
>> 0x20000118 switched out
>> 0x20000118 switched in
>> end call to k_sem_give
>> 0x20000118 takes semaphore(wait): 0x200000f4 (count: 0)
>> thread pend: 0x20000118
>> 0x20000118 switched out
>> 0x200001d0 switched in

with this patch:

>> 0x200001d0 gives semaphore(signal): 0x200000f4 (count: 0)
>> thread ready: 0x200001d0
>> end call to k_sem_give
>> 0x200001d0 takes semaphore(wait): 0x20000104 (count: 0)
>> thread pend: 0x200001d0
>> 0x200001d0 switched out
>> 0x20000118 switched in
>> end call to k_sem_take

The above is output from tracing with a custom format used for
debugging.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Anas Nashif 2020-08-10 15:47:02 -04:00
commit 379b93f0d3

View file

@ -748,9 +748,27 @@ static inline int resched(uint32_t key)
return arch_irq_unlocked(key) && !arch_is_in_isr(); return arch_irq_unlocked(key) && !arch_is_in_isr();
} }
/*
* Check if the next ready thread is the same as the current thread
* and save the trip if true.
*/
static inline bool need_swap(void)
{
/* the SMP case will be handled in C based z_swap() */
#ifdef CONFIG_SMP
return true;
#else
struct k_thread *new_thread;
/* Check if the next ready thread is the same as the current thread */
new_thread = z_get_next_ready_thread();
return new_thread != _current;
#endif
}
void z_reschedule(struct k_spinlock *lock, k_spinlock_key_t key) void z_reschedule(struct k_spinlock *lock, k_spinlock_key_t key)
{ {
if (resched(key.key)) { if (resched(key.key) && need_swap()) {
z_swap(lock, key); z_swap(lock, key);
} else { } else {
k_spin_unlock(lock, key); k_spin_unlock(lock, key);