fix deadlock in load_balancing
This commit is contained in:
parent
5b5139c283
commit
8ec1d0e817
1 changed files with 22 additions and 9 deletions
|
@ -1155,17 +1155,16 @@ void load_balancing(void)
|
|||
uint32_t prio;
|
||||
task_t* task;
|
||||
|
||||
spinlock_irqsave_lock(&runqueues[core_id].lock);
|
||||
for(i=0; (i<atomic_int32_read(&cpu_online)) && (runqueues[core_id].balance_counter <= 0); i++)
|
||||
{
|
||||
if (i == core_id)
|
||||
continue;
|
||||
|
||||
spinlock_irqsave_lock(&runqueues[i].lock);
|
||||
if ((runqueues[i].load[0] >> (FSHIFT-1)) > (runqueues[core_id].load[0] >> (FSHIFT-1))) {
|
||||
//kprintf("Try to steal a task from core %u (load %u) to %u (load %u)\n", i, runqueues[i].load[0], core_id, runqueues[core_id].load[0]);
|
||||
//kprintf("Task on core %u: %u, core %u, %u\n", i, runqueues[i].nr_tasks, core_id, runqueues[i].nr_tasks);
|
||||
|
||||
spinlock_irqsave_lock(&runqueues[i].lock);
|
||||
prio = lsb(runqueues[i].prio_bitmap);
|
||||
if (prio < sizeof(size_t)*8) {
|
||||
// steal a ready task
|
||||
|
@ -1180,7 +1179,12 @@ void load_balancing(void)
|
|||
runqueues[i].prio_bitmap &= ~(1 << prio);
|
||||
} else runqueues[i].queue[prio-1].last = task->prev;
|
||||
|
||||
// update task counters
|
||||
runqueues[i].nr_tasks--;
|
||||
spinlock_irqsave_unlock(&runqueues[i].lock);
|
||||
|
||||
// add task at the end of queue core_id
|
||||
spinlock_irqsave_lock(&runqueues[core_id].lock);
|
||||
if (!runqueues[core_id].queue[prio-1].last) {
|
||||
runqueues[core_id].queue[prio-1].first = runqueues[core_id].queue[prio-1].last = task;
|
||||
task->next = task->prev = NULL;
|
||||
|
@ -1194,15 +1198,20 @@ void load_balancing(void)
|
|||
|
||||
// update task counters
|
||||
runqueues[core_id].nr_tasks++;
|
||||
runqueues[i].nr_tasks--;
|
||||
runqueues[core_id].balance_counter = TIMER_FREQ/2;
|
||||
} /*else {
|
||||
spinlock_irqsave_unlock(&runqueues[core_id].lock);
|
||||
} else {
|
||||
#if 1
|
||||
spinlock_irqsave_unlock(&runqueues[i].lock);
|
||||
#else
|
||||
task_t* tmp;
|
||||
|
||||
// steal a blocked task
|
||||
task = runqueues[i].timers.first;
|
||||
if (!task) // Ups, found no valid task to steal
|
||||
if (!task) { // Ups, found no valid task to steal
|
||||
spinlock_irqsave_unlock(&runqueues[i].lock);
|
||||
goto no_task_found;
|
||||
}
|
||||
|
||||
kprintf("Core %u steals the blocked task %d from %u with prio %u\n", core_id, task->id, i, task->prio);
|
||||
|
||||
|
@ -1212,6 +1221,10 @@ void load_balancing(void)
|
|||
else
|
||||
runqueues[i].timers.first = runqueues[i].timers.first->next;
|
||||
|
||||
spinlock_irqsave_unlock(&runqueues[i].lock);
|
||||
|
||||
spinlock_irqsave_lock(&runqueues[core_id].lock);
|
||||
|
||||
// add timer to queue core_id
|
||||
tmp = runqueues[core_id].timers.first;
|
||||
while(tmp && (task->timeout >= tmp->timeout))
|
||||
|
@ -1240,16 +1253,16 @@ void load_balancing(void)
|
|||
|
||||
// update task counters
|
||||
runqueues[core_id].balance_counter = TIMER_FREQ/2;
|
||||
}*/
|
||||
|
||||
spinlock_irqsave_lock(&runqueues[core_id].lock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//no_task_found:
|
||||
spinlock_irqsave_unlock(&runqueues[i].lock);
|
||||
}
|
||||
|
||||
if (runqueues[core_id].balance_counter <= 0)
|
||||
runqueues[core_id].balance_counter = TIMER_FREQ/2;
|
||||
|
||||
spinlock_irqsave_unlock(&runqueues[core_id].lock);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue