cfiber provides an efficient implementation of fibers (also known as stackful coroutines, non-preemptive threads, or cooperative threads) with support for multiple architectures:
- x86_64 (Linux only)
- AArch64 (ARM 64-bit)
- ARM Cortex-M (M0, M0+, M3, M4, M7) with optional FPU support
Fibers enable cooperative multitasking where tasks explicitly yield control, making them ideal for:
- Async I/O frameworks
- Embedded systems with resource constraints
- Game engines and simulation loops
- Any scenario where deterministic, low-overhead task switching is required
- Zero dependencies - Pure C and assembly implementation
- Minimal overhead - Direct context switching without OS scheduler involvement, no dynamic memory allocation
- Portable - Clean separation of architecture-specific code
- Embedded-friendly - Designed for bare-metal ARM Cortex-M microcontrollers
- ABI-compliant - Follows platform calling conventions (System V AMD64, AAPCS, AAPCS64)
- FPU support - Optional floating-point context preservation on ARM Cortex-M4F/M7F
This library is freestanding-compatible and can be used in
environments without a standard C library. It only depends on
freestanding headers (<stdint.h>, <stddef.h>) and requires
no runtime support.
Suitable for:
- Embedded systems
- Bootloaders
- Kernel development
- Any
-ffreestandingcompilation target
| Architecture | Status | Notes |
|---|---|---|
| x86_64 | Supported | Linux (System V AMD64 ABI) |
| AArch64 (ARM64) | Supported | 64-bit ARM (AAPCS64) |
| ARM Cortex-M0 | Supported | ARMv6-M (Thumb-1) |
| ARM Cortex-M0+ | Supported | ARMv6-M (Thumb-1) |
| ARM Cortex-M3 | Supported | ARMv7-M (Thumb-2) |
| ARM Cortex-M4 | Supported | ARMv7-M with optional FPU |
| ARM Cortex-M7 | Supported | ARMv7E-M with optional FPU |
The easiest way to integrate cfiber into your CMake project is using add_subdirectory:
-
Add cfiber as a subdirectory in your project:
# Option 1: Clone as a git submodule git submodule add https://github.com/aotodev/cfiber.git external/cfiber # Option 2: Copy the cfiber directory into your project cp -r /path/to/cfiber_external/cfiber
-
Update your CMakeLists.txt:
cmake_minimum_required(VERSION 3.28) project(my_project) # Add cfiber as a subdirectory add_subdirectory(external/cfiber) # Create your executable add_executable(my_app main.c) # Link against cfiber target_link_libraries(my_app PRIVATE cfiber) # cfiber's include directories are automatically available
-
Use in your code:
#include "cfiber/fiber.h" #include "cfiber/context.h" // Your code here
The cfiber library will automatically detect your target architecture and build accordingly. For cross-compilation to ARM Cortex-M, ensure you set up your toolchain file before calling add_subdirectory().
- CMake 3.28 or newer
- GCC/Clang for x86_64 and AArch64
- ARM GCC toolchain for ARM Cortex-M targets
Note: cfiber uses GNU extensions and is supported only by GNU compilers (GCC, aarch64-linux-gnu-gcc, arm-none-eabi-gcc, etc.) and LLVM (Clang). Other compilers are not supported.
# Build library
mkdir build && cd build
cmake ..
make
# Build with sample
cmake -DBUILD_SAMPLE=ON ..
make
./sample/sample
# Build with tests
cmake -DBUILD_TESTS=ON ..
make
ctest# Example for Cortex-M4 with FPU
mkdir build-arm && cd build-arm
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../utils/cmake/toolchain-arm.cmake \
-DCFIBER_SYSTEM_PROCESSOR=arm \
-DCFIBER_TARGET_CPU=cortex-m4 \
-DCFIBER_ARM_FLOAT_ABI=hard \
-DCFIBER_ARM_FPU=fpv4-sp-d16 \
-DBUILD_TESTS=ON
make- CFIBER_TARGET_CPU:
cortex-m0,cortex-m0plus,cortex-m3,cortex-m4,cortex-m7 - CFIBER_ARM_FLOAT_ABI:
soft,softfp,hard(required for FPU support) - CFIBER_ARM_FPU:
fpv4-sp-d16,fpv5-d16, etc. (defines FPU to use)
For Cortex-M4/M7 with FPU (hardware floating-point):
-DCFIBER_ARM_FLOAT_ABI=hard -DCFIBER_ARM_FPU=fpv4-sp-d16For Cortex-M0/M0+/M3 (no FPU):
-DCFIBER_ARM_FLOAT_ABI=softThe project includes a helper script for common build configurations:
./utils/make.sh
# Examples:
./utils/make.sh --arch=aarch64
./utils/make.sh --arch=arm --cpu=cortex-m4
# for debug build. Default is release
./utils/make.sh --arch=aarch64 -d
# native build
./utils/make.sh #include "cfiber/fiber.h"
#include "cfiber/context.h"
#include <stdio.h>
#include <stdlib.h>
// Define a fiber function
void my_fiber(void* user_data) {
int* counter = (int*)user_data;
while (*counter > 0) {
printf("Fiber running: %d\n", *counter);
(*counter)--;
// Yield control back to scheduler
yield();
}
printf("Fiber complete!\n");
}
int main() {
// Allocate stack for the fiber
const size_t stack_size = 8192;
uint8_t* stack = malloc(stack_size);
// Create and initialize fiber
fiber_t fiber = {
.stack = stack,
.stack_size = stack_size
};
int counter = 5;
init_fiber(&fiber, my_fiber, &counter);
// In a real scheduler, you would call switch_context
// to switch between fibers and the main scheduler context
free(stack);
return 0;
}See the sample/ directory for a complete working example with:
- Multiple fiber scheduling
- Nested fiber spawning
- Graceful fiber completion handling
- Round-robin scheduling implementation
The sample demonstrates:
// Initialize runtime with stack size
scheduler_init(8192);
// Spawn fibers
scheduler_spawn(my_function, user_data);
scheduler_spawn(another_function, other_data);
// Start scheduler (blocks until all fibers complete)
scheduler_run();
// Cleanup
scheduler_cleanup();Building and runing the example:
- using the host architecture
# Release by default
./utils/make.sh -s
# try in debug
./utils/make.sh -s -d- cross compiling and running with qemu
./utils/make.sh --arch=aarch64 -s
./utils/make.sh --arch=arm --cpu=cortex-m4 -s
# with FPU(script sets all FPU required flags)
./utils/make.sh --arch=arm --cpu=cortex-m7 -sFor complete API documentation including all types, functions, and architecture-specific details, see:
Core Types:
fiber_t- Fiber structure (context, stack pointer, stack size)fiber_fn- Function signature for fiber entry points
Core Functions:
init_fiber()- Initialize a fiber with a function and user dataswitch_context()- Switch between execution contextsscheduler_return_fiber()- Scheduler callback (you implement this)
See the full API reference for detailed documentation, usage examples, and platform-specific information.
For comprehensive documentation about how cfiber works internally, see:
This includes:
- How context switching works
- Fiber initialization process
- Memory layout and stack management
- Platform-specific implementation details
- Performance characteristics and optimization tips
- FPU handling on ARM Cortex-M
- Integration with RTOS
- Usage guidelines and best practices
The project includes comprehensive unit tests for all architectures:
# Native tests (x86_64/AArch64)
./utils/make.sh -t
# Cross-compile and test with qemu
./utils/make.sh --arch=aarch64 -t
./utils/make.sh --arch=arm --cpu=cortex-m0 -t # armv6
./utils/make.sh --arch=arm --cpu=cortex-m3 -t # armv7 without FPU
./utils/make.sh --arch=arm --cpu=cortex-m7 -t # armv7 with FPUTest coverage includes:
- Basic context switching
- Register preservation
- Stack integrity
- FPU register preservation (ARM)
- Multiple fiber coordination
This project is licensed under the MIT License - see the LICENSE file for details.