POSKI (Portable Operating System Kernel Interface) is a lightweight Operating System Abstraction Layer (OSAL) that began as the CHIP OSAL in Project CHIP (now Matter). POSKI acts as a "POSIX for embedded," providing a thin C and C++ abstraction layer that ensures seamless application portability across RTOS and host targets.
By bridging kernels like FreeRTOS, Zephyr, RT-Thread, and POSIX (Linux/macOS), POSKI empowers a single codebase to traverse the entire development lifecycle: host-based simulation, bring-up testing, and the final production environment. This ensures long-term portability, future-proofing applications against RTOS shifts while ending platform fragmentation.
The name POSKI (and the pos_ / poski:: namespaces) disambiguates this OSAL
from external OSAL layers used by other projects or vendor SDKs.
POSKI is designed to provide a thin adaptation layer for portability of embedded applications and device layers across a range of Real-Time Operating Systems (RTOS) and host platforms. The intent is to leverage native OS primitives as much as possible while providing a unified C and C++ interface surface for those primitives, and to deliver common OS functionality suitable for deeply embedded environments.
POSKI provides abstractions for:
| Module | C API | C++ API | Summary |
|---|---|---|---|
| Task | <poski/osal/os_task.h> |
poski::OsTask |
Independent threads of execution |
| Mutex | <poski/osal/os_mutex.h> |
poski::OsMutex |
Recursive mutual exclusion |
| Semaphore | <poski/osal/os_sem.h> |
poski::OsSemaphore |
Counting semaphores |
| Critical section | <poski/osal/os_crit.h> |
poski::OsCriticalSection |
Interrupt-masking mutual exclusion |
| Queue | <poski/osal/os_queue.h> |
poski::OsQueue<T, N> |
Fixed-size message queues (copy semantics) |
| Event queue | <poski/osal/os_event.h> |
poski::OsEvent, OsEventQueue, OsEventTimer |
Allocation-free intrusive event queue |
| Timer | <poski/osal/os_timer.h> |
poski::OsTimer |
One-shot software timers |
| Time | <poski/osal/os_time.h> |
poski::OsTime |
System time and tick/millisecond conversion |
| Scheduler | <poski/osal/os_sched.h> |
poski::OsTask |
Start and query the scheduler |
| Panic | <poski/osal/os_panic.h> |
— | Fatal error handler |
| Ring buffer | — | poski::OsRing |
Ring buffer of fixed-size items |
<poski/osal/osal.h> includes every C module. Each C++ class poski::OsX is
defined in its own header-only <poski/OsX.h>.
| Target | Port | Native primitives | Build | CI | Status |
|---|---|---|---|---|---|
| Linux | targets/posix |
pthreads, sem_t, timer_create, clock_gettime |
Make; Bazel :osal_posix |
Build and all tests | Supported; reference port |
| macOS | targets/posix |
pthreads, dispatch_semaphore, dispatch_source, Mach clock_get_time |
Make; Bazel :osal_posix |
— | Supported; not CI-tested |
| FreeRTOS | targets/freertos |
Tasks, recursive mutexes, counting semaphores, queues, software timers | Bazel :osal_freertos (compile check); Make PLATFORM=nrf52840 |
Bazel compile check | Supported; no pos_queue_set_signal_cb |
| Zephyr | targets/zephyr |
k_thread, k_mutex, k_sem, k_msgq, k_timer, k_uptime_get |
Bazel :osal_zephyr (manual; needs Zephyr headers) |
— | Experimental; no pos_sched_* |
| RT-Thread | targets/rt-thread |
rt_thread, rt_mutex, rt_sem, rt_mq, rt_timer, rt_tick_get |
None in-tree | — | Partial; some timer, queue, and scheduler functions missing |
- Thin, native mapping. Each POSKI object wraps the closest native
primitive (for example,
pos_semis a FreeRTOS counting semaphore, a Zephyrk_sem, or a POSIXsem_t). POSKI adds no scheduler, timer service, or IPC mechanism of its own. - Caller-owned objects. Every object is a
struct pos_*that the caller allocates (statically, on a stack, or embedded in another struct) and passes by pointer; the API never hands out heap-allocated handles. Where a native API allocates internally (FreeRTOSx*Create(), RT-Threadrt_*_create(), and the POSIX and Zephyr queue buffers), the port inherits that behavior. - One predictable namespace. C functions are named
pos_<module>_<verb>(), constants arePOS_*, most calls return apos_error_t, and C++ classes areposki::Os*. - Lightweight C++. The C++ wrappers are header-only RAII classes that
hold the C object by value (plus small bookkeeping such as an init flag or
lock depth) and expose it through
GetNative(). They need no virtual functions, exceptions, or RTTI, and onlyOsRingallocates (its buffer, withnew[]). - Host-first testing. The same portable tests in
tests/run on Linux and macOS through Make or Bazel, as plain executables or as GoogleTest cases, before the code reaches a target.
POSKI grew out of the goals of Project CHIP: a unifying, interoperable, versatile, low-overhead, and robust connected-home solution with an explicit focus on time-to-market. These goals require the platform layer design to be highly scalable, allowing disparate and diverse platforms to be integrated with high velocity. Supporting rapid integration of new platforms in a scalable and maintainable way requires:
- Maximum reuse of code, verification, and host-side unit testing
- Minimum code fragmentation, forking, and conditional compilation
- Adaptable and thin pathway to optimized native RTOS APIs
Device platforms tend to be highly unique on the first order, but also pivot on three major axes of common functionality. These axes define a three-dimensional matrix of possible device configurations, where a shared point on any one axis allows code reuse across otherwise disparate platforms:
-
Device (board)
- Platforms that share a specific choice of chip combinations and wiring
at the PCB level can share a common device layer port (for example, a
Matter
DeviceLayerport). - The device layer provides the minimum interface required to connect the application stack to all the hardware-specific details of a device, such as BLE, Wi-Fi, and storage.
- Target examples are silicon vendor development boards or final product PCBs.
- A device layer is able to own all decisions about a device and impose hard assumptions on the particular combination of board + OS + HW.
- A device layer is also free to use an abstraction of the underlying OS or HW layers, such as POSKI, to provide better portability between RTOS environments or across a family of SoCs.
- Platforms that share a specific choice of chip combinations and wiring
at the PCB level can share a common device layer port (for example, a
Matter
-
Operating system (OS)
- Platforms that share a common OS or RTOS can share a common POSKI port
(
targets/freertos,targets/zephyr,targets/rt-thread,targets/posix). - Target examples are FreeRTOS, Zephyr, RT-Thread, Linux, and macOS.
- A given app or device layer codebase may need to be retargeted from one OS to another. This could happen during an upgrade cycle, for instance, or when a new product wants to use an existing device layer port but on the RTOS it typically uses.
- An application or driver stack written against POSKI runs unchanged in Linux/macOS host unit tests and on target RTOS firmware.
- Platforms that share a common OS or RTOS can share a common POSKI port
(
-
Hardware (HW / SoC)
- Platforms that share a common chipset, SoC, or silicon can share a common Hardware Abstraction Layer (HAL) from the vendor SDK.
- By leveraging a HAL, the same application can be retargeted to different chipsets across a family of similar SoCs.
The primary motivation of POSKI is to enable code sharing and reuse in applications and device layers. Rather than having a separate example app for each combination of HW + OS + board, POSKI allows an app to be written in a common way and be retargeted to a different OS/RTOS such as FreeRTOS, Zephyr, or Linux. POSKI is intended to help keep the system scalable as the matrix of HW + OS + app combinations grows over time.
There is a long history of OSAL layers. Why does POSKI exist?
While it is true that POSKI is "Yet Another OSAL," it was designed to meet the specific requirements of Project CHIP. Other OSAL projects were considered, some with contributors in common with POSKI, but each had gaps relative to those requirements:
-
nler — Nest Labs Embedded Runtime
- Uses event queues with event-pointer semantics, whereas POSKI's core IPC primitive is the message queue with copy semantics, which maps directly onto native RTOS queues.
- Has an inconsistent API namespace, whereas all POSKI C functions
predictably begin with
pos_(originallychip_os_). - Was designed to enforce a particular embedded programming philosophy; semaphores, for example, are notably missing.
- Imposes its own centralized timer system rather than providing a thin pass-through to native OS timers. That timer system relies on nler event queues, which are antithetical to the message-queue paradigm.
-
npl — Apache Mynewt NimBLE Porting Layer
- Uses event queues with event-pointer semantics, whereas POSKI's core IPC primitive is the message queue with copy semantics.
- Is embedded within a larger BLE stack project and as such isn't easily composable as a submodule.
- Uses a consistent but domain-specific API namespace:
ble_npl_.
- Make builds: GNU Make, GCC (Linux) or Clang (macOS), and
ccache, which the Makefiles use to invoke the compiler.make gtestalso needscurlto download GoogleTest. - Bazel builds: Bazel with Bzlmod
(Bazelisk is recommended) and
Clang, which
.bazelrcselects. Bazel fetches GoogleTest and the FreeRTOS kernel automatically.
sudo apt install build-essential ccache clang curl
# Then install Bazel, for example with Bazelisk.xcode-select --install # Clang and make
brew install ccache bazeliskmake # POSIX library: tests/libosal.a
make test # build and run the C and C++ tests
make gtest # download GoogleTest v1.14.0 into tests/, then build and run the gtest suites
make clean # remove build outputs, including the GoogleTest downloadmake -C tests all builds the library and the test executables without running
them.
To build the FreeRTOS port for the Nordic nRF52840, using the FreeRTOS
kernel and configuration bundled with the nRF5 SDK (override them with
FREERTOS_DIR and FREERTOS_CONFIG_DIR) and the arm-none-eabi- toolchain:
# Export the path to the Nordic nRF5 SDK
export NRF5_SDK_ROOT=/path/to/nRF5_SDK_17.1.0_ddde560
PLATFORM=nrf52840 make # tests/libosal_freertos.a
PLATFORM=nrf52840 make -C tests all # plus test firmware images (tests/*.hex)bazel build //... # POSIX and FreeRTOS libraries and all test binaries
bazel test //... # run every test
bazel test //:test # C and C++ tests only
bazel test //:gtest # GoogleTest suites only
bazel build //:test //:gtest # build the test binaries without running themTo build a single library:
bazel build //:osal # POSIX (alias of //:osal_posix)
bazel build //:freertos # FreeRTOS (alias of //:osal_freertos)//:osal_freertoscompiles the port against the FreeRTOS-Kernel V10.4.3 headers using the POSIX simulator configuration intargets/freertos/config/posix/. It checks that the port builds; it does not link a kernel.//:osal_zephyr(alias//:zephyr) is taggedmanual, so wildcard patterns such as//...skip it; building it requires the Zephyr headers and toolchain..bazelrcdisables thebazel-*convenience symlinks. Usebazel info bazel-binorbazel info bazel-testlogsto find outputs.
GitHub Actions runs make, make test,
make gtest, bazel build //:osal, bazel test //:test //:gtest, and
bazel build //:freertos on Ubuntu for pushes and pull requests to main.
Run the same checks locally before sending a pull request (see
CONTRIBUTING.md).
With Bazel (Bzlmod), depend on the osal module:
# MODULE.bazel
bazel_dep(name = "osal")
git_override(
module_name = "osal",
remote = "https://github.com/project-chip/poski.git",
commit = "<commit>",
)# BUILD
cc_binary(
name = "app",
srcs = ["app.c"],
deps = ["@osal//:osal_posix"],
)Refer to the libraries by their full names (osal_posix, osal_freertos,
osal_zephyr) from other repositories; the short aliases (//:osal,
//:freertos, //:zephyr) are only visible within this repository.
With other build systems, add include/ and targets/<port>/ to the
include path, compile targets/<port>/*.c (plus *.cc for POSIX), and link
against your RTOS kernel, or against -lpthread -lrt -lstdc++ on Linux.
A minimal producer and consumer, in C:
#include <poski/osal/osal.h>
struct sensor_msg
{
uint16_t id;
int32_t value;
};
static struct pos_queue s_msgq; /* caller-owned: static, on a stack, or embedded */
static struct pos_task s_worker;
static void * worker(void * arg)
{
struct sensor_msg msg;
(void) arg;
while (pos_queue_get(&s_msgq, &msg, POS_TIME_FOREVER) == POS_OK)
{
/* Handle msg.id / msg.value in task context. */
}
return NULL;
}
int main(void)
{
struct sensor_msg msg = { .id = 1, .value = 42 };
pos_queue_init(&s_msgq, sizeof(struct sensor_msg), 8);
pos_task_init(&s_worker, "worker", worker, NULL, POS_PRIORITY_APP, 2048);
pos_queue_put(&s_msgq, &msg); /* copied into the queue */
pos_sched_start(); /* does not return */
return 0;
}And with the C++ wrappers:
#include <poski/OsQueue.h>
#include <poski/OsTask.h>
struct SensorMsg {
uint16_t id;
int32_t value;
};
static poski::OsQueue<SensorMsg, 8> sMsgQueue; // RAII: init in ctor, deinit in dtor
static poski::OsTask sWorker;
static void * Worker(void *)
{
SensorMsg msg;
while (sMsgQueue.Pop(msg) == POS_OK) {
// Handle msg in task context.
}
return nullptr;
}
int main()
{
sWorker.Start("worker", Worker, nullptr, POS_PRIORITY_APP, 2048);
sMsgQueue.Push({ 1, 42 }); // copied into the queue
poski::OsTask::SchedStart(); // does not return
}Conventions shared by all modules:
- Most functions return a
pos_error_t:POS_OKon success, or an error such asPOS_TIMEOUT,POS_EBUSY, orPOS_EINVAL(seeos_types.h). - Blocking calls take a
pos_time_t timeout, which may also bePOS_TIME_NO_WAITorPOS_TIME_FOREVER. The headers specify milliseconds, but the FreeRTOS and RT-Thread ports currently pass the value through as OS ticks, which is equivalent only at a 1 kHz tick rate. - Calls documented as ISR-safe may be made from interrupt handlers; blocking
calls made from an ISR must use
POS_TIME_NO_WAIT.
<poski/osal/os_task.h> · struct pos_task · poski::OsTask
A task (also known as a thread) is an independent context of code execution that runs without any dependency on other concurrent tasks within the system. Only one task runs on a core at any given time. The scheduler starts and stops tasks as necessary to manage resources according to the priorities and policies of the system. A task has no knowledge of the underlying scheduler activity and can be swapped in and out, but always runs with a consistent execution context and stack.
pos_task_init() creates a task from an entry function, an argument, a
priority (POS_PRIORITY_MIN to POS_PRIORITY_MAX; POS_PRIORITY_APP is a
reasonable default), and a stack size in bytes, and makes it ready to run. The
running task can call pos_task_yield(), pos_task_sleep() (ticks), or
pos_task_sleep_ms(), and pos_get_current_task_id() identifies it.
pos_task_remove() is experimental.
<poski/osal/os_mutex.h> · struct pos_mutex · poski::OsMutex
A mutex provides a locking mechanism for enforcing mutual exclusion and
protection of shared resources between independent tasks. POSKI mutexes are
recursive: the owning task may lock a mutex again and must unlock it as many
times as it locked it (pos_mutex_init(), pos_mutex_lock(),
pos_mutex_unlock()). To signal a task from an interrupt, use a semaphore
instead. OsMutex can lock on construction and releases any locks it holds in
its destructor.
<poski/osal/os_sem.h> · struct pos_sem · poski::OsSemaphore
A counting semaphore is a synchronization primitive which provides a means to
block one task until it is released by a signal from another task or
interrupt. pos_sem_init() sets the initial token count, pos_sem_take()
waits for a token, and pos_sem_give() releases one. Both are ISR-safe.
<poski/osal/os_crit.h> · poski::OsCriticalSection / poski::OsAtomicGuard
A critical section provides nestable, short-duration protection for atomic
code sequences by masking interrupts (pos_crit_enter() / pos_crit_exit(),
with pos_atomic_enter() / pos_atomic_exit() aliases). The native interrupt
state is saved in pos_crit_state_t (uintptr_t) and must be restored in
LIFO order.
pos_crit_is_active() reports whether the calling execution context is
inside a critical section, and pos_crit_in_isr() reports whether execution
is inside an Interrupt Service Routine.
<poski/osal/os_queue.h> · struct pos_queue · poski::OsQueue<T, N>
A message queue is a basic primitive for intertask communication. It carries
fixed-size messages from a task or interrupt producer to a consumer task using
copy semantics: pos_queue_put() copies the message in and pos_queue_get()
copies it out, so producer and consumer never share a buffer. Queues are
created with pos_queue_init() (message size and capacity) and released with
pos_queue_deinit(). pos_queue_is_empty() and pos_queue_inited() query
the queue, and pos_queue_set_signal_cb() registers a callback that runs after
each put (for example, to wake an external event loop). pos_queue_put() and
pos_queue_get() are ISR-safe. OsQueue<T, N> provides type-safe Push()
and Pop().
<poski/osal/os_event.h> · struct pos_event / pos_eventq / pos_event_timer · <poski/OsEvent.h>
Events, event queues, and event timers (modeled on Mynewt os_event /
os_eventq / os_callout) provide allocation-free deferred work. An event
(struct pos_event) is a caller-owned {callback, argument} record that
queues link intrusively, so posting never copies or allocates, and posting an
already-pending event is a no-op. Events can be statically initialized with
POS_EVENT_INITIALIZER(). A consumer task drains the queue
(struct pos_eventq) with pos_eventq_get() / pos_eventq_run(). An event
timer (struct pos_event_timer) posts its event to a queue when it expires, so
the callback runs in the consumer task rather than in an ISR or timer context.
The C++ classes poski::OsEvent, OsEventQueue, and OsEventTimer
(<poski/OsEvent.h>, <poski/OsEventQueue.h>, <poski/OsEventTimer.h>) are
pure wrappers of the C API that hold the C structs by value with no extra
storage, so a port implements only the C API. OsEventIn / OsEventTimerIn
dispatch directly to an owner's member function.
<poski/osal/os_timer.h> · struct pos_timer · poski::OsTimer
A software timer triggers a callback function after a given amount of time has
passed. Timers are one-shot: pos_timer_init() binds the callback and its
argument, and pos_timer_start() (ticks) or pos_timer_start_ms() arms the
timer. pos_timer_stop() (ISR-safe), pos_timer_is_active(),
pos_timer_get_ticks(), pos_timer_remaining_ticks(), and
pos_timer_arg_set() / pos_timer_arg_get() manage and query it.
The callback runs in a port-specific context, such as the FreeRTOS timer service task, a POSIX timer thread, or interrupt context on Zephyr and RT-Thread, so keep it short and never block in it.
<poski/osal/os_time.h> · poski::OsTime
A collection of utility functions for getting the current system time and
converting between milliseconds and OS ticks: pos_time_get() (ticks),
pos_time_get_ms(), pos_time_ms_to_ticks(), and pos_time_ticks_to_ms().
POS_TICKS_PER_SEC is the port's tick rate and pos_time_t its tick type;
for example, 32-bit 1 kHz ticks on Linux, 64-bit 1 MHz ticks on macOS, and
TickType_t on FreeRTOS.
<poski/osal/os_sched.h> · poski::OsTask::SchedStart() / SchedStarted()
pos_sched_start() starts the underlying scheduler and does not return; on
POSIX it keeps the calling thread alive (on macOS, by running the main dispatch
queue). pos_sched_started() reports whether the scheduler is running.
<poski/osal/os_panic.h>
pos_panic(const char *msg) is a noreturn fatal error handler. It prints the
message with a POSKI PANIC: prefix, then aborts (POSIX) or asserts and halts
(RTOS targets).
<poski/OsRing.h> · poski::OsRing
OsRing is a portable ring buffer of fixed-size items (push_back(),
front(), pop_front(), size(), empty(), full()). The item count must
be a power of two, and the buffer is allocated with new[]. OsRing is not
thread-safe by itself; the POSIX port wraps it in RingPthread to implement
pos_queue.
POSKI separates its public interface headers cleanly from target-specific implementations:
| File / Folder | Contents |
|---|---|
include/poski/osal/osal.h |
Umbrella C header that includes every POSKI module |
include/poski/osal/os_*.h |
Public C API, one header per module, shared by all ports |
include/poski/Os*.h |
Header-only C++ RAII wrappers (namespace poski) |
targets/<port>/poski/osal/os_port.h |
Maps POSKI types and constants to the target's native definitions |
targets/<port>/os_*.c |
Target implementation of the C API |
tests/ |
Portable C, C++, and GoogleTest suites for the POSKI APIs |
.
├── BUILD - Bazel libraries (osal_posix, osal_freertos, osal_zephyr) and tests
├── MODULE.bazel - Bzlmod dependencies (rules_cc, googletest, FreeRTOS kernel)
├── Makefile - Convenience wrapper around tests/Makefile
├── include/poski
│ ├── OsCriticalSection.h - C++ RAII guard for pos_crit / pos_atomic
│ ├── OsEvent.h - C++ wrapper for pos_event and member dispatch
│ ├── OsEventQueue.h - C++ wrapper for pos_eventq
│ ├── OsEventTimer.h - C++ wrapper for pos_event_timer
│ ├── OsMutex.h - C++ wrapper for pos_mutex
│ ├── OsQueue.h - C++ template wrapper for pos_queue
│ ├── OsRing.h - Portable ring buffer class
│ ├── OsSemaphore.h - C++ wrapper for pos_sem
│ ├── OsTask.h - C++ wrapper for pos_task and pos_sched
│ ├── OsTime.h - C++ wrapper for pos_time
│ ├── OsTimer.h - C++ wrapper for pos_timer
│ └── osal
│ ├── os_crit.h - Critical section / interrupt masking C API
│ ├── os_event.h - Event, event queue, and event timer C API
│ ├── os_mutex.h - Mutex C API
│ ├── os_panic.h - Fatal error (panic) C API
│ ├── os_queue.h - Message queue C API
│ ├── os_sched.h - Scheduler control C API
│ ├── os_sem.h - Semaphore C API
│ ├── os_task.h - Task C API
│ ├── os_time.h - System time and tick conversion C API
│ ├── os_timer.h - Software timer C API
│ ├── os_types.h - Common types and error codes (pos_error_t); includes os_port.h
│ └── osal.h - Umbrella C header
├── targets
│ ├── freertos/ - FreeRTOS port (config/posix/ holds the Bazel compile-check config)
│ ├── posix/ - POSIX port (Linux and macOS)
│ ├── rt-thread/ - RT-Thread port
│ └── zephyr/ - Zephyr port
└── tests
├── Makefile - Make build of the library and tests (PLATFORM=posix or nrf52840)
├── Makefile.freertos-nrf52840 - Settings for FreeRTOS on the Nordic nRF52840
├── test_os_*.c - Portable tests of the C APIs
├── test_os_*_cpp.cpp - Tests of the C++ wrappers
├── test_os_*_cpp_gtest.cpp - Native GoogleTest versions of the C++ tests
├── test_os_ring.cpp - Tests of OsRing
├── test_gtest_wrapper.cpp - Runs a C test's main() as a GoogleTest case
└── test_util.h - Common test utilities (SuccessOrQuit, VerifyOrQuit, TEST_LOG)
- Create
targets/<port>/poski/osal/os_port.h, whichos_types.hincludes. Directly or through headers it includes, it must define:- the tick type
pos_time_tand the constantsPOS_TIME_NO_WAIT,POS_TIME_FOREVER, andPOS_TICKS_PER_SEC; - the priorities
POS_PRIORITY_MIN,POS_PRIORITY_MAX, andPOS_PRIORITY_APP; - the object layouts
struct pos_task,struct pos_mutex,struct pos_sem,struct pos_queue, andstruct pos_timer, which typically embed or point to the native kernel object.
- the tick type
- Implement the C API declared in
include/poski/osal/os_*.hintargets/<port>/os_*.c. Trivial functions may instead bestatic inlineinos_port.h. - Build with
include/andtargets/<port>/on the include path (see theosal_*libraries inBUILD), and run the portable tests fromtests/on the target. - Add CI coverage where practical; at minimum a compile check such as
//:osal_freertos.
The POSIX port (targets/posix) includes both Linux and macOS implementations.
Linux uses the standard POSIX APIs for all functionality. macOS uses POSIX
pthreads, Grand Central Dispatch for the semaphore and timer implementations,
and a Mach clock for time.
| OS | Task | Mutex | Semaphore | Timer | Time | Queue |
|---|---|---|---|---|---|---|
| Linux | pthread |
recursive pthread_mutex |
sem_t |
timer_create (SIGEV_THREAD) |
clock_gettime(CLOCK_MONOTONIC), 1 kHz |
RingPthread |
| macOS | pthread |
recursive pthread_mutex |
dispatch_semaphore |
dispatch_source |
Mach clock_get_time, 1 MHz |
RingPthread |
targets/posix
├── poski/osal
│ ├── os_port.h - Port header included by <poski/osal/os_types.h>
│ ├── os_time.h - Time and timer types (pos_time_t, POS_TIME_*, struct pos_timer)
│ └── os_types.h - Task, mutex, semaphore, and queue types; task priorities
├── os_crit.c - Implementation of pos_crit
├── os_event.c - Implementation of pos_eventq and pos_event_timer
├── os_mutex.c - Implementation of pos_mutex
├── os_panic.c - Implementation of pos_panic
├── os_queue.cc - Implementation of pos_queue (C++, using RingPthread)
├── os_sem.c - Implementation of pos_sem
├── os_task.c - Implementation of pos_task and pos_sched
├── os_time.c - Implementation of pos_time
├── os_timer.c - Implementation of pos_timer
├── os_utils.c - Shared code for the POSIX port, most notably error mapping
├── os_utils.h - Shared header for the POSIX port, most notably SuccessOrExit-style macros
└── RingPthread.h - Thread-safe OsRing using a pthread mutex and condition variable
targets/freertos/README.md and
targets/zephyr/README.md describe those ports
and how to set up their toolchains. They were written for the original CHIP
OSAL, so they still use its chip_os_ names and source paths.
POSKI began as the CHIP OSAL inside Project CHIP. When it moved to its own repository, the API was renamed:
| CHIP OSAL | POSKI |
|---|---|
#include <chip/osal.h> |
#include <poski/osal/osal.h> (or <poski/osal/os_*.h>) |
chip_os_*(), struct chip_os_*, chip_os_error_t |
pos_*(), struct pos_*, pos_error_t |
CHIP_OS_* constants |
POS_* constants |
chip_os_mutex_take() / chip_os_mutex_give() |
pos_mutex_lock() / pos_mutex_unlock() |
Ring (Ring.h) |
poski::OsRing (<poski/OsRing.h>) |
Contributions are welcome. See CONTRIBUTING.md for the workflow, CLA, and required checks, and follow the Code of Conduct. Please report bugs and propose features through GitHub Issues.
POSKI is licensed under the Apache License 2.0.