Brendan's Multi-tasking Tutorial: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
Line 394:
For "nano_sleep_until()" you'd store the time the task is supposed to wake up somewhere, put the task on the unsorted list, then block the task. You'll need to add a "wake up time" field to the data structure you're using to keep track of tasks for this, and you'll need to define a new task state ("SLEEPING"). The code might look like this:
 
<sourcesyntaxhighlight lang="c">
thread_control_block * sleeping_task_list = NULL;
 
Line 422:
block_task(SLEEPING);
}
</syntaxhighlight>
</source>
 
Note that we're using the same "next" field in the data structure that the kernel uses to keep track of a task's information that the scheduler uses for its list of "ready to run" tasks. A task can't be ready to run and sleeping at the same time, so this is fine.
Line 428:
The code for the timer IRQ handler depends a little on which timer you're using. If you're using the PIT chip on 80x86 PCs, and the PIT chip has been set to a frequency of about 1000 Hz, then the timer IRQ handler might look like this:
 
<sourcesyntaxhighlight lang="c">
uint64_t time_since_boot = 0;
uint64_t time_between_ticks = 1000000; // 1000 Hz = 1 ms between ticks = 1000000 nanoseconds between ticks
Line 464:
unlock_stuff();
}
</syntaxhighlight>
</source>
 
Finally, test the code to make sure tasks block and unblock correctly when they call "sleep()" or "nano_sleep()" or "nano_sleep_until()". Please note that currently there's a minor problem with the scheduler - if all tasks are blocked waiting for something (either paused or sleeping) there won't be any tasks that the scheduler can give CPU time to so the scheduler will give CPU time to a task that is supposed to be blocked (which is bad!). For now, just make sure that at least one task is running.
Line 637:
For the earlier example (using the PIT on 80x86 at a frequency of 1000 Hz) it might look like this:
 
<sourcesyntaxhighlight lang="c">
uint64_t time_slice_remaining = 0;
 
Line 686:
unlock_stuff();
}
</syntaxhighlight>
</source>
 
The other change that's needed is that the "time_slice_remaining" variable needs to be set when a task switch happens. This can be done in the low level task switch code (which is "architecture specific assembly").
Line 846:
With that done, we want some functions to acquire a semaphore or a mutex:
 
<sourcesyntaxhighlight lang="c">
void acquire_semaphore(SEMAPHORE * semaphore) {
lock_stuff();
Line 869:
acquire_semaphore();
}
</syntaxhighlight>
</source>
 
Lastly, we need to be able to release the semaphore or mutex: