Branch data Line data Source code
1 : : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
2 : : * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
3 : : */
4 : :
5 : : #include "SolidSyslogCmsisRtosMutex.h"
6 : :
7 : : #include <stdbool.h>
8 : : #include <stddef.h>
9 : : #include <stdint.h>
10 : :
11 : : #include "cmsis_os2.h"
12 : :
13 : : #include "SolidSyslogCmsisRtosMutexPrivate.h"
14 : : #include "SolidSyslogError.h"
15 : : #include "SolidSyslogErrorCategory.h"
16 : : #include "SolidSyslogMutexDefinition.h"
17 : : #include "SolidSyslogNullMutex.h"
18 : :
19 : : const struct SolidSyslogErrorSource SolidSyslogCmsisRtosMutexErrorSource = {
20 : : "CmsisRtosMutex",
21 : : SolidSyslogMutexErrors_Name
22 : : };
23 : :
24 : : static void CmsisRtosMutex_Lock(struct SolidSyslogMutex* base);
25 : : static void CmsisRtosMutex_Unlock(struct SolidSyslogMutex* base);
26 : :
27 : : static inline osMutexAttr_t CmsisRtosMutex_AttributesFor(void* controlBlock, uint32_t controlBlockBytes);
28 : : static inline struct SolidSyslogCmsisRtosMutex* CmsisRtosMutex_SelfFromBase(struct SolidSyslogMutex* base);
29 : : static inline bool CmsisRtosMutex_HasRtosMutex(const struct SolidSyslogCmsisRtosMutex* self);
30 : :
31 : 26 : bool SolidSyslogCmsisRtosMutex_Initialise(struct SolidSyslogMutex* base, void* controlBlock, uint32_t controlBlockBytes)
32 : : {
33 : 26 : osMutexAttr_t attributes = CmsisRtosMutex_AttributesFor(controlBlock, controlBlockBytes);
34 : 26 : struct SolidSyslogCmsisRtosMutex* self = CmsisRtosMutex_SelfFromBase(base);
35 : 26 : self->Id = osMutexNew(&attributes);
36 : 26 : bool created = CmsisRtosMutex_HasRtosMutex(self);
37 [ + + ]: 26 : if (created == true)
38 : : {
39 : 20 : self->Base.Lock = CmsisRtosMutex_Lock;
40 : 20 : self->Base.Unlock = CmsisRtosMutex_Unlock;
41 : : }
42 : : else
43 : : {
44 : : /* The control block was too small for the object this implementation
45 : : * builds, a size only the integrator can know. Present the NullMutex
46 : : * rather than a handle with nothing behind it, and say so. */
47 : 6 : *base = *SolidSyslogNullMutex_Get();
48 : 6 : CmsisRtosMutex_Report(
49 : : SOLIDSYSLOG_BAD_CONFIG_FATAL_SEVERITY,
50 : : SOLIDSYSLOG_CAT_BAD_CONFIG,
51 : : SOLIDSYSLOG_MUTEX_ERROR_CREATE_FAILED
52 : : );
53 : : }
54 : 26 : return created;
55 : : }
56 : :
57 : 26 : static inline osMutexAttr_t CmsisRtosMutex_AttributesFor(void* controlBlock, uint32_t controlBlockBytes)
58 : : {
59 : : /* Priority inheritance is what stops a low-priority task holding the buffer
60 : : * lock from being preempted indefinitely while a high-priority task waits
61 : : * on it. An implementation whose mutexes always inherit ignores the bit;
62 : : * one that does not needs asking.
63 : : *
64 : : * The control block is the caller's, unread here and passed straight
65 : : * through: CMSIS-RTOS2 leaves its size to the implementation, so the
66 : : * library cannot size one. NULL and zero together are the form CMSIS
67 : : * defines for letting the implementation allocate instead. */
68 : 26 : osMutexAttr_t attributes = {NULL, osMutexPrioInherit, controlBlock, controlBlockBytes};
69 : 26 : return attributes;
70 : : }
71 : :
72 : 57 : static inline struct SolidSyslogCmsisRtosMutex* CmsisRtosMutex_SelfFromBase(struct SolidSyslogMutex* base)
73 : : {
74 : 57 : return (struct SolidSyslogCmsisRtosMutex*) base;
75 : : }
76 : :
77 : 52 : static inline bool CmsisRtosMutex_HasRtosMutex(const struct SolidSyslogCmsisRtosMutex* self)
78 : : {
79 : 52 : return self->Id != NULL;
80 : : }
81 : :
82 : 26 : void SolidSyslogCmsisRtosMutex_Cleanup(struct SolidSyslogMutex* base)
83 : : {
84 : 26 : struct SolidSyslogCmsisRtosMutex* self = CmsisRtosMutex_SelfFromBase(base);
85 [ + + ]: 26 : if (CmsisRtosMutex_HasRtosMutex(self) == true)
86 : : {
87 : 20 : (void) osMutexDelete(self->Id);
88 : : }
89 : : /* Overwrite the abstract base with the shared NullMutex vtable so
90 : : * use-after-destroy is a safe no-op rather than a NULL-fn-pointer crash. */
91 : 26 : *base = *SolidSyslogNullMutex_Get();
92 : 26 : }
93 : :
94 : 4 : static void CmsisRtosMutex_Lock(struct SolidSyslogMutex* base)
95 : : {
96 : 4 : (void) osMutexAcquire(CmsisRtosMutex_SelfFromBase(base)->Id, osWaitForever);
97 : 4 : }
98 : :
99 : 1 : static void CmsisRtosMutex_Unlock(struct SolidSyslogMutex* base)
100 : : {
101 : 1 : (void) osMutexRelease(CmsisRtosMutex_SelfFromBase(base)->Id);
102 : 1 : }
|