Skip to content

Commit ab1d0b6

Browse files
committed
sched: Reverse runqueue order when CLZ is available
This commit reverses the runqueue_cache bit order when the architecture has a CLZ (count leading zeros) instruction. When the architecture supports CLZ, it is faster to determine the most significant set bit of a word than to determine the least significant bit set. Unfortunately when the instruction is not available, it is more efficient to determine the least significant bit set. Reversing the bit order shaves off another 4 cycles on the same54-xpro. From 147 to 143 ticks when testing with tests/bench_sched_nop. Architectures where no CLZ instruction is available are not affected.
1 parent 01e6b62 commit ab1d0b6

File tree

1 file changed

+37
-3
lines changed

1 file changed

+37
-3
lines changed

core/sched.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,40 @@ static void (*sched_cb) (kernel_pid_t active_thread,
7979
kernel_pid_t next_thread) = NULL;
8080
#endif
8181

82+
/* Depending on whether the CLZ instruction is available, the order of the
83+
* runqueue_bitcache is reversed. When the instruction is available, it is
84+
* faster to determine the MSBit set. When it is not available it is faster to
85+
* determine the LSBit set. These functions abstract the runqueue modifications
86+
* and readout away, switching between the two orders depending on the CLZ
87+
* instruction availability
88+
*/
89+
static inline void _set_runqueue_bit(thread_t *process)
90+
{
91+
#if defined(BITARITHM_HAS_CLZ)
92+
runqueue_bitcache |= BIT31 >> process->priority;
93+
#else
94+
runqueue_bitcache |= 1 << process->priority;
95+
#endif
96+
}
97+
98+
static inline void _clear_runqueue_bit(thread_t *process)
99+
{
100+
#if defined(BITARITHM_HAS_CLZ)
101+
runqueue_bitcache &= ~(BIT31 >> process->priority);
102+
#else
103+
runqueue_bitcache &= ~(1 << process->priority);
104+
#endif
105+
}
106+
107+
static inline unsigned _get_prio_queue_from_runqueue(void)
108+
{
109+
#if defined(BITARITHM_HAS_CLZ)
110+
return 31 - bitarithm_msb(runqueue_bitcache);
111+
#else
112+
return bitarithm_lsb(runqueue_bitcache);
113+
#endif
114+
}
115+
82116
static void _unschedule(thread_t *active_thread)
83117
{
84118
if (active_thread->status == STATUS_RUNNING) {
@@ -119,7 +153,7 @@ int __attribute__((used)) sched_run(void)
119153

120154
sched_context_switch_request = 0;
121155

122-
int nextrq = bitarithm_lsb(runqueue_bitcache);
156+
unsigned nextrq = _get_prio_queue_from_runqueue();
123157
thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next,
124158
thread_t, rq_entry);
125159

@@ -173,7 +207,7 @@ void sched_set_status(thread_t *process, thread_status_t status)
173207
process->pid, process->priority);
174208
clist_rpush(&sched_runqueues[process->priority],
175209
&(process->rq_entry));
176-
runqueue_bitcache |= 1 << process->priority;
210+
_set_runqueue_bit(process);
177211
}
178212
}
179213
else {
@@ -184,7 +218,7 @@ void sched_set_status(thread_t *process, thread_status_t status)
184218
clist_lpop(&sched_runqueues[process->priority]);
185219

186220
if (!sched_runqueues[process->priority].next) {
187-
runqueue_bitcache &= ~(1 << process->priority);
221+
_clear_runqueue_bit(process);
188222
}
189223
}
190224
}

0 commit comments

Comments
 (0)