Go to file
alexis 67d79fc935 Add a readme 2023-02-05 16:40:48 -07:00
inc Add UTASK_INIT 2023-02-05 16:32:31 -07:00
src Define stack by bottom and size 2023-02-03 19:48:22 -07:00
README.md Add a readme 2023-02-05 16:40:48 -07:00
meson.build Initial import of task from xutil 2023-02-03 10:55:09 -07:00

README.md

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

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.