From 1fc159b575f082ef623c31169ddf84f5cd93d98c Mon Sep 17 00:00:00 2001 From: David Cozens Date: Fri, 22 May 2026 15:05:33 +0100 Subject: [PATCH] refactor: S24.08 enforce top-down function ordering across all .c files Pure move-only refactor. Re-applies the documented function-ordering convention (`_Create`/`_Destroy` first, public funcs next, static helpers defined immediately beneath their first caller) across every `.c` file under Core/Source, Platform/, and Bdd/Targets/. Tests/fakes audited clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- Bdd/Targets/FreeRtos/diskio.c | 166 ++++---- Bdd/Targets/FreeRtos/main.c | 400 +++++++++--------- Core/Source/BlockSequence.c | 70 +-- Core/Source/SolidSyslogBlockStoreStatic.c | 68 +-- Core/Source/SolidSyslogMetaSdStatic.c | 22 +- Core/Source/SolidSyslogStatic.c | 34 +- Core/Source/SolidSyslogUdpSenderStatic.c | 22 +- DEVLOG.md | 52 +++ .../Source/SolidSyslogStdAtomicCounter.c | 12 +- Platform/FatFs/Source/SolidSyslogFatFsFile.c | 24 +- .../Source/SolidSyslogFreeRtosAddressStatic.c | 10 +- .../Source/SolidSyslogFreeRtosDatagram.c | 34 +- .../Source/SolidSyslogFreeRtosMutex.c | 10 +- .../SolidSyslogFreeRtosStaticResolver.c | 14 +- .../Source/SolidSyslogFreeRtosTcpStream.c | 22 +- .../MbedTls/Source/SolidSyslogMbedTlsStream.c | 30 +- .../OpenSsl/Source/SolidSyslogTlsStream.c | 32 +- .../Source/SolidSyslogPosixAddressStatic.c | 10 +- .../Posix/Source/SolidSyslogPosixDatagram.c | 20 +- .../Posix/Source/SolidSyslogPosixTcpStream.c | 14 +- .../Source/SolidSyslogWindowsAtomicCounter.c | 16 +- .../Source/SolidSyslogWinsockAddressStatic.c | 10 +- .../Source/SolidSyslogWinsockDatagram.c | 20 +- .../Source/SolidSyslogWinsockTcpStream.c | 24 +- 24 files changed, 596 insertions(+), 540 deletions(-) diff --git a/Bdd/Targets/FreeRtos/diskio.c b/Bdd/Targets/FreeRtos/diskio.c index 341cf340..25057376 100644 --- a/Bdd/Targets/FreeRtos/diskio.c +++ b/Bdd/Targets/FreeRtos/diskio.c @@ -114,6 +114,76 @@ static bool DiskImageIsReady(void) return true; } +static int SemihostingOpen(const char* path, int mode) +{ + const struct + { + const char* name; + int mode; + int length; + } args = {path, mode, (int) strlen(path)}; + + return Semihosting(SEMIHOSTING_SYS_OPEN, &args); +} + +static int Semihosting(int op, const void* args) +{ + /* BKPT 0xAB is the Cortex-M Thumb semihosting trap. r0 is the + * operation number on entry and the return value on exit; r1 + * is a pointer to a per-op parameter block. memory clobber so + * the compiler doesn't reorder around buffers passed by pointer. */ + register int result __asm("r0") = op; + register const void* request __asm("r1") = args; + __asm volatile("bkpt 0xAB" : "+r"(result) : "r"(request) : "memory"); + return result; +} + +static int SemihostingFlen(int handle) +{ + /* SYS_FLEN returns the file length in bytes, -1 on error. */ + const struct + { + int handle; + } args = {handle}; + + return Semihosting(SEMIHOSTING_SYS_FLEN, &args); +} + +static int SemihostingClose(int handle) +{ + const struct + { + int handle; + } args = {handle}; + + return Semihosting(SEMIHOSTING_SYS_CLOSE, &args); +} + +static int SemihostingSeek(int handle, int position) +{ + /* SYS_SEEK returns 0 on success, a negative value on error. */ + const struct + { + int handle; + int position; + } args = {handle, position}; + + return Semihosting(SEMIHOSTING_SYS_SEEK, &args); +} + +static int SemihostingWrite(int handle, const void* buffer, int count) +{ + /* SYS_WRITE returns the number of bytes NOT written (0 == full write). */ + const struct + { + int handle; + const void* buffer; + int count; + } args = {handle, buffer, count}; + + return Semihosting(SEMIHOSTING_SYS_WRITE, &args); +} + DSTATUS disk_status(BYTE pdrv) { if (pdrv != 0) @@ -146,6 +216,19 @@ DRESULT disk_read(BYTE pdrv, BYTE* buff, LBA_t sector, UINT count) return RES_OK; } +static int SemihostingRead(int handle, void* buffer, int count) +{ + /* SYS_READ returns the number of bytes NOT read (0 == full read). */ + const struct + { + int handle; + void* buffer; + int count; + } args = {handle, buffer, count}; + + return Semihosting(SEMIHOSTING_SYS_READ, &args); +} + DRESULT disk_write(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) { if ((pdrv != 0) || (g_diskHandle < 0)) @@ -196,86 +279,3 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff) return RES_PARERR; } } - -static int Semihosting(int op, const void* args) -{ - /* BKPT 0xAB is the Cortex-M Thumb semihosting trap. r0 is the - * operation number on entry and the return value on exit; r1 - * is a pointer to a per-op parameter block. memory clobber so - * the compiler doesn't reorder around buffers passed by pointer. */ - register int result __asm("r0") = op; - register const void* request __asm("r1") = args; - __asm volatile("bkpt 0xAB" : "+r"(result) : "r"(request) : "memory"); - return result; -} - -static int SemihostingOpen(const char* path, int mode) -{ - const struct - { - const char* name; - int mode; - int length; - } args = {path, mode, (int) strlen(path)}; - - return Semihosting(SEMIHOSTING_SYS_OPEN, &args); -} - -static int SemihostingRead(int handle, void* buffer, int count) -{ - /* SYS_READ returns the number of bytes NOT read (0 == full read). */ - const struct - { - int handle; - void* buffer; - int count; - } args = {handle, buffer, count}; - - return Semihosting(SEMIHOSTING_SYS_READ, &args); -} - -static int SemihostingWrite(int handle, const void* buffer, int count) -{ - /* SYS_WRITE returns the number of bytes NOT written (0 == full write). */ - const struct - { - int handle; - const void* buffer; - int count; - } args = {handle, buffer, count}; - - return Semihosting(SEMIHOSTING_SYS_WRITE, &args); -} - -static int SemihostingSeek(int handle, int position) -{ - /* SYS_SEEK returns 0 on success, a negative value on error. */ - const struct - { - int handle; - int position; - } args = {handle, position}; - - return Semihosting(SEMIHOSTING_SYS_SEEK, &args); -} - -static int SemihostingFlen(int handle) -{ - /* SYS_FLEN returns the file length in bytes, -1 on error. */ - const struct - { - int handle; - } args = {handle}; - - return Semihosting(SEMIHOSTING_SYS_FLEN, &args); -} - -static int SemihostingClose(int handle) -{ - const struct - { - int handle; - } args = {handle}; - - return Semihosting(SEMIHOSTING_SYS_CLOSE, &args); -} diff --git a/Bdd/Targets/FreeRtos/main.c b/Bdd/Targets/FreeRtos/main.c index df6e4477..95dd092c 100644 --- a/Bdd/Targets/FreeRtos/main.c +++ b/Bdd/Targets/FreeRtos/main.c @@ -117,6 +117,13 @@ * absorbs it. */ #define INTERACTIVE_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 48U) +/* Drains the CircularBuffer in the background while the interactive task + * (and, in S08.04 slice 3, additional worker tasks) call SolidSyslog_Log. + * Equal priority to the producers — FreeRTOS round-robins time slices + * between same-priority ready tasks so the buffer is drained without the + * Service task starving slower producers. */ +#define SERVICE_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 16U) + /* Static IPv4 wiring matching the QEMU slirp default. 10.0.2.15 is the * standard slirp DHCP-allocated guest address; we hardcode it here so no * DHCP server is required. The destination address — 10.0.2.2, the slirp @@ -259,6 +266,10 @@ static TaskHandle_t serviceTaskHandle = NULL; extern NetworkInterface_t* pxMPS2_FillInterfaceDescriptor(BaseType_t xEMACIndex, NetworkInterface_t* pxInterface); +static void SetEthernetIrqPriority(void); +static void InteractiveTask(void* argument); +static void ServiceTask(void* argument); + static bool TryUpdateString(char* storage, size_t storageSize, const char* value); static bool TryParseUInt(const char* value, unsigned long* out); static bool RebuildWithFileStore(void); @@ -299,6 +310,105 @@ static void RtosSleep(int milliseconds) static const CmsdkUartMemoryAccess MMIO_ACCESS = {MmioRead32, MmioWrite32, RtosSleep}; +int main(void) +{ + CmsdkUart_Init(&MMIO_ACCESS, CMSDK_UART0_BASE_ADDRESS); + + SetEthernetIrqPriority(); + + (void) pxMPS2_FillInterfaceDescriptor(0, &networkInterface); + FreeRTOS_FillEndPoint( + &networkInterface, + &networkEndPoint, + TEST_IP_ADDRESS, + TEST_NETMASK, + TEST_GATEWAY, + TEST_DNS, + TEST_MAC + ); + + if (FreeRTOS_IPInit_Multi() != pdPASS) + { + for (;;) + { + } + } + + vTaskStartScheduler(); + + for (;;) + { + } + return 0; +} + +void vApplicationIPNetworkEventHook_Multi(eIPCallbackEvent_t eNetworkEvent, struct xNetworkEndPoint* pxEndPoint) +{ + (void) pxEndPoint; + if ((eNetworkEvent == eNetworkUp) && (interactiveTaskCreated == pdFALSE)) + { + if (xTaskCreate( + InteractiveTask, + "interactive", + INTERACTIVE_TASK_STACK_DEPTH, + NULL, + tskIDLE_PRIORITY + 1, + NULL + ) == pdPASS) + { + (void) xTaskCreate( + ServiceTask, + "service", + SERVICE_TASK_STACK_DEPTH, + NULL, + tskIDLE_PRIORITY + 1, + &serviceTaskHandle + ); + interactiveTaskCreated = pdTRUE; + } + } +} + +void vApplicationMallocFailedHook(void) +{ + for (;;) + { + } +} + +void vApplicationStackOverflowHook(TaskHandle_t task, char* taskName) +{ + (void) task; + (void) taskName; + for (;;) + { + } +} + +/* Plus-TCP requires the application to provide a per-endpoint random seed + * source for ARP / IP-ID generation. The QEMU mps2-an385 has no RNG; for a + * deterministic smoke test we return the run-time tick mixed with a fixed + * constant. */ +BaseType_t xApplicationGetRandomNumber(uint32_t* pulValue) +{ + *pulValue = (uint32_t) xTaskGetTickCount() ^ 0xA5A5A5A5U; + return pdPASS; +} + +uint32_t ulApplicationGetNextSequenceNumber( + uint32_t ulSourceAddress, + uint16_t usSourcePort, + uint32_t ulDestinationAddress, + uint16_t usDestinationPort +) +{ + (void) ulSourceAddress; + (void) usSourcePort; + (void) ulDestinationAddress; + (void) usDestinationPort; + return (uint32_t) xTaskGetTickCount(); +} + static void SetEthernetIrqPriority(void) { // NOLINTNEXTLINE(performance-no-int-to-ptr) -- writing the NVIC IPR byte for IRQ 13. @@ -539,17 +649,37 @@ static bool OnSet(const char* name, const char* value) return false; } -static enum SolidSyslogDiscardPolicy MapDiscardPolicy(const char* policy) +static bool TryUpdateString(char* storage, size_t storageSize, const char* value) { - if (strcmp(policy, "newest") == 0) + size_t length = strlen(value); + if ((length == 0U) || (length >= storageSize)) { - return SOLIDSYSLOG_DISCARD_POLICY_NEWEST; + return false; } - if (strcmp(policy, "halt") == 0) + memcpy(storage, value, length); + storage[length] = '\0'; + return true; +} + +static bool TryParseUInt(const char* value, unsigned long* out) +{ + if (*value == '\0') { - return SOLIDSYSLOG_DISCARD_POLICY_HALT; + return false; } - return SOLIDSYSLOG_DISCARD_POLICY_OLDEST; + char* end = NULL; + unsigned long parsed = strtoul(value, &end, 10); + /* strtoul accepts a leading '-' and wraps to a huge unsigned. The port + * call site bounds-checks against UINT16_MAX upstream; facility and + * severity intentionally don't, mirroring the Linux example's + * atoi-and-cast so wrapped values reach the library and encode as + * the internal-error PRIVAL. */ + if (*end != '\0') + { + return false; + } + *out = parsed; + return true; } static bool RebuildWithFileStore(void) @@ -609,6 +739,72 @@ static bool RebuildWithFileStore(void) return true; } +/* Mount volume 0; format-on-first-use if the disk image has no FAT yet. + * Idempotent — subsequent calls short-circuit on fatfsMounted. The work + * buffer for f_mkfs is sized to FF_MAX_SS (512 B) which is the minimum + * f_mkfs accepts on a FAT12/16 volume. */ +static bool EnsureFatFsMounted(void) +{ + if (fatfsMounted) + { + return true; + } + FRESULT res = f_mount( + &fatfs, + "", + 1 + ); /* opt=1 → mount immediately, surface FR_NO_FILESYSTEM here rather than at first f_open */ + if (res == FR_NO_FILESYSTEM) + { + /* Fresh disk image — lay down a FAT and re-mount. FAT12 is the + * natural choice for a 1 MiB volume (small enough that FAT32's + * cluster overhead would dominate). */ + static BYTE workBuffer[FF_MAX_SS]; + const MKFS_PARM opts = {.fmt = FM_FAT | FM_SFD, .n_fat = 1, .align = 1, .n_root = 0, .au_size = 0}; + res = f_mkfs("", &opts, workBuffer, sizeof(workBuffer)); + if (res == FR_OK) + { + res = f_mount(&fatfs, "", 1); + } + } + if (res != FR_OK) + { + (void) printf("[solidsyslog] fatfs mount failed: FRESULT=%d\n", (int) res); + return false; + } + fatfsMounted = true; + return true; +} + +/* Tears down whichever store is currently installed (file-backed or null). + * Shared by RebuildWithFileStore (which then re-creates) and + * ShutdownGracefully (which then exits). FatFsFile_Destroy → Close → + * f_close flushes the underlying FIL's dir entry. */ +static void DestroyCurrentStore(void) +{ + if (currentStoreIsFile) + { + SolidSyslogBlockStore_Destroy(currentStore); + SolidSyslogFileBlockDevice_Destroy(storeBlockDevice); + SolidSyslogCrc16Policy_Destroy(); + SolidSyslogFatFsFile_Destroy(storeFile); + } + /* else: NullStore is shared and immutable — nothing to destroy. */ +} + +static enum SolidSyslogDiscardPolicy MapDiscardPolicy(const char* policy) +{ + if (strcmp(policy, "newest") == 0) + { + return SOLIDSYSLOG_DISCARD_POLICY_NEWEST; + } + if (strcmp(policy, "halt") == 0) + { + return SOLIDSYSLOG_DISCARD_POLICY_HALT; + } + return SOLIDSYSLOG_DISCARD_POLICY_OLDEST; +} + static void OnStoreFull(void* context) { (void) context; @@ -640,22 +836,6 @@ static void OnThresholdCrossed(void* context) (void) printf("[THRESHOLD-CROSSED]\r\n"); } -/* Tears down whichever store is currently installed (file-backed or null). - * Shared by RebuildWithFileStore (which then re-creates) and - * ShutdownGracefully (which then exits). FatFsFile_Destroy → Close → - * f_close flushes the underlying FIL's dir entry. */ -static void DestroyCurrentStore(void) -{ - if (currentStoreIsFile) - { - SolidSyslogBlockStore_Destroy(currentStore); - SolidSyslogFileBlockDevice_Destroy(storeBlockDevice); - SolidSyslogCrc16Policy_Destroy(); - SolidSyslogFatFsFile_Destroy(storeFile); - } - /* else: NullStore is shared and immutable — nothing to destroy. */ -} - /* Full teardown of every resource InteractiveTask allocated during Setup. * Two entry points — `quit` (falls through after BddTargetInteractive_Run * returns) and `set shutdown 1` (OnSet handler) — both route through here @@ -711,43 +891,6 @@ static void TeardownAll(void) SolidSyslogFreeRtosStaticResolver_Destroy(resolver); } -/* Mount volume 0; format-on-first-use if the disk image has no FAT yet. - * Idempotent — subsequent calls short-circuit on fatfsMounted. The work - * buffer for f_mkfs is sized to FF_MAX_SS (512 B) which is the minimum - * f_mkfs accepts on a FAT12/16 volume. */ -static bool EnsureFatFsMounted(void) -{ - if (fatfsMounted) - { - return true; - } - FRESULT res = f_mount( - &fatfs, - "", - 1 - ); /* opt=1 → mount immediately, surface FR_NO_FILESYSTEM here rather than at first f_open */ - if (res == FR_NO_FILESYSTEM) - { - /* Fresh disk image — lay down a FAT and re-mount. FAT12 is the - * natural choice for a 1 MiB volume (small enough that FAT32's - * cluster overhead would dominate). */ - static BYTE workBuffer[FF_MAX_SS]; - const MKFS_PARM opts = {.fmt = FM_FAT | FM_SFD, .n_fat = 1, .align = 1, .n_root = 0, .au_size = 0}; - res = f_mkfs("", &opts, workBuffer, sizeof(workBuffer)); - if (res == FR_OK) - { - res = f_mount(&fatfs, "", 1); - } - } - if (res != FR_OK) - { - (void) printf("[solidsyslog] fatfs mount failed: FRESULT=%d\n", (int) res); - return false; - } - fatfsMounted = true; - return true; -} - static void SemihostingExit(int status) { /* SYS_EXIT_EXTENDED (0x20) — the only ARM Semihosting exit form on @@ -771,39 +914,6 @@ static void SemihostingExit(int status) } } -static bool TryUpdateString(char* storage, size_t storageSize, const char* value) -{ - size_t length = strlen(value); - if ((length == 0U) || (length >= storageSize)) - { - return false; - } - memcpy(storage, value, length); - storage[length] = '\0'; - return true; -} - -static bool TryParseUInt(const char* value, unsigned long* out) -{ - if (*value == '\0') - { - return false; - } - char* end = NULL; - unsigned long parsed = strtoul(value, &end, 10); - /* strtoul accepts a leading '-' and wraps to a huge unsigned. The port - * call site bounds-checks against UINT16_MAX upstream; facility and - * severity intentionally don't, mirroring the Linux example's - * atoi-and-cast so wrapped values reach the library and encode as - * the internal-error PRIVAL. */ - if (*end != '\0') - { - return false; - } - *out = parsed; - return true; -} - static void InteractiveTask(void* argument) { (void) argument; @@ -951,13 +1061,6 @@ static void InteractiveTask(void* argument) vTaskDelete(NULL); } -/* Drains the CircularBuffer in the background while the interactive task - * (and, in S08.04 slice 3, additional worker tasks) call SolidSyslog_Log. - * Equal priority to the producers — FreeRTOS round-robins time slices - * between same-priority ready tasks so the buffer is drained without the - * Service task starving slower producers. */ -#define SERVICE_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 16U) - static void ServiceTask(void* argument) { (void) argument; @@ -989,102 +1092,3 @@ static void ServiceTask(void* argument) vTaskDelay(pdMS_TO_TICKS(1)); } } - -void vApplicationIPNetworkEventHook_Multi(eIPCallbackEvent_t eNetworkEvent, struct xNetworkEndPoint* pxEndPoint) -{ - (void) pxEndPoint; - if ((eNetworkEvent == eNetworkUp) && (interactiveTaskCreated == pdFALSE)) - { - if (xTaskCreate( - InteractiveTask, - "interactive", - INTERACTIVE_TASK_STACK_DEPTH, - NULL, - tskIDLE_PRIORITY + 1, - NULL - ) == pdPASS) - { - (void) xTaskCreate( - ServiceTask, - "service", - SERVICE_TASK_STACK_DEPTH, - NULL, - tskIDLE_PRIORITY + 1, - &serviceTaskHandle - ); - interactiveTaskCreated = pdTRUE; - } - } -} - -int main(void) -{ - CmsdkUart_Init(&MMIO_ACCESS, CMSDK_UART0_BASE_ADDRESS); - - SetEthernetIrqPriority(); - - (void) pxMPS2_FillInterfaceDescriptor(0, &networkInterface); - FreeRTOS_FillEndPoint( - &networkInterface, - &networkEndPoint, - TEST_IP_ADDRESS, - TEST_NETMASK, - TEST_GATEWAY, - TEST_DNS, - TEST_MAC - ); - - if (FreeRTOS_IPInit_Multi() != pdPASS) - { - for (;;) - { - } - } - - vTaskStartScheduler(); - - for (;;) - { - } - return 0; -} - -void vApplicationMallocFailedHook(void) -{ - for (;;) - { - } -} - -void vApplicationStackOverflowHook(TaskHandle_t task, char* taskName) -{ - (void) task; - (void) taskName; - for (;;) - { - } -} - -/* Plus-TCP requires the application to provide a per-endpoint random seed - * source for ARP / IP-ID generation. The QEMU mps2-an385 has no RNG; for a - * deterministic smoke test we return the run-time tick mixed with a fixed - * constant. */ -BaseType_t xApplicationGetRandomNumber(uint32_t* pulValue) -{ - *pulValue = (uint32_t) xTaskGetTickCount() ^ 0xA5A5A5A5U; - return pdPASS; -} - -uint32_t ulApplicationGetNextSequenceNumber( - uint32_t ulSourceAddress, - uint16_t usSourcePort, - uint32_t ulDestinationAddress, - uint16_t usDestinationPort -) -{ - (void) ulSourceAddress; - (void) usSourcePort; - (void) ulDestinationAddress; - (void) usDestinationPort; - return (uint32_t) xTaskGetTickCount(); -} diff --git a/Core/Source/BlockSequence.c b/Core/Source/BlockSequence.c index 0f280b00..ede3cc11 100644 --- a/Core/Source/BlockSequence.c +++ b/Core/Source/BlockSequence.c @@ -205,6 +205,41 @@ static inline int BlockSequence_CircularPrev(int index) return (index + MAX_SEQUENCE - 1) % MAX_SEQUENCE; } +static inline bool BlockSequence_ThresholdEnabled(const struct BlockSequence* blockSequence); +static inline bool BlockSequence_IsAboveThreshold(const struct BlockSequence* blockSequence, size_t threshold); + +static inline void BlockSequence_NotifyThresholdCrossed(struct BlockSequence* blockSequence) +{ + if (BlockSequence_ThresholdEnabled(blockSequence)) + { + size_t threshold = blockSequence->GetCapacityThreshold(blockSequence->ThresholdContext); + + if (!BlockSequence_IsAboveThreshold(blockSequence, threshold)) + { + blockSequence->ThresholdCrossed = false; + } + else if (!blockSequence->ThresholdCrossed) + { + blockSequence->ThresholdCrossed = true; + blockSequence->OnThresholdCrossed(blockSequence->ThresholdContext); + } + else + { + /* still above threshold and already notified — no edge to report */ + } + } +} + +static inline bool BlockSequence_ThresholdEnabled(const struct BlockSequence* blockSequence) +{ + return (blockSequence->OnThresholdCrossed != NULL) && (blockSequence->GetCapacityThreshold != NULL); +} + +static inline bool BlockSequence_IsAboveThreshold(const struct BlockSequence* blockSequence, size_t threshold) +{ + return (threshold != 0U) && (BlockSequence_UsedBytes(blockSequence) >= threshold); +} + static inline bool BlockSequence_BlockIsFull(const struct BlockSequence* blockSequence, size_t recordSize); static inline bool BlockSequence_StoreIsFull(const struct BlockSequence* blockSequence); static inline void BlockSequence_NotifyStoreFull(struct BlockSequence* blockSequence); @@ -374,41 +409,6 @@ void BlockSequence_NoteRecordWritten(struct BlockSequence* blockSequence, size_t BlockSequence_NotifyThresholdCrossed(blockSequence); } -static inline bool BlockSequence_ThresholdEnabled(const struct BlockSequence* blockSequence); -static inline bool BlockSequence_IsAboveThreshold(const struct BlockSequence* blockSequence, size_t threshold); - -static inline void BlockSequence_NotifyThresholdCrossed(struct BlockSequence* blockSequence) -{ - if (BlockSequence_ThresholdEnabled(blockSequence)) - { - size_t threshold = blockSequence->GetCapacityThreshold(blockSequence->ThresholdContext); - - if (!BlockSequence_IsAboveThreshold(blockSequence, threshold)) - { - blockSequence->ThresholdCrossed = false; - } - else if (!blockSequence->ThresholdCrossed) - { - blockSequence->ThresholdCrossed = true; - blockSequence->OnThresholdCrossed(blockSequence->ThresholdContext); - } - else - { - /* still above threshold and already notified — no edge to report */ - } - } -} - -static inline bool BlockSequence_ThresholdEnabled(const struct BlockSequence* blockSequence) -{ - return (blockSequence->OnThresholdCrossed != NULL) && (blockSequence->GetCapacityThreshold != NULL); -} - -static inline bool BlockSequence_IsAboveThreshold(const struct BlockSequence* blockSequence, size_t threshold) -{ - return (threshold != 0U) && (BlockSequence_UsedBytes(blockSequence) >= threshold); -} - void BlockSequence_MarkWriteBlockCorrupt(struct BlockSequence* blockSequence) { blockSequence->WriteBlockCorrupt = true; diff --git a/Core/Source/SolidSyslogBlockStoreStatic.c b/Core/Source/SolidSyslogBlockStoreStatic.c index 20076ff8..62244abd 100644 --- a/Core/Source/SolidSyslogBlockStoreStatic.c +++ b/Core/Source/SolidSyslogBlockStoreStatic.c @@ -69,6 +69,40 @@ struct SolidSyslogStore* SolidSyslogBlockStore_Create(const struct SolidSyslogBl return result; } +static struct SolidSyslogSecurityPolicy* BlockStore_ResolveSecurityPolicy(struct SolidSyslogSecurityPolicy* configured) +{ + struct SolidSyslogSecurityPolicy* resolved = configured; + + if ((resolved == NULL) || (resolved->IntegritySize > SOLIDSYSLOG_MAX_INTEGRITY_SIZE)) + { + resolved = SolidSyslogNullSecurityPolicy_Get(); + } + + return resolved; +} + +static struct BlockSequenceConfig BlockStore_BuildBlockSequenceConfig( + const struct SolidSyslogBlockStoreConfig* config, + const struct RecordStore* recordStore +) +{ + size_t minBlockSize = RecordStore_RecordSize(recordStore, SOLIDSYSLOG_MAX_MESSAGE_SIZE); + size_t maxBlockSize = (config->MaxBlockSize < minBlockSize) ? minBlockSize : config->MaxBlockSize; + + struct BlockSequenceConfig blockConfig = { + .BlockDevice = config->BlockDevice, + .MaxBlockSize = maxBlockSize, + .MaxBlocks = config->MaxBlocks, + .DiscardPolicy = config->DiscardPolicy, + .OnStoreFull = config->OnStoreFull, + .StoreFullContext = config->StoreFullContext, + .GetCapacityThreshold = config->GetCapacityThreshold, + .OnThresholdCrossed = config->OnThresholdCrossed, + .ThresholdContext = config->ThresholdContext, + }; + return blockConfig; +} + void SolidSyslogBlockStore_Destroy(struct SolidSyslogStore* base) { size_t index = BlockStore_IndexFromHandle(base); @@ -119,37 +153,3 @@ static inline void BlockStore_CleanupAtIndex(size_t index, void* context) (void) context; BlockStore_Cleanup(&BlockStore_Pool[index].Base); } - -static struct SolidSyslogSecurityPolicy* BlockStore_ResolveSecurityPolicy(struct SolidSyslogSecurityPolicy* configured) -{ - struct SolidSyslogSecurityPolicy* resolved = configured; - - if ((resolved == NULL) || (resolved->IntegritySize > SOLIDSYSLOG_MAX_INTEGRITY_SIZE)) - { - resolved = SolidSyslogNullSecurityPolicy_Get(); - } - - return resolved; -} - -static struct BlockSequenceConfig BlockStore_BuildBlockSequenceConfig( - const struct SolidSyslogBlockStoreConfig* config, - const struct RecordStore* recordStore -) -{ - size_t minBlockSize = RecordStore_RecordSize(recordStore, SOLIDSYSLOG_MAX_MESSAGE_SIZE); - size_t maxBlockSize = (config->MaxBlockSize < minBlockSize) ? minBlockSize : config->MaxBlockSize; - - struct BlockSequenceConfig blockConfig = { - .BlockDevice = config->BlockDevice, - .MaxBlockSize = maxBlockSize, - .MaxBlocks = config->MaxBlocks, - .DiscardPolicy = config->DiscardPolicy, - .OnStoreFull = config->OnStoreFull, - .StoreFullContext = config->StoreFullContext, - .GetCapacityThreshold = config->GetCapacityThreshold, - .OnThresholdCrossed = config->OnThresholdCrossed, - .ThresholdContext = config->ThresholdContext, - }; - return blockConfig; -} diff --git a/Core/Source/SolidSyslogMetaSdStatic.c b/Core/Source/SolidSyslogMetaSdStatic.c index 1c3f1fed..07e3b4e9 100644 --- a/Core/Source/SolidSyslogMetaSdStatic.c +++ b/Core/Source/SolidSyslogMetaSdStatic.c @@ -40,17 +40,6 @@ struct SolidSyslogStructuredData* SolidSyslogMetaSd_Create(const struct SolidSys return result; } -void SolidSyslogMetaSd_Destroy(struct SolidSyslogStructuredData* base) -{ - size_t index = MetaSd_IndexFromHandle(base); - bool released = SolidSyslogPoolAllocator_IndexIsValid(&MetaSd_Allocator, index) && - SolidSyslogPoolAllocator_FreeIfInUse(&MetaSd_Allocator, index, MetaSd_CleanupAtIndex, NULL); - if (!released) - { - SolidSyslog_Error(SOLIDSYSLOG_SEVERITY_WARNING, SOLIDSYSLOG_ERROR_MSG_METASD_UNKNOWN_DESTROY); - } -} - static bool MetaSd_IsValidConfig(const struct SolidSyslogMetaSdConfig* config) { bool valid = false; @@ -69,6 +58,17 @@ static bool MetaSd_IsValidConfig(const struct SolidSyslogMetaSdConfig* config) return valid; } +void SolidSyslogMetaSd_Destroy(struct SolidSyslogStructuredData* base) +{ + size_t index = MetaSd_IndexFromHandle(base); + bool released = SolidSyslogPoolAllocator_IndexIsValid(&MetaSd_Allocator, index) && + SolidSyslogPoolAllocator_FreeIfInUse(&MetaSd_Allocator, index, MetaSd_CleanupAtIndex, NULL); + if (!released) + { + SolidSyslog_Error(SOLIDSYSLOG_SEVERITY_WARNING, SOLIDSYSLOG_ERROR_MSG_METASD_UNKNOWN_DESTROY); + } +} + static inline size_t MetaSd_IndexFromHandle(const struct SolidSyslogStructuredData* base) { size_t result = SOLIDSYSLOG_META_SD_POOL_SIZE; diff --git a/Core/Source/SolidSyslogStatic.c b/Core/Source/SolidSyslogStatic.c index c3a86abd..59564c66 100644 --- a/Core/Source/SolidSyslogStatic.c +++ b/Core/Source/SolidSyslogStatic.c @@ -54,6 +54,23 @@ struct SolidSyslog* SolidSyslog_Create(const struct SolidSyslogConfig* config) return result; } +static void SolidSyslog_EnsureNullInstancePopulated(void) +{ + if (!SolidSyslog_NullInstancePopulated) + { + SolidSyslog_NullInstance.Buffer = SolidSyslogNullBuffer_Get(); + SolidSyslog_NullInstance.Sender = SolidSyslogNullSender_Get(); + SolidSyslog_NullInstance.Store = SolidSyslogNullStore_Get(); + SolidSyslog_NullInstance.Clock = SolidSyslog_NullClock; + SolidSyslog_NullInstance.GetHostname = SolidSyslog_NullStringFunction; + SolidSyslog_NullInstance.GetAppName = SolidSyslog_NullStringFunction; + SolidSyslog_NullInstance.GetProcessId = SolidSyslog_NullStringFunction; + SolidSyslog_NullInstance.Sd = NULL; + SolidSyslog_NullInstance.SdCount = 0; + SolidSyslog_NullInstancePopulated = true; + } +} + void SolidSyslog_Destroy(struct SolidSyslog* handle) { size_t index = SolidSyslog_IndexFromHandle(handle); @@ -85,20 +102,3 @@ static inline void SolidSyslog_CleanupAtIndex(size_t index, void* context) (void) context; SolidSyslog_Cleanup(&SolidSyslog_Pool[index]); } - -static void SolidSyslog_EnsureNullInstancePopulated(void) -{ - if (!SolidSyslog_NullInstancePopulated) - { - SolidSyslog_NullInstance.Buffer = SolidSyslogNullBuffer_Get(); - SolidSyslog_NullInstance.Sender = SolidSyslogNullSender_Get(); - SolidSyslog_NullInstance.Store = SolidSyslogNullStore_Get(); - SolidSyslog_NullInstance.Clock = SolidSyslog_NullClock; - SolidSyslog_NullInstance.GetHostname = SolidSyslog_NullStringFunction; - SolidSyslog_NullInstance.GetAppName = SolidSyslog_NullStringFunction; - SolidSyslog_NullInstance.GetProcessId = SolidSyslog_NullStringFunction; - SolidSyslog_NullInstance.Sd = NULL; - SolidSyslog_NullInstance.SdCount = 0; - SolidSyslog_NullInstancePopulated = true; - } -} diff --git a/Core/Source/SolidSyslogUdpSenderStatic.c b/Core/Source/SolidSyslogUdpSenderStatic.c index 49220528..0890f9f1 100644 --- a/Core/Source/SolidSyslogUdpSenderStatic.c +++ b/Core/Source/SolidSyslogUdpSenderStatic.c @@ -40,17 +40,6 @@ struct SolidSyslogSender* SolidSyslogUdpSender_Create(const struct SolidSyslogUd return result; } -void SolidSyslogUdpSender_Destroy(struct SolidSyslogSender* base) -{ - size_t index = UdpSender_IndexFromHandle(base); - bool released = SolidSyslogPoolAllocator_IndexIsValid(&UdpSender_Allocator, index) && - SolidSyslogPoolAllocator_FreeIfInUse(&UdpSender_Allocator, index, UdpSender_CleanupAtIndex, NULL); - if (!released) - { - SolidSyslog_Error(SOLIDSYSLOG_SEVERITY_WARNING, SOLIDSYSLOG_ERROR_MSG_UDPSENDER_UNKNOWN_DESTROY); - } -} - static bool UdpSender_IsValidConfig(const struct SolidSyslogUdpSenderConfig* config) { bool valid = false; @@ -81,6 +70,17 @@ static bool UdpSender_IsValidConfig(const struct SolidSyslogUdpSenderConfig* con return valid; } +void SolidSyslogUdpSender_Destroy(struct SolidSyslogSender* base) +{ + size_t index = UdpSender_IndexFromHandle(base); + bool released = SolidSyslogPoolAllocator_IndexIsValid(&UdpSender_Allocator, index) && + SolidSyslogPoolAllocator_FreeIfInUse(&UdpSender_Allocator, index, UdpSender_CleanupAtIndex, NULL); + if (!released) + { + SolidSyslog_Error(SOLIDSYSLOG_SEVERITY_WARNING, SOLIDSYSLOG_ERROR_MSG_UDPSENDER_UNKNOWN_DESTROY); + } +} + static inline size_t UdpSender_IndexFromHandle(const struct SolidSyslogSender* base) { size_t result = SOLIDSYSLOG_UDP_SENDER_POOL_SIZE; diff --git a/DEVLOG.md b/DEVLOG.md index fc1601e4..c0bf6e63 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,5 +1,57 @@ # Dev Log +## 2026-05-22 — S24.08 top-down function ordering sweep + +Closes S24.08 (#423). Pure refactoring pass: re-applied the documented +function-ordering convention (`_Create`/`_Destroy` first, public funcs +next, static helpers defined immediately beneath their first caller) to +every `.c` file under Core/Source, Platform/, and Bdd/Targets/. Move-only +diff; no behaviour change. + +### Audit first, then move + +Three parallel Explore agents audited Core, Platform, and Tests/fakes +against the strict rule. First pass under-flagged Core/Source and +over-flagged a few simple files (PosixClock, WindowsClock, +WinsockResolver, CmsdkUart all turned out to be compliant once +re-examined). Second pass with the precise rule — "a helper is +non-compliant only when a non-calling function intervenes between its +first caller and its definition" — landed the real list: 5 Core files, +13 Platform files, 2 Bdd/Targets files (`diskio.c`, FreeRTOS BDD +`main.c`). Tests/fakes audited clean. + +### Convention clarifications gathered along the way + +- **Vtable methods called by `_Cleanup`.** TLS-style files + (`TlsStream`, `MbedTlsStream`, `WinsockTcpStream`) where `_Cleanup` + delegates the close logic to `_Close`: `_Close` moved up to sit + beneath `_Cleanup`. Files where `_Cleanup` inlines its own close + logic (`PosixTcpStream`) keep `_Close` at the end in API order. +- **Helper-to-helper call order within a cluster.** The strict + "next non-calling function" reading was followed for clear + violations (helper sits after an unrelated public function). + Reordering helpers *within* a single caller's helper cluster purely + for call-order aesthetics was skipped to keep the diff focused. +- **`main` is a special case.** Entry-point function comes first + (David's call); other rules apply normally. The FreeRTOS BDD + `main.c` was restructured so `main` plus the four `vApplication*` + OS-callback hooks sit at the top, with the OnSet helper cluster + reorganised into call-graph order (TryUpdateString, TryParseUInt, + RebuildWithFileStore + its helper cascade, TeardownAll, + SemihostingExit). + +### Pre-existing format-violation noise + +`analyze-format` will continue to flag `TlsStreamStatic.c` and +`FatFsFileStatic.c` for a `bool released = ...` continuation indent — +both untouched by this PR. Pre-existing; out of scope here. + +### Deferred + +- Strict helper-to-helper call ordering within a single caller's + helper cluster — left for a future tightening pass if the + convention is sharpened to require it. + ## 2026-05-21 — S08.07 slice 6 + 7: FreeRTOS TLS via mbedTLS Closes S08.07 (#272). Lights up the TLS slot on the FreeRTOS QEMU BDD diff --git a/Platform/Atomics/Source/SolidSyslogStdAtomicCounter.c b/Platform/Atomics/Source/SolidSyslogStdAtomicCounter.c index 14763cba..ec2b0313 100644 --- a/Platform/Atomics/Source/SolidSyslogStdAtomicCounter.c +++ b/Platform/Atomics/Source/SolidSyslogStdAtomicCounter.c @@ -19,11 +19,9 @@ void StdAtomicCounter_Initialise(struct SolidSyslogAtomicCounter* base) StdAtomicCounter_Init(self, 0U); } -void StdAtomicCounter_Cleanup(struct SolidSyslogAtomicCounter* base) +static inline struct SolidSyslogStdAtomicCounter* StdAtomicCounter_SelfFromBase(struct SolidSyslogAtomicCounter* base) { - /* Overwrite the abstract base with the shared NullAtomicCounter vtable so - * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */ - *base = *SolidSyslogNullAtomicCounter_Get(); + return (struct SolidSyslogStdAtomicCounter*) base; } void StdAtomicCounter_Init(struct SolidSyslogStdAtomicCounter* self, uint32_t value) @@ -31,9 +29,11 @@ void StdAtomicCounter_Init(struct SolidSyslogStdAtomicCounter* self, uint32_t va atomic_init(&self->Value, value); } -static inline struct SolidSyslogStdAtomicCounter* StdAtomicCounter_SelfFromBase(struct SolidSyslogAtomicCounter* base) +void StdAtomicCounter_Cleanup(struct SolidSyslogAtomicCounter* base) { - return (struct SolidSyslogStdAtomicCounter*) base; + /* Overwrite the abstract base with the shared NullAtomicCounter vtable so + * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */ + *base = *SolidSyslogNullAtomicCounter_Get(); } static uint32_t StdAtomicCounter_Increment(struct SolidSyslogAtomicCounter* base) diff --git a/Platform/FatFs/Source/SolidSyslogFatFsFile.c b/Platform/FatFs/Source/SolidSyslogFatFsFile.c index 8865f1c6..e3ee64fa 100644 --- a/Platform/FatFs/Source/SolidSyslogFatFsFile.c +++ b/Platform/FatFs/Source/SolidSyslogFatFsFile.c @@ -40,6 +40,11 @@ void FatFsFile_Initialise(struct SolidSyslogFile* base) self->IsOpen = false; } +static inline struct SolidSyslogFatFsFile* FatFsFile_SelfFromBase(struct SolidSyslogFile* base) +{ + return (struct SolidSyslogFatFsFile*) base; +} + void FatFsFile_Cleanup(struct SolidSyslogFile* base) { FatFsFile_Close(base); @@ -48,9 +53,14 @@ void FatFsFile_Cleanup(struct SolidSyslogFile* base) *base = *SolidSyslogNullFile_Get(); } -static inline struct SolidSyslogFatFsFile* FatFsFile_SelfFromBase(struct SolidSyslogFile* base) +static void FatFsFile_Close(struct SolidSyslogFile* base) { - return (struct SolidSyslogFatFsFile*) base; + struct SolidSyslogFatFsFile* self = FatFsFile_SelfFromBase(base); + if (self->IsOpen) + { + f_close(&self->Fp); + self->IsOpen = false; + } } static bool FatFsFile_Open(struct SolidSyslogFile* base, const char* path) @@ -61,16 +71,6 @@ static bool FatFsFile_Open(struct SolidSyslogFile* base, const char* path) return self->IsOpen; } -static void FatFsFile_Close(struct SolidSyslogFile* base) -{ - struct SolidSyslogFatFsFile* self = FatFsFile_SelfFromBase(base); - if (self->IsOpen) - { - f_close(&self->Fp); - self->IsOpen = false; - } -} - static bool FatFsFile_IsOpen(struct SolidSyslogFile* base) { return FatFsFile_SelfFromBase(base)->IsOpen; diff --git a/Platform/FreeRtos/Source/SolidSyslogFreeRtosAddressStatic.c b/Platform/FreeRtos/Source/SolidSyslogFreeRtosAddressStatic.c index d5b16060..d6e898df 100644 --- a/Platform/FreeRtos/Source/SolidSyslogFreeRtosAddressStatic.c +++ b/Platform/FreeRtos/Source/SolidSyslogFreeRtosAddressStatic.c @@ -46,6 +46,11 @@ struct SolidSyslogAddress* SolidSyslogFreeRtosAddress_Create(void) return handle; } +static inline struct SolidSyslogAddress* FreeRtosAddress_HandleFromIndex(size_t index) +{ + return (struct SolidSyslogAddress*) &FreeRtosAddress_Pool[index]; +} + void SolidSyslogFreeRtosAddress_Destroy(struct SolidSyslogAddress* base) { size_t index = FreeRtosAddress_IndexFromHandle(base); @@ -58,11 +63,6 @@ void SolidSyslogFreeRtosAddress_Destroy(struct SolidSyslogAddress* base) } } -static inline struct SolidSyslogAddress* FreeRtosAddress_HandleFromIndex(size_t index) -{ - return (struct SolidSyslogAddress*) &FreeRtosAddress_Pool[index]; -} - static inline size_t FreeRtosAddress_IndexFromHandle(const struct SolidSyslogAddress* base) { size_t result = SOLIDSYSLOG_ADDRESS_POOL_SIZE; diff --git a/Platform/FreeRtos/Source/SolidSyslogFreeRtosDatagram.c b/Platform/FreeRtos/Source/SolidSyslogFreeRtosDatagram.c index d3796b22..100617cc 100644 --- a/Platform/FreeRtos/Source/SolidSyslogFreeRtosDatagram.c +++ b/Platform/FreeRtos/Source/SolidSyslogFreeRtosDatagram.c @@ -49,6 +49,11 @@ void FreeRtosDatagram_Initialise(struct SolidSyslogDatagram* base) self->Socket = FREERTOS_INVALID_SOCKET; } +static inline struct SolidSyslogFreeRtosDatagram* FreeRtosDatagram_SelfFromBase(struct SolidSyslogDatagram* base) +{ + return (struct SolidSyslogFreeRtosDatagram*) base; +} + void FreeRtosDatagram_Cleanup(struct SolidSyslogDatagram* base) { FreeRtosDatagram_Close(base); @@ -57,9 +62,14 @@ void FreeRtosDatagram_Cleanup(struct SolidSyslogDatagram* base) *base = *SolidSyslogNullDatagram_Get(); } -static inline struct SolidSyslogFreeRtosDatagram* FreeRtosDatagram_SelfFromBase(struct SolidSyslogDatagram* base) +static void FreeRtosDatagram_Close(struct SolidSyslogDatagram* base) { - return (struct SolidSyslogFreeRtosDatagram*) base; + struct SolidSyslogFreeRtosDatagram* self = FreeRtosDatagram_SelfFromBase(base); + if (FreeRtosDatagram_IsOpen(self)) + { + (void) FreeRTOS_closesocket(self->Socket); + self->Socket = FREERTOS_INVALID_SOCKET; + } } static bool FreeRtosDatagram_Open(struct SolidSyslogDatagram* base) @@ -72,6 +82,11 @@ static bool FreeRtosDatagram_Open(struct SolidSyslogDatagram* base) return FreeRtosDatagram_IsOpen(self); } +static inline bool FreeRtosDatagram_IsOpen(const struct SolidSyslogFreeRtosDatagram* self) +{ + return self->Socket != FREERTOS_INVALID_SOCKET; +} + static enum SolidSyslogDatagramSendResult FreeRtosDatagram_SendTo( struct SolidSyslogDatagram* base, const void* buffer, @@ -109,25 +124,10 @@ static inline void FreeRtosDatagram_PrimeArpIfMissing(uint32_t ip) } } -static inline bool FreeRtosDatagram_IsOpen(const struct SolidSyslogFreeRtosDatagram* self) -{ - return self->Socket != FREERTOS_INVALID_SOCKET; -} - static size_t FreeRtosDatagram_MaxPayload(struct SolidSyslogDatagram* base) { (void) base; return SOLIDSYSLOG_UDP_IPV6_SAFE_PAYLOAD; } -static void FreeRtosDatagram_Close(struct SolidSyslogDatagram* base) -{ - struct SolidSyslogFreeRtosDatagram* self = FreeRtosDatagram_SelfFromBase(base); - if (FreeRtosDatagram_IsOpen(self)) - { - (void) FreeRTOS_closesocket(self->Socket); - self->Socket = FREERTOS_INVALID_SOCKET; - } -} - // NOLINTEND(performance-no-int-to-ptr) diff --git a/Platform/FreeRtos/Source/SolidSyslogFreeRtosMutex.c b/Platform/FreeRtos/Source/SolidSyslogFreeRtosMutex.c index 30fef2f9..c95a4df7 100644 --- a/Platform/FreeRtos/Source/SolidSyslogFreeRtosMutex.c +++ b/Platform/FreeRtos/Source/SolidSyslogFreeRtosMutex.c @@ -35,6 +35,11 @@ void FreeRtosMutex_Initialise(struct SolidSyslogMutex* base) } } +static inline struct SolidSyslogFreeRtosMutex* FreeRtosMutex_SelfFromBase(struct SolidSyslogMutex* base) +{ + return (struct SolidSyslogFreeRtosMutex*) base; +} + void FreeRtosMutex_Cleanup(struct SolidSyslogMutex* base) { struct SolidSyslogFreeRtosMutex* self = FreeRtosMutex_SelfFromBase(base); @@ -47,11 +52,6 @@ void FreeRtosMutex_Cleanup(struct SolidSyslogMutex* base) *base = *SolidSyslogNullMutex_Get(); } -static inline struct SolidSyslogFreeRtosMutex* FreeRtosMutex_SelfFromBase(struct SolidSyslogMutex* base) -{ - return (struct SolidSyslogFreeRtosMutex*) base; -} - static inline SemaphoreHandle_t FreeRtosMutex_AsHandle(struct SolidSyslogFreeRtosMutex* self) { return (SemaphoreHandle_t) &self->Buffer; diff --git a/Platform/FreeRtos/Source/SolidSyslogFreeRtosStaticResolver.c b/Platform/FreeRtos/Source/SolidSyslogFreeRtosStaticResolver.c index d041b04b..e3d43944 100644 --- a/Platform/FreeRtos/Source/SolidSyslogFreeRtosStaticResolver.c +++ b/Platform/FreeRtos/Source/SolidSyslogFreeRtosStaticResolver.c @@ -35,6 +35,13 @@ void FreeRtosStaticResolver_Initialise(struct SolidSyslogResolver* base, const u self->Octets[3] = ipv4Octets[3]; } +static inline struct SolidSyslogFreeRtosStaticResolver* FreeRtosStaticResolver_SelfFromBase( + struct SolidSyslogResolver* base +) +{ + return (struct SolidSyslogFreeRtosStaticResolver*) base; +} + void FreeRtosStaticResolver_Cleanup(struct SolidSyslogResolver* base) { /* Overwrite the abstract base with the shared NullResolver vtable so @@ -43,13 +50,6 @@ void FreeRtosStaticResolver_Cleanup(struct SolidSyslogResolver* base) *base = *SolidSyslogNullResolver_Get(); } -static inline struct SolidSyslogFreeRtosStaticResolver* FreeRtosStaticResolver_SelfFromBase( - struct SolidSyslogResolver* base -) -{ - return (struct SolidSyslogFreeRtosStaticResolver*) base; -} - static bool FreeRtosStaticResolver_Resolve( struct SolidSyslogResolver* base, enum SolidSyslogTransport transport, diff --git a/Platform/FreeRtos/Source/SolidSyslogFreeRtosTcpStream.c b/Platform/FreeRtos/Source/SolidSyslogFreeRtosTcpStream.c index 8affef6c..08685079 100644 --- a/Platform/FreeRtos/Source/SolidSyslogFreeRtosTcpStream.c +++ b/Platform/FreeRtos/Source/SolidSyslogFreeRtosTcpStream.c @@ -98,6 +98,11 @@ void FreeRtosTcpStream_Initialise(struct SolidSyslogStream* base) self->Socket = FREERTOS_INVALID_SOCKET; } +static inline struct SolidSyslogFreeRtosTcpStream* FreeRtosTcpStream_SelfFromBase(struct SolidSyslogStream* base) +{ + return (struct SolidSyslogFreeRtosTcpStream*) base; +} + void FreeRtosTcpStream_Cleanup(struct SolidSyslogStream* base) { struct SolidSyslogFreeRtosTcpStream* self = FreeRtosTcpStream_SelfFromBase(base); @@ -107,9 +112,13 @@ void FreeRtosTcpStream_Cleanup(struct SolidSyslogStream* base) *base = *SolidSyslogNullStream_Get(); } -static inline struct SolidSyslogFreeRtosTcpStream* FreeRtosTcpStream_SelfFromBase(struct SolidSyslogStream* base) +static void FreeRtosTcpStream_CloseSocket(struct SolidSyslogFreeRtosTcpStream* self) { - return (struct SolidSyslogFreeRtosTcpStream*) base; + if (FreeRtosTcpStream_IsOpen(self)) + { + (void) FreeRTOS_closesocket(self->Socket); + self->Socket = FREERTOS_INVALID_SOCKET; + } } static bool FreeRtosTcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr) @@ -272,13 +281,4 @@ static void FreeRtosTcpStream_Close(struct SolidSyslogStream* base) FreeRtosTcpStream_CloseSocket(FreeRtosTcpStream_SelfFromBase(base)); } -static void FreeRtosTcpStream_CloseSocket(struct SolidSyslogFreeRtosTcpStream* self) -{ - if (FreeRtosTcpStream_IsOpen(self)) - { - (void) FreeRTOS_closesocket(self->Socket); - self->Socket = FREERTOS_INVALID_SOCKET; - } -} - // NOLINTEND(performance-no-int-to-ptr) diff --git a/Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c b/Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c index dce6e728..e54e44ce 100644 --- a/Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c +++ b/Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c @@ -55,6 +55,11 @@ void MbedTlsStream_Initialise(struct SolidSyslogStream* base, const struct Solid mbedtls_ssl_config_init(&self->SslConfig); } +static inline struct SolidSyslogMbedTlsStream* MbedTlsStream_SelfFromBase(struct SolidSyslogStream* base) +{ + return (struct SolidSyslogMbedTlsStream*) base; +} + void MbedTlsStream_Cleanup(struct SolidSyslogStream* base) { /* Mirror the OpenSSL TlsStream pattern: an integrator who destroys a @@ -65,9 +70,17 @@ void MbedTlsStream_Cleanup(struct SolidSyslogStream* base) *base = *SolidSyslogNullStream_Get(); } -static inline struct SolidSyslogMbedTlsStream* MbedTlsStream_SelfFromBase(struct SolidSyslogStream* base) +/* Idempotent: a previous Close left the structs in mbedTLS's freed-equivalent + * (zeroed) state, so close_notify sees conf == NULL and returns harmlessly, + * and the *_free calls are no-ops on already-freed structs. Transport Close + * is itself idempotent on every Stream impl. */ +static inline void MbedTlsStream_Close(struct SolidSyslogStream* base) { - return (struct SolidSyslogMbedTlsStream*) base; + struct SolidSyslogMbedTlsStream* self = MbedTlsStream_SelfFromBase(base); + (void) mbedtls_ssl_close_notify(&self->SslContext); + mbedtls_ssl_free(&self->SslContext); + mbedtls_ssl_config_free(&self->SslConfig); + SolidSyslogStream_Close(self->Config.Transport); } static inline bool MbedTlsStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr) @@ -241,16 +254,3 @@ static inline SolidSyslogSsize MbedTlsStream_Read(struct SolidSyslogStream* base } return result; } - -/* Idempotent: a previous Close left the structs in mbedTLS's freed-equivalent - * (zeroed) state, so close_notify sees conf == NULL and returns harmlessly, - * and the *_free calls are no-ops on already-freed structs. Transport Close - * is itself idempotent on every Stream impl. */ -static inline void MbedTlsStream_Close(struct SolidSyslogStream* base) -{ - struct SolidSyslogMbedTlsStream* self = MbedTlsStream_SelfFromBase(base); - (void) mbedtls_ssl_close_notify(&self->SslContext); - mbedtls_ssl_free(&self->SslContext); - mbedtls_ssl_config_free(&self->SslConfig); - SolidSyslogStream_Close(self->Config.Transport); -} diff --git a/Platform/OpenSsl/Source/SolidSyslogTlsStream.c b/Platform/OpenSsl/Source/SolidSyslogTlsStream.c index d9535116..f5362e64 100644 --- a/Platform/OpenSsl/Source/SolidSyslogTlsStream.c +++ b/Platform/OpenSsl/Source/SolidSyslogTlsStream.c @@ -65,6 +65,11 @@ void TlsStream_Initialise(struct SolidSyslogStream* base, const struct SolidSysl self->BioMethod = NULL; } +static inline struct SolidSyslogTlsStream* TlsStream_SelfFromBase(struct SolidSyslogStream* base) +{ + return (struct SolidSyslogTlsStream*) base; +} + void TlsStream_Cleanup(struct SolidSyslogStream* base) { struct SolidSyslogTlsStream* self = TlsStream_SelfFromBase(base); @@ -80,9 +85,18 @@ void TlsStream_Cleanup(struct SolidSyslogStream* base) *base = *SolidSyslogNullStream_Get(); } -static inline struct SolidSyslogTlsStream* TlsStream_SelfFromBase(struct SolidSyslogStream* base) +/* Idempotent: Send/Read may close internally on failure, after which the + * StreamSender's reconnect path or the caller's Destroy may call Close + * again. Skipping when ssl is already NULL keeps that safe. */ +static inline void TlsStream_Close(struct SolidSyslogStream* base) { - return (struct SolidSyslogTlsStream*) base; + struct SolidSyslogTlsStream* self = TlsStream_SelfFromBase(base); + if (self->Ssl != NULL) + { + SSL_shutdown(self->Ssl); + TlsStream_ReleaseHandshakeState(self); + } + SolidSyslogStream_Close(self->Config.Transport); } static inline void TlsStream_ReleaseHandshakeState(struct SolidSyslogTlsStream* self) @@ -419,17 +433,3 @@ static inline SolidSyslogSsize TlsStream_Read(struct SolidSyslogStream* base, vo } return result; } - -/* Idempotent: Send/Read may close internally on failure, after which the - * StreamSender's reconnect path or the caller's Destroy may call Close - * again. Skipping when ssl is already NULL keeps that safe. */ -static inline void TlsStream_Close(struct SolidSyslogStream* base) -{ - struct SolidSyslogTlsStream* self = TlsStream_SelfFromBase(base); - if (self->Ssl != NULL) - { - SSL_shutdown(self->Ssl); - TlsStream_ReleaseHandshakeState(self); - } - SolidSyslogStream_Close(self->Config.Transport); -} diff --git a/Platform/Posix/Source/SolidSyslogPosixAddressStatic.c b/Platform/Posix/Source/SolidSyslogPosixAddressStatic.c index 935bcc50..0b53d630 100644 --- a/Platform/Posix/Source/SolidSyslogPosixAddressStatic.c +++ b/Platform/Posix/Source/SolidSyslogPosixAddressStatic.c @@ -43,6 +43,11 @@ struct SolidSyslogAddress* SolidSyslogPosixAddress_Create(void) return handle; } +static inline struct SolidSyslogAddress* PosixAddress_HandleFromIndex(size_t index) +{ + return (struct SolidSyslogAddress*) &PosixAddress_Pool[index]; +} + void SolidSyslogPosixAddress_Destroy(struct SolidSyslogAddress* base) { size_t index = PosixAddress_IndexFromHandle(base); @@ -55,11 +60,6 @@ void SolidSyslogPosixAddress_Destroy(struct SolidSyslogAddress* base) } } -static inline struct SolidSyslogAddress* PosixAddress_HandleFromIndex(size_t index) -{ - return (struct SolidSyslogAddress*) &PosixAddress_Pool[index]; -} - static inline size_t PosixAddress_IndexFromHandle(const struct SolidSyslogAddress* base) { size_t result = SOLIDSYSLOG_ADDRESS_POOL_SIZE; diff --git a/Platform/Posix/Source/SolidSyslogPosixDatagram.c b/Platform/Posix/Source/SolidSyslogPosixDatagram.c index 4191c9a3..bdbad0a1 100644 --- a/Platform/Posix/Source/SolidSyslogPosixDatagram.c +++ b/Platform/Posix/Source/SolidSyslogPosixDatagram.c @@ -50,6 +50,11 @@ void PosixDatagram_Initialise(struct SolidSyslogDatagram* base) self->Connected = false; } +static inline struct SolidSyslogPosixDatagram* PosixDatagram_SelfFromBase(struct SolidSyslogDatagram* base) +{ + return (struct SolidSyslogPosixDatagram*) base; +} + void PosixDatagram_Cleanup(struct SolidSyslogDatagram* base) { struct SolidSyslogPosixDatagram* self = PosixDatagram_SelfFromBase(base); @@ -64,6 +69,11 @@ void PosixDatagram_Cleanup(struct SolidSyslogDatagram* base) *base = *SolidSyslogNullDatagram_Get(); } +static inline bool PosixDatagram_IsFileDescriptorValid(int fd) +{ + return fd >= 0; +} + static bool PosixDatagram_Open(struct SolidSyslogDatagram* base) { struct SolidSyslogPosixDatagram* self = PosixDatagram_SelfFromBase(base); @@ -72,16 +82,6 @@ static bool PosixDatagram_Open(struct SolidSyslogDatagram* base) return PosixDatagram_IsFileDescriptorValid(self->Fd); } -static inline struct SolidSyslogPosixDatagram* PosixDatagram_SelfFromBase(struct SolidSyslogDatagram* base) -{ - return (struct SolidSyslogPosixDatagram*) base; -} - -static inline bool PosixDatagram_IsFileDescriptorValid(int fd) -{ - return fd >= 0; -} - static enum SolidSyslogDatagramSendResult PosixDatagram_SendTo( struct SolidSyslogDatagram* base, const void* buffer, diff --git a/Platform/Posix/Source/SolidSyslogPosixTcpStream.c b/Platform/Posix/Source/SolidSyslogPosixTcpStream.c index ddb9e963..bc4aeb06 100644 --- a/Platform/Posix/Source/SolidSyslogPosixTcpStream.c +++ b/Platform/Posix/Source/SolidSyslogPosixTcpStream.c @@ -70,6 +70,11 @@ void PosixTcpStream_Initialise(struct SolidSyslogStream* base) self->Fd = INVALID_FD; } +static inline struct SolidSyslogPosixTcpStream* PosixTcpStream_SelfFromBase(struct SolidSyslogStream* base) +{ + return (struct SolidSyslogPosixTcpStream*) base; +} + void PosixTcpStream_Cleanup(struct SolidSyslogStream* base) { struct SolidSyslogPosixTcpStream* self = PosixTcpStream_SelfFromBase(base); @@ -83,9 +88,9 @@ void PosixTcpStream_Cleanup(struct SolidSyslogStream* base) *base = *SolidSyslogNullStream_Get(); } -static inline struct SolidSyslogPosixTcpStream* PosixTcpStream_SelfFromBase(struct SolidSyslogStream* base) +static inline bool PosixTcpStream_IsFileDescriptorValid(int fd) { - return (struct SolidSyslogPosixTcpStream*) base; + return (fd >= 0); } static bool PosixTcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr) @@ -155,11 +160,6 @@ static bool PosixTcpStream_SetNonBlocking(int fd) return (flags >= 0) && (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1); } -static inline bool PosixTcpStream_IsFileDescriptorValid(int fd) -{ - return (fd >= 0); -} - static bool PosixTcpStream_ConnectOrCloseOnFailure( struct SolidSyslogPosixTcpStream* self, const struct sockaddr_in* sin diff --git a/Platform/Windows/Source/SolidSyslogWindowsAtomicCounter.c b/Platform/Windows/Source/SolidSyslogWindowsAtomicCounter.c index 2637573a..41c4be2b 100644 --- a/Platform/Windows/Source/SolidSyslogWindowsAtomicCounter.c +++ b/Platform/Windows/Source/SolidSyslogWindowsAtomicCounter.c @@ -21,11 +21,11 @@ void WindowsAtomicCounter_Initialise(struct SolidSyslogAtomicCounter* base) WindowsAtomicCounter_Init(self, 0U); } -void WindowsAtomicCounter_Cleanup(struct SolidSyslogAtomicCounter* base) +static inline struct SolidSyslogWindowsAtomicCounter* WindowsAtomicCounter_SelfFromBase( + struct SolidSyslogAtomicCounter* base +) { - /* Overwrite the abstract base with the shared NullAtomicCounter vtable so - * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */ - *base = *SolidSyslogNullAtomicCounter_Get(); + return (struct SolidSyslogWindowsAtomicCounter*) base; } void WindowsAtomicCounter_Init(struct SolidSyslogWindowsAtomicCounter* self, uint32_t value) @@ -33,11 +33,11 @@ void WindowsAtomicCounter_Init(struct SolidSyslogWindowsAtomicCounter* self, uin self->Value = (LONG) value; } -static inline struct SolidSyslogWindowsAtomicCounter* WindowsAtomicCounter_SelfFromBase( - struct SolidSyslogAtomicCounter* base -) +void WindowsAtomicCounter_Cleanup(struct SolidSyslogAtomicCounter* base) { - return (struct SolidSyslogWindowsAtomicCounter*) base; + /* Overwrite the abstract base with the shared NullAtomicCounter vtable so + * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */ + *base = *SolidSyslogNullAtomicCounter_Get(); } static uint32_t WindowsAtomicCounter_Increment(struct SolidSyslogAtomicCounter* base) diff --git a/Platform/Windows/Source/SolidSyslogWinsockAddressStatic.c b/Platform/Windows/Source/SolidSyslogWinsockAddressStatic.c index 95fc4682..862d6939 100644 --- a/Platform/Windows/Source/SolidSyslogWinsockAddressStatic.c +++ b/Platform/Windows/Source/SolidSyslogWinsockAddressStatic.c @@ -43,6 +43,11 @@ struct SolidSyslogAddress* SolidSyslogWinsockAddress_Create(void) return handle; } +static inline struct SolidSyslogAddress* WinsockAddress_HandleFromIndex(size_t index) +{ + return (struct SolidSyslogAddress*) &WinsockAddress_Pool[index]; +} + void SolidSyslogWinsockAddress_Destroy(struct SolidSyslogAddress* base) { size_t index = WinsockAddress_IndexFromHandle(base); @@ -55,11 +60,6 @@ void SolidSyslogWinsockAddress_Destroy(struct SolidSyslogAddress* base) } } -static inline struct SolidSyslogAddress* WinsockAddress_HandleFromIndex(size_t index) -{ - return (struct SolidSyslogAddress*) &WinsockAddress_Pool[index]; -} - static inline size_t WinsockAddress_IndexFromHandle(const struct SolidSyslogAddress* base) { size_t result = SOLIDSYSLOG_ADDRESS_POOL_SIZE; diff --git a/Platform/Windows/Source/SolidSyslogWinsockDatagram.c b/Platform/Windows/Source/SolidSyslogWinsockDatagram.c index 79c2cc80..7661074d 100644 --- a/Platform/Windows/Source/SolidSyslogWinsockDatagram.c +++ b/Platform/Windows/Source/SolidSyslogWinsockDatagram.c @@ -89,6 +89,11 @@ void WinsockDatagram_Initialise(struct SolidSyslogDatagram* base) self->Connected = false; } +static inline struct SolidSyslogWinsockDatagram* WinsockDatagram_SelfFromBase(struct SolidSyslogDatagram* base) +{ + return (struct SolidSyslogWinsockDatagram*) base; +} + void WinsockDatagram_Cleanup(struct SolidSyslogDatagram* base) { struct SolidSyslogWinsockDatagram* self = WinsockDatagram_SelfFromBase(base); @@ -103,6 +108,11 @@ void WinsockDatagram_Cleanup(struct SolidSyslogDatagram* base) *base = *SolidSyslogNullDatagram_Get(); } +static inline bool WinsockDatagram_IsSocketValid(SOCKET fd) +{ + return fd != INVALID_SOCKET; +} + static bool WinsockDatagram_Open(struct SolidSyslogDatagram* base) { struct SolidSyslogWinsockDatagram* self = WinsockDatagram_SelfFromBase(base); @@ -111,16 +121,6 @@ static bool WinsockDatagram_Open(struct SolidSyslogDatagram* base) return WinsockDatagram_IsSocketValid(self->Fd); } -static inline struct SolidSyslogWinsockDatagram* WinsockDatagram_SelfFromBase(struct SolidSyslogDatagram* base) -{ - return (struct SolidSyslogWinsockDatagram*) base; -} - -static inline bool WinsockDatagram_IsSocketValid(SOCKET fd) -{ - return fd != INVALID_SOCKET; -} - static enum SolidSyslogDatagramSendResult WinsockDatagram_SendTo( struct SolidSyslogDatagram* base, const void* buffer, diff --git a/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c b/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c index 6a3fe8fc..abfe35b3 100644 --- a/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c +++ b/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c @@ -155,6 +155,11 @@ void WinsockTcpStream_Initialise(struct SolidSyslogStream* base) self->Fd = INVALID_SOCKET; } +static inline struct SolidSyslogWinsockTcpStream* WinsockTcpStream_SelfFromBase(struct SolidSyslogStream* base) +{ + return (struct SolidSyslogWinsockTcpStream*) base; +} + void WinsockTcpStream_Cleanup(struct SolidSyslogStream* base) { WinsockTcpStream_Close(base); @@ -163,9 +168,14 @@ void WinsockTcpStream_Cleanup(struct SolidSyslogStream* base) *base = *SolidSyslogNullStream_Get(); } -static inline struct SolidSyslogWinsockTcpStream* WinsockTcpStream_SelfFromBase(struct SolidSyslogStream* base) +static void WinsockTcpStream_Close(struct SolidSyslogStream* base) { - return (struct SolidSyslogWinsockTcpStream*) base; + struct SolidSyslogWinsockTcpStream* self = WinsockTcpStream_SelfFromBase(base); + if (WinsockTcpStream_IsSocketValid(self->Fd)) + { + WinsockTcpStream_closesocket(self->Fd); + self->Fd = INVALID_SOCKET; + } } static bool WinsockTcpStream_Open(struct SolidSyslogStream* base, const struct SolidSyslogAddress* addr) @@ -351,13 +361,3 @@ static inline bool WinsockTcpStream_WouldBlock(int wsaError) { return wsaError == WSAEWOULDBLOCK; } - -static void WinsockTcpStream_Close(struct SolidSyslogStream* base) -{ - struct SolidSyslogWinsockTcpStream* self = WinsockTcpStream_SelfFromBase(base); - if (WinsockTcpStream_IsSocketValid(self->Fd)) - { - WinsockTcpStream_closesocket(self->Fd); - self->Fd = INVALID_SOCKET; - } -}