Skip to content

feat: buffer records and drain them on the service task - #7

Merged
DavidCozens merged 1 commit into
mainfrom
stage-07-buffered
Aug 16, 2026
Merged

feat: buffer records and drain them on the service task#7
DavidCozens merged 1 commit into
mainfrom
stage-07-buffered

Conversation

@DavidCozens

Copy link
Copy Markdown
Contributor

A SolidSyslogCircularBuffer between SolidSyslog_Log and the sender, drained by a service task
calling SolidSyslog_Service. SolidSyslog_Log formats, enqueues and returns; the service task
does the I/O.

static uint8_t s_ring[SOLIDSYSLOG_CIRCULAR_BUFFER_RING_BYTES(SYSLOG_BUFFER_RECORDS)];

.Buffer = SolidSyslogCircularBuffer_Create(SolidSyslogFreeRtosMutex_Create(), s_ring, sizeof(s_ring)),

This separates logging an event from sending it. SolidSyslog_Log becomes safe to call from any
number of tasks, and cheap enough to call from the place the event actually happens rather than
from somewhere convenient later. Nothing that logs waits on the network.

A whole record now passes through both seams, and the depth follows it. The log task formats
one; the service task drains one and sends it. Sized at the RTOS floor, the service task did not
merely trip its overflow hook — it locked the CPU up, because a frame that large clears the guard
band entirely rather than growing into it. Both seams now hold a record and their onward call, and
both are tightened against measured high-water marks at the end.

The mutex is what makes the enqueue and drain sides safe on different tasks, and it comes from the
RTOS — which is what brings the FreeRtos platform into the build. A single-task device injects
SolidSyslogNullMutex_Get() instead and pays nothing.

SolidSyslog_Service returns a status a device wanting more sophisticated scheduling can drive
from. A loop with a delay is the simplest model that works.

When you need it. Once logging and sending are decoupled, the buffer has to absorb however many
events can be logged before it is next serviced. It also makes logging from multiple tasks safe.

@DavidCozens

Copy link
Copy Markdown
Contributor Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

@DavidCozens
DavidCozens force-pushed the stage-06-sequence-id branch from 2dbd29b to 87039e5 Compare August 16, 2026 21:47
A circular buffer in front of the sender, and the service seam finally doing
something: Log enqueues and returns, the service task drains and sends. The
logging task stops waiting on the network. A FreeRTOS mutex makes the two sides
safe on different tasks, which is what brings the FreeRtos platform into the
build.

  Flash    +6,804 B    (+752)
  RAM      +7,484 B  (+5,512)
  Log stack   +672 B  (unchanged)
  Service     +952 B    (+952)

Most of the RAM is the ring: eight records at the message cap plus a two-byte
length prefix each.

The rest is a stack that appeared. Sending left the log task and arrived on the
service task, which drains a whole record and sends it, and which was still at
the FreeRTOS floor. It did not trip the overflow hook — it locked the CPU up:

  qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)

A frame that large clears the guard band rather than growing into it, so the
check never sees it. Both seams now hold a record and their onward call. Measured
at 792 and 1,004 bytes against 2,048 allocated; the margin comes off at the end.

Adding the platform is one word: naming FreeRtos compiles its sources, and the
mutex is the real one rather than the Null fallback that would have made the two
sides quietly unsafe.

The harness gains a drain window. Log no longer sends, so the record is in the
ring when Log returns and the collector has nothing until the service task next
runs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@DavidCozens
DavidCozens changed the base branch from stage-06-sequence-id to main August 16, 2026 21:48
@DavidCozens
DavidCozens merged commit c7abcb8 into main Aug 16, 2026
@DavidCozens
DavidCozens deleted the stage-07-buffered branch August 16, 2026 21:54
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.

1 participant