Kernel-v4 Semaphores
Synchronised access to shared resource using semaphores
Description
This example program demonstrates the use of kernel-v4 using two simple actors that synchronise their access to a shared serial terminals using a semaphore.
Other than kernel-v1 threads, which are implemented based on coroutines, and coded as loops, kernel-v4 actors use a set of run-to-the-end procedures, which can be implemented as states of a finite state machine (ie. the procedures themselves reflect the state of the actor).
Both actors use the same state procedures. Since the procedures always run to their end, any actor state must be held in the actor's data structure, not on the stack. All actors use the same address space on the main stack (MSP).
Actors
The program uses two periodically timed actors writing go the same serial terminal, which stands for any resource that must be held reserved and in control of one actor across a kernel rescheduling run.
The actors' state procedures are:
-
aiInit: set up the state array, set first state =aiClaim, await kernel tick -
aiClaim: set state =aiPrint0, claim the semaphore -
aiPrint0: print first message part, set state =aiPrint1, await kernel tick -
aiPrint1: print second message part, set state =aiClaim, release semaphore, await kernel tick
The actors get triggered periodically by the kernel (Kernel.GetTick). As with SemaphoreSync, one actor holds the semaphore across a kernel rescheduling via the tick, so that the other actor has to wait until the first actor releases the semaphore.
The semaphore is implemented based on the kernel's basic actor activation scheme of subscribing and receiving a message: the semaphore is an event queue with one single token message.
Start-up and Run-time
After the program gets control, run installs the kernel using Kernel.Install, which installs the timing loop as actor queue (for actors requesting a tick) and its ready queue to run the actors receiving the tick.
Then the actors and the semaphore guarding the output terminal are instantiated, initialised, and started.
To get the program off the ground, the kernel is started with Kernel.Run, which starts the tick scheduler.
Further Reading
Repository
<repo>/examples/v3.1/rpi/pico2/K4sema<repo>/examples/v3.1/stm/h573i-dk/K4sema<repo>/examples/v3.1/stm/u585i-iot/K4sema
Last updated: 19 May 2026