https://github.com/brunexgeek/utask
Single file library implementing userspace cooperative multitasking
https://github.com/brunexgeek/utask
cooperative-multitasking coroutines multitasking ucontext userspace
Last synced: 3 months ago
JSON representation
Single file library implementing userspace cooperative multitasking
- Host: GitHub
- URL: https://github.com/brunexgeek/utask
- Owner: brunexgeek
- License: apache-2.0
- Created: 2022-01-23T02:50:38.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2023-09-24T17:05:05.000Z (over 1 year ago)
- Last Synced: 2025-01-10T01:53:04.079Z (4 months ago)
- Topics: cooperative-multitasking, coroutines, multitasking, ucontext, userspace
- Language: C
- Homepage: https://brunocosta.net.br/project/utask/
- Size: 10.7 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# utask: userspace cooperative mutitasking
`utask` is a single file library implementing userspace cooperative multitasking inside native threads. Tasks have many-to-one relantionship with native threads (i.e. each thread has its own tasks) and you can create up to 128 tasks per thread.
By default, `utask` can be used only by one thread. If you want to use it in more threads, define `UTASK_MULTI_THREAD` before including `utask.h`. Defining `UTASK_MULTI_THREAD` incurs additional overhead to retrieve per thread internal information.
This library requires [ucontext](https://pubs.opengroup.org/onlinepubs/7908799/xsh/ucontext.h.html) API provided by GNU/Linux and some other operating systems.
## Usage
Include `utask.h` in your project. You can include `utask.h` in any source file, but one of them (and only one) must define `UTASK_IMPL` before including it. That tells `utask` to define the library implementation. If you want to use tasks in more than one thread, also defines `UTASK_MULTI_THREAD`.
```
/* #define UTASK_MULTI_THREAD */
#define UTASK_IMPL
#include "utask.h"
```Before using any function you must initialize the task scheduler in the current thread with `utask_initialize`. The default number of tasks is 8 and the default stack size is 16 KiB. Always check the return value for errors.
```
int result = utask_initialize(2, UT_DEFAULT, UT_DEFAULT);
if (result != UT_EOK)
abort("Failure");
```Now just create some tasks and start the task scheduler to run them. The function `utask_run` will block the execution until all tasks are finished. Make sure that inside `my_function_1` and `my_function_2` you call `utask_yield` regularly to give up processor time to other tasks. You can also create tasks inside other tasks.
```
utask_create(my_function_1, NULL);
utask_create(my_function_2, NULL);
utask_run();
printf("Finished running all tasks!\n");
```Remember to terminate the task scheduler to release the allocated resources.
```
utask_terminate();
```## API
### utask_initialize
`int utask_initialize( int max, int stack_size, int flags )`
Initialize the task scheduler for the current thread.
If `UTASK_MULTI_THREAD` is not defined before `utask.h` is included
only one thread can use tasks. Otherwise, this function can be called
for each thread to initialize its task scheduler.This function must be called outside a task.
### utask_terminate
`int utask_terminate()`
Terminate the task scheduler for the current thread.
This function must be called outside a task.
### utask_create
`int utask_create(void (*func)(void*), void *arg)`
Create a new task and add it in the task scheduler's running queue. The return value is the task identifier (same value returned by `utask_id` function).
This function can be called inside and outside a task.
### utask_run
`int utask_run()`
Run the task scheduler until all tasks are completed.
Tasks are selected via round-robin algorithm.
### utask_yield
`int utask_yield()`
Relinquish control and enables the task scheduler run another task.
### utask_id
`int utask_id()`
Returns the current task identifier.
### utask_count
`int utask_count()`
Returns the number of tasks in runnable state.
### utask_info
`int utask_info( utask_info_t *info )`
Returns information about the task scheduler state.
# Stack size
There is no simple and portable way to accurately check for stack overflows. Furthermore, the task stack does not grow as needed, as operating systems usually do with threads. The library attempts to perform rudimentary validations to detect possible stack overflows, but this is not sufficient to ensure execution stability (especially if the call graph is deep). Be sure to test your application to verify that the specified stack size is sufficient for various use cases.