Skip to content

Commit 56f1094

Browse files
Preempt a task if a higher-priority task could run
1 parent cce0dfa commit 56f1094

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

kernel/src/task.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ bool timefreeze = false;
1717
uint32_t timemillis;
1818

1919
uint8_t current_queue = 0;
20-
uint8_t timeQuantumCounter = 0;
20+
uint8_t timeQuantumCounters[QUEUE_NUMBER] = {0};
21+
22+
// Prematurely preempted threads
23+
static thread_t* early_preempted_threads[QUEUE_NUMBER] = {NULL};
2124

2225
task_t* kernel_task;
2326

@@ -410,20 +413,35 @@ uint32_t task_switch(uint32_t esp) {
410413
old_thread->esp = esp; // save esp
411414

412415
if (old_thread->parent != doNothing_task) {
413-
++timeQuantumCounter;
416+
timeQuantumCounters[current_queue]++;
414417

415418
if (timemillis < old_thread->timeout) {
416419
// Task was faster than the time quantum
417420
old_thread->nice = (4 * old_thread->nice) / 5 + (old_thread->timeout - timemillis) / 5;
418-
} else if (timeQuantumCounter > current_queue) {
421+
timeQuantumCounters[current_queue] = 0;
422+
} else if (timeQuantumCounters[current_queue] > current_queue) {
419423
// Task took too long, demoting it to a lower priority queue
420424
queue_enqueue(&(queues[MIN(current_queue + 1, QUEUE_NUMBER - 1)]), old_thread);
421425
old_thread->nice = 0;
426+
timeQuantumCounters[current_queue] = 0;
422427
} else {
423-
// Task still has some time left to run
424-
ODA.ts_flag = true;
425-
timefreeze = false;
426-
return old_thread->esp;
428+
bool higherPriorityAppeared = false;
429+
430+
for (uint8_t i = 0; i < current_queue; ++i) {
431+
if (!queue_isEmpty(&(queues[i]))) {
432+
// Another task in a higher priority queue has appeared
433+
early_preempted_threads[current_queue] = old_thread;
434+
higherPriorityAppeared = true;
435+
break;
436+
}
437+
}
438+
439+
if (!higherPriorityAppeared) {
440+
// Task still has some time left to run
441+
ODA.ts_flag = true;
442+
timefreeze = false;
443+
return old_thread->esp;
444+
}
427445
}
428446

429447
uint64_t cpuCycles = rdtsc() - old_thread->parent->last_active;
@@ -433,12 +451,17 @@ uint32_t task_switch(uint32_t esp) {
433451
}
434452
}
435453

436-
timeQuantumCounter = 0;
437-
438454
// Find the next task to run
439455
for (uint8_t i = 0; i < QUEUE_NUMBER; ++i) {
440456
queue_t* queue = &(queues[i]);
441457

458+
if (early_preempted_threads[i] != NULL) {
459+
current_thread = early_preempted_threads[i];
460+
early_preempted_threads[i] = NULL;
461+
current_queue = i;
462+
goto found_new_task;
463+
}
464+
442465
if (!queue_isEmpty(queue)) {
443466
current_thread = queue_dequeue(queue);
444467
current_queue = i;

0 commit comments

Comments
 (0)