[kernel][thread] Allow pinning threads to a specific cpu
The existing runqueues are scanned on resched until a thread that is not pinned to another cpu is found. Per-pu runqueues can be added later to avoid this scan. Change-Id: Idd7dbddb4b79ef38a0ccd0c42b53f8867020e6cd Conflicts: kernel/thread.c
This commit is contained in:
committed by
Travis Geiselbrecht
parent
888ecb3e33
commit
794d304599
@@ -68,6 +68,7 @@ typedef struct thread {
|
||||
int remaining_quantum;
|
||||
unsigned int flags;
|
||||
int curr_cpu;
|
||||
int pinned_cpu; /* only run on pinned_cpu if >= 0 */
|
||||
|
||||
/* if blocked, a pointer to the wait queue */
|
||||
struct wait_queue *blocking_wait_queue;
|
||||
|
||||
@@ -112,6 +112,7 @@ static void init_thread_struct(thread_t *t, const char *name)
|
||||
{
|
||||
memset(t, 0, sizeof(thread_t));
|
||||
t->magic = THREAD_MAGIC;
|
||||
t->pinned_cpu = -1;
|
||||
strlcpy(t->name, name, sizeof(t->name));
|
||||
}
|
||||
|
||||
@@ -424,6 +425,31 @@ static void idle_thread_routine(void)
|
||||
arch_idle();
|
||||
}
|
||||
|
||||
static thread_t *get_top_thread(int cpu)
|
||||
{
|
||||
thread_t *newthread;
|
||||
uint32_t local_run_queue_bitmap = run_queue_bitmap;
|
||||
int next_queue;
|
||||
|
||||
while (local_run_queue_bitmap) {
|
||||
next_queue = HIGHEST_PRIORITY - __builtin_clz(local_run_queue_bitmap) - (32 - NUM_PRIORITIES);
|
||||
|
||||
list_for_every_entry(&run_queue[next_queue], newthread, thread_t, queue_node) {
|
||||
if (newthread->pinned_cpu < 0 || newthread->pinned_cpu == cpu) {
|
||||
list_delete(&newthread->queue_node);
|
||||
|
||||
if (list_is_empty(&run_queue[next_queue]))
|
||||
run_queue_bitmap &= ~(1<<next_queue);
|
||||
|
||||
return newthread;
|
||||
}
|
||||
}
|
||||
|
||||
local_run_queue_bitmap &= ~(1<<next_queue);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cause another thread to be executed.
|
||||
*
|
||||
@@ -450,16 +476,8 @@ void thread_resched(void)
|
||||
|
||||
THREAD_STATS_INC(reschedules);
|
||||
|
||||
if (likely(run_queue_bitmap != 0)) {
|
||||
/* find the first queue with a thread in it */
|
||||
uint next_queue = HIGHEST_PRIORITY - __builtin_clz(run_queue_bitmap)
|
||||
- (sizeof(run_queue_bitmap) * 8 - NUM_PRIORITIES);
|
||||
|
||||
newthread = list_remove_head_type(&run_queue[next_queue], thread_t, queue_node);
|
||||
|
||||
if (list_is_empty(&run_queue[next_queue]))
|
||||
run_queue_bitmap &= ~(1U << next_queue);
|
||||
} else {
|
||||
newthread = get_top_thread(cpu);
|
||||
if (unlikely(!newthread)) {
|
||||
/* no threads to run, select the idle thread for this cpu */
|
||||
newthread = &idle_threads[cpu];
|
||||
}
|
||||
@@ -746,6 +764,7 @@ void thread_init_early(void)
|
||||
t->state = THREAD_RUNNING;
|
||||
t->flags = THREAD_FLAG_DETACHED;
|
||||
t->curr_cpu = 0;
|
||||
t->pinned_cpu = 0;
|
||||
wait_queue_init(&t->retcode_wait_queue);
|
||||
list_add_head(&thread_list, &t->thread_list_node);
|
||||
set_current_thread(t);
|
||||
@@ -818,6 +837,7 @@ void thread_become_idle(void)
|
||||
/* mark ourself as idle */
|
||||
t->priority = IDLE_PRIORITY;
|
||||
t->flags |= THREAD_FLAG_IDLE;
|
||||
t->pinned_cpu = arch_curr_cpu_num();
|
||||
|
||||
mp_set_curr_cpu_active(true);
|
||||
mp_set_cpu_idle(arch_curr_cpu_num());
|
||||
@@ -847,6 +867,7 @@ void thread_secondary_cpu_entry(void)
|
||||
t->state = THREAD_RUNNING;
|
||||
t->flags = THREAD_FLAG_DETACHED | THREAD_FLAG_IDLE;
|
||||
t->curr_cpu = cpu;
|
||||
t->pinned_cpu = cpu;
|
||||
wait_queue_init(&t->retcode_wait_queue);
|
||||
|
||||
THREAD_LOCK(state);
|
||||
@@ -885,8 +906,8 @@ static const char *thread_state_to_str(enum thread_state state)
|
||||
void dump_thread(thread_t *t)
|
||||
{
|
||||
dprintf(INFO, "dump_thread: t %p (%s)\n", t, t->name);
|
||||
dprintf(INFO, "\tstate %s, curr_cpu %d, priority %d, remaining quantum %d\n",
|
||||
thread_state_to_str(t->state), t->curr_cpu, t->priority, t->remaining_quantum);
|
||||
dprintf(INFO, "\tstate %s, curr_cpu %d, pinned_cpu %d, priority %d, remaining quantum %d\n",
|
||||
thread_state_to_str(t->state), t->curr_cpu, t->pinned_cpu, t->priority, t->remaining_quantum);
|
||||
dprintf(INFO, "\tstack %p, stack_size %zd\n", t->stack, t->stack_size);
|
||||
dprintf(INFO, "\tentry %p, arg %p, flags 0x%x\n", t->entry, t->arg, t->flags);
|
||||
dprintf(INFO, "\twait queue %p, wait queue ret %d\n", t->blocking_wait_queue, t->wait_queue_block_ret);
|
||||
|
||||
@@ -110,6 +110,7 @@ void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3)
|
||||
// create a thread to complete system initialization
|
||||
dprintf(SPEW, "creating bootstrap completion thread\n");
|
||||
thread_t *t = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
|
||||
t->pinned_cpu = 0;
|
||||
thread_detach(t);
|
||||
thread_resume(t);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user