https://gitlab.synchro.net/main/sbbs/-/commit/9e7885d0f08b00641b058beb
Modified Files:
src/sbbs3/ringbuf.c
Log Message:
ringbuf: only signal events on state transitions in mutex-held builds
RingBufWrite called ResetEvent(empty_event) and SetEvent(data_event) unconditionally on every call, regardless of whether the ring's
empty/non-empty state actually changed. In sexyz, send_byte calls
RingBufWrite once per transmitted byte, so a download was paying for
2-3 event-object operations per byte. On Win32 those operations are
real kernel syscalls; on Unix they go through xpevent.c (pthread
mutex+cond) which is much cheaper.
A reporter on Windows saw 447 KB/s downloads on a link that delivered
~43 MB/s for the reverse direction (the upload path takes data through recv()->inbuf[] in 64 KiB chunks with no per-byte event signaling, so
it wasn't affected).
The unconditional signaling exists because RINGBUF_MUTEX is optional:
without the mutex you cannot safely check "is this a transition" and
then signal, since another writer/reader could change state between
the check and the call. But every Synchronet build that defines
RINGBUF_EVENT also defines RINGBUF_MUTEX (sbbs.vcxproj, websrvr.vcxproj, sbbsexec.vcxproj, sexyz.vcxproj, sbbsdefs.mk, CMakeLists.txt, and the
sbbs.h fallback), so the slow path is the only one in practice.
Add a #ifdef RINGBUF_MUTEX fast path inside the #ifdef RINGBUF_EVENT
block in RingBufWrite and RingBufRead that uses the pre-update fill
level (already captured for the truncation check) together with the
post-clamp byte count to signal only on actual empty<->non-empty and below<->at-or-above-highwater transitions. The mutexless #else path
preserves the existing always-signal semantics verbatim.
Co-Authored-By: Claude Opus 4.7 (1M context) <
noreply@anthropic.com>
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)