30,7 → 30,8 |
/** @addtogroup genericddi |
* @{ |
*/ |
/** @file |
/** @file tasklet.c |
* @brief Tasklet implementation |
*/ |
|
#include <arch.h> |
91,10 → 92,10 |
//create the tasklet_thread, it's wired to the current cpu, we'll migrate it ourselves |
thread_t* t= thread_create(&tasklet_thread, NULL, kernel_task, THREAD_FLAG_WIRED, "tasklet_thread", false); |
if (t==NULL) { |
//wtf? |
panic_printf("tasklet thread not created\n"); |
} else { |
spinlock_lock(&t->lock); |
spinlock_lock(&t->lock); |
//we'll default on the first CPU |
t->cpu = &cpus[0]; |
t->priority = TASKLET_THREAD_PRIORITY; |
spinlock_unlock(&t->lock); |
114,21 → 115,25 |
waitq_t wq; |
waitq_initialize(&wq); |
|
//the infinite loop |
while (true) { |
//execute any scheduled tasklets |
tasklet_do(); |
#ifdef CONFIG_SMP |
//check whether other CPUs have tasklets to execute |
if (config.cpu_active>1) { |
current_cpu = CPU->id; |
//find the first cpu with nonempty tasklet_list |
for (new_cpu = (current_cpu + 1) % config.cpu_active; new_cpu!=current_cpu && tasklet_list[new_cpu]==0 && cpus[new_cpu].active; |
new_cpu=(new_cpu + 1)% config.cpu_active); |
for (new_cpu = (current_cpu + 1) % config.cpu_count; new_cpu!=current_cpu && tasklet_list[new_cpu]==0 ; |
new_cpu=(new_cpu + 1)% config.cpu_count); |
|
if (new_cpu!=current_cpu) { |
//if we found a CPU with unsatisfied tasklet schedule to run there. It must be active! |
if (new_cpu!=current_cpu && cpus[new_cpu].active) { |
//we need to migrate this thread to CPU with id new_cpu |
cpu = &cpus[new_cpu]; |
|
spinlock_lock(&THREAD->lock); |
//put tasklet_thread on the new_cpu |
//move tasklet_thread on the new_cpu |
THREAD->cpu = cpu; |
spinlock_unlock(&THREAD->lock); |
} |
203,12 → 208,12 |
|
|
|
/** Executes scheduled enabled tasklets on current CPU */ |
/** Executes scheduled enabled tasklets on current CPU |
* this function could be called from other parts of kernel */ |
void tasklet_do(void) |
{ |
spinlock_lock(&tasklet_lock); |
tasklet_descriptor_t* t = tasklet_list[CPU->id]; |
//printf("."); |
if (t) { |
//empty the tasklet_list |
tasklet_list[CPU->id]=0; |
218,8 → 223,7 |
if (t->func) { |
t->state = TASKLET_STATE_RUNNING; |
t->func(t->data); |
//clear running flag, set not active - the tasklet can disable itself |
//thats why we don't just set it as not active |
//clear running flag, set not active |
t->state &= ~TASKLET_STATE_RUNNING; |
t->state |= TASKLET_STATE_NOTACTIVE; |
} else |
240,7 → 244,7 |
} |
|
/** Frees the tasklet structure when no longer needed. The function doesn't provide |
* any synchronization, the caller must be sure, the tasklet is not scheduled. |
* any synchronization, the caller must be sure, that the tasklet is not scheduled. |
* |
* @param tasklet to be freed |
*/ |