From 8867d1fedf7baa4275a68440f42ed9b5cb790f49 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Sat, 24 Oct 2026 16:47:57 +0900 Subject: [PATCH 1/3] support freertos --- zephyr/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 5e2db49..b1139f3 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -74,4 +74,8 @@ config DMOSAL_QUEUE_MSG_NUM_MAX int "Maximum number of messages per queue" default 16 +config DMOSAL_QUEUE_MSG_NUM_MAX + int "Maximum number of messages per queue" + default 8 + endif # DMOSAL From 4e9672de6e5c9418ba1fd8c857414ef33a6c1ae4 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Sat, 24 Oct 2026 17:04:21 +0900 Subject: [PATCH 2/3] fixed ci error --- zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zephyr/Kconfig b/zephyr/Kconfig index b1139f3..d79eea0 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -76,6 +76,6 @@ config DMOSAL_QUEUE_MSG_NUM_MAX config DMOSAL_QUEUE_MSG_NUM_MAX int "Maximum number of messages per queue" - default 8 + default 16 endif # DMOSAL From b91e5af3aa51e20a486e46d443bc82764ab52dc4 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Sat, 24 Oct 2026 17:45:16 +0900 Subject: [PATCH 3/3] clang tidy scan for backend and update readme --- .github/workflows/ci.yml | 4 +++ README.md | 78 ++++++++++++++++++++++------------------ docs/architecture.md | 5 ++- freertos/Dockerfile | 4 +++ freertos/docker.sh | 7 +++- justfile | 10 ++++++ zephyr/CMakeLists.txt | 7 ++++ zephyr/Dockerfile | 4 +++ zephyr/docker.sh | 12 ++++++- 9 files changed, 94 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c449117..4c7083b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,6 +193,8 @@ jobs: run: zephyr/docker.sh run - name: Build and run cmocka tests run: zephyr/docker.sh test + - name: clang-tidy (backend sources) + run: zephyr/docker.sh tidy freertos: name: freertos posix simulator (examples + tests) @@ -219,6 +221,8 @@ jobs: run: freertos/docker.sh run - name: Run cmocka tests run: freertos/docker.sh test + - name: clang-tidy (backend sources) + run: freertos/docker.sh tidy docs: name: docs (build) diff --git a/README.md b/README.md index bdb737a..47fe33a 100644 --- a/README.md +++ b/README.md @@ -8,59 +8,67 @@ A small, portable C abstraction layer for tasks, mutexes, semaphores, queues, timers and time, with the same semantics on every supported OS. -All resources are statically allocated up front, so there is no `malloc` on -any hot path and worst-case memory use is known in advance. New backends can -be added behind the same API without breaking existing callers. +All resources are statically allocated up front, so the code in dmosal itself +never calls `malloc` on any hot path and its worst-case memory use is known in +advance. This does not cover the OS calls underneath: pthreads, POSIX message +queues and timers on Linux, or the FreeRTOS kernel in dynamic allocation mode, +may allocate internally. New backends can be added behind the same API without +breaking existing callers. ## Supported backends -| Backend | Source | Tested on | Details | -|----------|---------------------------------|------------------------------------|----------------------------------------| -| Linux | [source/linux/](source/linux/) | Native Linux (pthreads, POSIX IPC) | Quick start | -| Zephyr | [source/zephyr/](source/zephyr/) | `native_sim` virtual board (Docker) | [zephyr/README.md](zephyr/README.md) | -| FreeRTOS | [source/freertos/](source/freertos/) | POSIX/Linux simulator (Docker) | [freertos/README.md](freertos/README.md) | -| ... | your own, see [docs/porting.md](docs/porting.md) | | | +| Backend | Source | Tested on | Details | +|----------|--------------------------------------------------|-------------------------------------|------------------------------------------| +| Linux | [source/linux/](source/linux/) | Native Linux (pthreads, POSIX IPC) | Quick start below | +| Zephyr | [source/zephyr/](source/zephyr/) | `native_sim` virtual board (Docker) | [zephyr/README.md](zephyr/README.md) | +| FreeRTOS | [source/freertos/](source/freertos/) | POSIX/Linux simulator (Docker) | [freertos/README.md](freertos/README.md) | +| ... | your own, see [docs/porting.md](docs/porting.md) | | | The same [examples](examples/) and [cmocka tests](test/) run unchanged on every backend. The Zephyr and FreeRTOS targets need no hardware. More backends can be added behind the same API. ``` -+-------------------------------+ -| Application | -+---------------+---------------+ -| dmosal | libc | -+---------------+---------------+ -| Linux | Zephyr | FreeRTOS | ...| -+-------------------------------+ ++-------------------------------------------------+ +| Application | ++-------------------------------------------------+ + | ++-------------------------------------------------+ +| dmosal public API | ++-------------------------------------------------+ + | ++----------+ +----------+ +----------+ +----------+ +| Linux | | Zephyr | | FreeRTOS | | ... | ++----------+ +----------+ +----------+ +----------+ ``` ## Quick start -Install the dependencies, then build and test on Linux: +On Linux you only need a compiler, CMake and cmocka: ``` -sudo apt install cmake libcmocka-dev doxygen -just check # configure, build, run tests -just build # build the examples +sudo apt install cmake libcmocka-dev +just check # build and run the tests +just run-examples # build and run the examples ``` -No toolchain locally? Use the pinned [`Dockerfile`](Dockerfile): +The `just` recipes are thin wrappers around `cmake` and `ctest`. Without +`just`, run the equivalent commands from the [`justfile`](justfile). + +The [`Dockerfile`](Dockerfile) provides the full toolchain: ``` docker build -t dmosal-dev . docker run --rm -v "$PWD":/workspace -w /workspace dmosal-dev just check ``` -Without [`just`](https://github.com/casey/just), the [`justfile`](justfile) -recipes are plain `cmake`/`ctest` commands you can run directly. - -Resource limits (number of tasks, queues, ...) are set at configure time in -[osal_config.cmake](osal_config.cmake). +Resource pool sizes (tasks, queues, mutexes, etc.) are fixed at build time in +[osal_config.cmake](osal_config.cmake) and can be overridden, e.g. +`cmake -DOSAL_CONFIG_QUEUE_NUM_MAX=8 ..`. ## Zephyr and FreeRTOS -Both run inside Docker, so no local SDK is needed: +Both backends run inside Docker, so no local SDK is required: ``` just zephyr-build # build examples and tests for native_sim @@ -72,20 +80,22 @@ just freertos-run # run the examples just freertos-test # run the cmocka tests ``` -## Other recipes +## More checks -`just check-valgrind`, `check-asan`, `check-tsan`, `check-coverage`, `doc`, -`format`, `tidy`. Run `just --list` for everything. +Additional recipes: `just check-valgrind`, `check-asan`, `check-tsan` and +`check-coverage` for dynamic analysis, `just format` and `just tidy` for style +checks (`just zephyr-tidy` and `just freertos-tidy` for the RTOS backends). +`just --list` shows all recipes. ## Documentation -- API reference (Doxygen): `just doc` → `build/doc/html/`. -- Design docs: [docs/](docs/README.md) (architecture, API spec, lifetime, - thread safety, porting guide). +`just doc` builds the API reference into `build/doc/html/` (requires +`doxygen`). Design documents are in [docs/](docs/README.md): architecture, API +spec, object lifetime, thread safety and the porting guide. ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) for building, testing and style. +See [CONTRIBUTING.md](CONTRIBUTING.md) for build, test and code style requirements. ## License diff --git a/docs/architecture.md b/docs/architecture.md index 36638a4..fd4e587 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -5,7 +5,10 @@ `dmosal` is a thin OS abstraction layer with a **static-allocation** ethos: every resource (mutex, semaphore, task, timer, queue, tmcheck) comes from a fixed-size pool sized at compile time. Applications acquire resources at -initialization, then run without further heap allocation. The layer is +initialization, then run without further heap allocation in dmosal's own code. +The OS or library calls underneath (for example pthreads, POSIX message +queues and timers, or the FreeRTOS kernel in dynamic mode) may still allocate +internally, and dmosal does not control that. The layer is designed for embedded / real-time contexts where predictable memory behaviour matters more than dynamic flexibility. diff --git a/freertos/Dockerfile b/freertos/Dockerfile index 316ace9..1fed519 100644 --- a/freertos/Dockerfile +++ b/freertos/Dockerfile @@ -20,4 +20,8 @@ RUN mkdir -p ${FREERTOS_KERNEL_PATH} \ | tar -xz -C ${FREERTOS_KERNEL_PATH} --strip-components=1 \ && chmod -R a+rX ${FREERTOS_KERNEL_PATH} +# Static analysis of the backend sources (docker.sh tidy). +RUN apt-get update && apt-get install -y --no-install-recommends clang-tidy \ + && rm -rf /var/lib/apt/lists/* + WORKDIR /dmosal diff --git a/freertos/docker.sh b/freertos/docker.sh index 43811de..9657c30 100755 --- a/freertos/docker.sh +++ b/freertos/docker.sh @@ -6,6 +6,7 @@ # freertos/docker.sh build # build every examples/*.c and test/osal/*_test.c into build-freertos/ # freertos/docker.sh run # run the examples # freertos/docker.sh test # run the cmocka tests (ctest) +# freertos/docker.sh tidy # clang-tidy over source/freertos/*.c # freertos/docker.sh shell # interactive shell in the container # # CMAKE_ARGS=-DDYNAMIC_ALLOC=ON builds against the kernel's dynamic allocation API instead @@ -38,11 +39,15 @@ run) test) "${DOCKER_RUN[@]}" "$IMAGE" ctest --test-dir "$BUILD" --output-on-failure ${TEST:+-R "^$TEST\$"} ;; +tidy) + "${DOCKER_RUN[@]}" "$IMAGE" sh -c \ + "cmake -S freertos/app -B build-freertos-tidy -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON >/dev/null && cmake --build build-freertos-tidy >/dev/null && clang-tidy -p build-freertos-tidy --quiet --warnings-as-errors='*' source/freertos/*.c" + ;; shell) "${DOCKER_RUN[@]}" -it "$IMAGE" bash ;; *) - sed -n "2,10p" "$0" + sed -n "2,11p" "$0" exit 1 ;; esac diff --git a/justfile b/justfile index 2f04d55..c179a87 100644 --- a/justfile +++ b/justfile @@ -19,10 +19,12 @@ # just zephyr-build # build the examples for Zephyr native_sim (Docker) # just zephyr-run # run the Zephyr examples # just zephyr-test # run the cmocka tests on Zephyr native_sim (TEST= for one) +# just zephyr-tidy # clang-tidy over source/zephyr (Docker) # just zephyr-shell # shell inside the Zephyr container # just freertos-build # build examples + tests for the FreeRTOS POSIX simulator (Docker) # just freertos-run # run the FreeRTOS examples # just freertos-test # run the cmocka tests on the FreeRTOS simulator (TEST= for one) +# just freertos-tidy # clang-tidy over source/freertos (Docker) # just freertos-shell # shell inside the FreeRTOS container # just clean # remove build directories @@ -88,6 +90,14 @@ tidy: cmake --build {{build_dir}} --target dmosal -j{{jobs}} pre-commit run clang-tidy --all-files --hook-stage manual +# Run clang-tidy over the Zephyr backend inside Docker +zephyr-tidy: + zephyr/docker.sh tidy + +# Run clang-tidy over the FreeRTOS backend inside Docker +freertos-tidy: + freertos/docker.sh tidy + # Build the examples for Zephyr native_sim inside Docker (EXAMPLE= for one) zephyr-build: zephyr/docker.sh build diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 6f353c1..ea60d23 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -61,4 +61,11 @@ zephyr_library_sources( "${DMOSAL_ROOT}/source/zephyr/osal_timer.c" ) +# Same extra warnings as the other backends, except -Wpedantic and -Wconversion: Zephyr builds +# with a strict -std that rejects the variadic log macros, and its own headers trigger both +# (they are not system headers). Conversions are covered by clang-tidy (just zephyr-tidy). +zephyr_library_compile_options( + -Wshadow -Wcast-align -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes +) + endif() diff --git a/zephyr/Dockerfile b/zephyr/Dockerfile index 2d9a50f..626a6f3 100644 --- a/zephyr/Dockerfile +++ b/zephyr/Dockerfile @@ -36,4 +36,8 @@ RUN mkdir -p /opt/cmocka \ # west and cmake write caches inside the Zephyr tree, and the container runs as the host user. RUN mkdir -p /opt/zephyrws/zephyr/.cache && chmod -R a+rwX /opt/zephyrws/.west /opt/zephyrws/zephyr/.cache +# Static analysis of the backend sources (docker.sh tidy). +RUN apt-get update && apt-get install -y --no-install-recommends clang-tidy \ + && rm -rf /var/lib/apt/lists/* + WORKDIR /dmosal diff --git a/zephyr/docker.sh b/zephyr/docker.sh index c689e9c..c26c4ba 100755 --- a/zephyr/docker.sh +++ b/zephyr/docker.sh @@ -6,6 +6,7 @@ # zephyr/docker.sh build # build every examples/*.c into build-zephyr/ # zephyr/docker.sh run # run them all # zephyr/docker.sh test # build + run every test/osal/*_test.c (cmocka) on native_sim +# zephyr/docker.sh tidy # clang-tidy over source/zephyr/*.c # zephyr/docker.sh shell # interactive shell in the container # # EXAMPLE= limits build/run to one file from examples/. @@ -62,11 +63,20 @@ test) exit 1 fi ;; +tidy) + # clang does not know a few gcc-only flags that Zephyr passes, so they are dropped from the + # compilation database. + "${DOCKER_RUN[@]}" "$IMAGE" sh -c \ + "west build -b $BOARD -d build-zephyr-tidy zephyr/app -p auto -- -DEXAMPLE=queue_sample -DCMAKE_EXPORT_COMPILE_COMMANDS=ON >/dev/null && + mkdir -p build-zephyr-tidy/db && + sed -e 's/ -fno-freestanding//g; s/ -fno-reorder-functions//g' build-zephyr-tidy/compile_commands.json > build-zephyr-tidy/db/compile_commands.json && + clang-tidy -p build-zephyr-tidy/db --quiet --warnings-as-errors='*' source/zephyr/*.c" + ;; shell) "${DOCKER_RUN[@]}" -it "$IMAGE" bash ;; *) - sed -n "2,10p" "$0" + sed -n "2,11p" "$0" exit 1 ;; esac