Skip to content

Feature/ipc messages and sync - #6

Merged
alexdev8930 merged 4 commits into
alexdev8930:mainfrom
komreb32:feature/ipc-messages-and-sync
Oct 3, 2026
Merged

alexdev8930 merged 4 commits into
alexdev8930:mainfrom
komreb32:feature/ipc-messages-and-sync

Conversation

@komreb32

@komreb32 komreb32 commented Oct 1, 2026

Copy link
Copy Markdown

No description provided.

Fills in ipc/ so kernel tasks can pass messages and synchronise.

IpcPort is a FIFO of fixed size messages. IpcSend waits while the port
is full and IpcReceive waits while it is empty, with Try forms that
never wait. A message is copied by value, so neither side holds a
pointer into the other's memory.

IpcSemaphore counts permits up to a ceiling, and IpcMutex passes
ownership straight to the first waiter on unlock so a ready task cannot
take the lock ahead of the one that was woken for it. A mutex is not
recursive: locking one the caller already holds reports IpcErrOwner
instead of parking on a lock nobody else can open.

Every entry point returns IpcStatus, so a refused call says why rather
than failing silently, and every call checks its arguments before
touching memory.

IpcPark registers the calling task and sleeps as one step under the
interrupt lock. Splitting those two apart would let a waker take the
entry, find the task still runnable, and drop the wakeup, leaving the
task parked with nobody to wake it. Wait queues are keyed by task id,
and a wakeup skips entries whose task was killed, since a dead task
can never run again.

The idle task cannot sleep, so a call that would have to wait reports
IpcErrNoTask rather than parking, matching what timer_sleep_ms does.

Adds ipc/ to the VPATH and its objects to KERNEL_OBJS.
Verifies the ipc at boot rather than assuming it works.

A producer and a consumer pass 40 messages, which is more than a port
holds, so the sender has to park on a full port and the receiver on an
empty one, and both have to be woken the right number of times for the
counts to line up. The consumer checks each message came back in order
and stamped with the sender's id.

The mutex test runs two tasks against one lock for as many rounds as
they finish before the stop flag, each one checking that the shared
counter only ever advanced by one, so the unlock handoff cannot let two
tasks into the critical section at once.

The semaphore and mutex checks that run in this task also cover the
paths that must refuse rather than wait: a re-lock, an unlock from a
task that does not hold the lock, a second create on a live port, and a
second destroy. The last wait reports IpcErrNoTask, since the idle task
has nowhere to park.

These run before the shell and worker start, so their output stays on
one run of lines instead of landing in the middle of the shell prompt.
Documents the ipc contracts in kernel_api.md now that the headers are
implemented, and drops ipc/message.h and ipc/sync.h from the planned
interfaces list. The README and the roadmap no longer describe ipc/ as
a stub.

The version moves to 0.9-dev for the new subsystem.

Known issues are listed rather than left for someone to find: none of
it is reentrant, a wait queue holds 16 entries and reports IpcErrFull
past that, and the objects are static kernel values rather than
something a task can allocate.
@alexdev8930

alexdev8930 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Thanks, this is great!

I especially like how IpcPark() handles blocking and wakeups, and how MutexUnlock() hands ownership to the next waiter. The dead-task handling is also a nice touch.

@alexdev8930
alexdev8930 merged commit 8ff5cf6 into alexdev8930:main Oct 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants