parent
c4760c282a
commit
67d79fc935
@ -0,0 +1,66 @@
|
||||
# utask
|
||||
|
||||
utask (micro-task) is an extremely lightweight cooperative multitasking
|
||||
library. µTasks are simply executed round-robin until each one yields.
|
||||
|
||||
By using compiler extensions in the form of synchronization builtins and
|
||||
carefully constructed clobber lists, utask gets an absolutely minimal context
|
||||
switch. Instead of saving and restoring all registers every time (on some
|
||||
architectures this is a lot — a RISC-V with floating point has 63 registers!),
|
||||
utask simply invalidates all registers before the context switch. This tells
|
||||
the compiler that after the switch, it is responsible for recomputing the
|
||||
contents of any registers that had active allocations. This is _much_ faster,
|
||||
because chances are, you do not have all 63 registers in use at once.
|
||||
|
||||
## Supported architectures
|
||||
|
||||
- RISC-V
|
||||
|
||||
## API example
|
||||
|
||||
```c
|
||||
static void task1_f(uintptr_t arg);
|
||||
static void task2_f(uintptr_t arg);
|
||||
|
||||
utask_decl_stack(task1_s, 1024);
|
||||
utask_decl_stack(task2_s, 1024);
|
||||
|
||||
utask_t task1 = {
|
||||
.func = task1_f,
|
||||
.stack = task1_s,
|
||||
.stack_size = sizeof(task1_s),
|
||||
.name = "task1",
|
||||
UTASK_INIT
|
||||
};
|
||||
|
||||
utask_t task2 = {
|
||||
.func = task2_f,
|
||||
.stack = task2_s,
|
||||
.stack_size = sizeof(task2_s),
|
||||
.name = "task2",
|
||||
UTASK_INIT
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
utask_add(&task2, 0);
|
||||
utask_add(&task1, 0);
|
||||
utask_run();
|
||||
}
|
||||
|
||||
static void task1_f(uintptr_t arg)
|
||||
{
|
||||
printf("Hello, ");
|
||||
utask_yield();
|
||||
}
|
||||
|
||||
static void task2_f(uintptr_t arg)
|
||||
{
|
||||
printf("world!\n");
|
||||
utask_yield();
|
||||
}
|
||||
```
|
||||
|
||||
## Copying
|
||||
|
||||
This code may not be used by anybody for any purpose. Be gay, do crime.
|
Loading…
Reference in new issue