From d35215e3a33db4c4e040d93cc06bdfa11a1a71c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 10:42:32 +0000 Subject: [PATCH 1/3] Initial plan From 4e6dfd019e48534224d91246321b6b67b88fb45e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 10:46:18 +0000 Subject: [PATCH 2/3] feat: add max_count support to SAL semaphore creation --- inc/dmod_sal.h | 2 +- src/system/if/dmod_if_rtos.c | 43 +++++++++++++++++--- tests/system/public/tests_dmod_semaphore.cpp | 20 ++++++++- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/inc/dmod_sal.h b/inc/dmod_sal.h index e584789..e185312 100644 --- a/inc/dmod_sal.h +++ b/inc/dmod_sal.h @@ -323,7 +323,7 @@ DMOD_BUILTIN_API(Dmod, 1.0, void*, _Mutex_New, ( bool Recursive ) ); DMOD_BUILTIN_API(Dmod, 1.0, int , _Mutex_Lock, ( void* Mutex ) ); DMOD_BUILTIN_API(Dmod, 1.0, int , _Mutex_Unlock, ( void* Mutex ) ); DMOD_BUILTIN_API(Dmod, 1.0, void , _Mutex_Delete, ( void* Mutex ) ); -DMOD_BUILTIN_API(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t InitialValue ) ); +DMOD_BUILTIN_API(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t InitialValue, uint32_t MaxCount ) ); DMOD_BUILTIN_API(Dmod, 1.0, int , _Semaphore_Wait, ( void* Semaphore ) ); DMOD_BUILTIN_API(Dmod, 1.0, int , _Semaphore_Post, ( void* Semaphore ) ); DMOD_BUILTIN_API(Dmod, 1.0, void , _Semaphore_Delete, ( void* Semaphore ) ); diff --git a/src/system/if/dmod_if_rtos.c b/src/system/if/dmod_if_rtos.c index 8a1d042..e2c7ffd 100644 --- a/src/system/if/dmod_if_rtos.c +++ b/src/system/if/dmod_if_rtos.c @@ -39,6 +39,14 @@ extern int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, s # endif #endif +#if DMOD_USE_PTHREAD +typedef struct +{ + sem_t Semaphore; + uint32_t MaxCount; +} Dmod_Semaphore_t; +#endif + //============================================================================== // FUNCTIONS DECLARATIONS //============================================================================== @@ -183,29 +191,38 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void, _Mutex_Delete, ( void* Mutex )) * @brief Create new semaphore * * @param InitialValue Initial semaphore value + * @param MaxCount Maximum semaphore value * * @return Pointer to new semaphore */ -DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t InitialValue )) +DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t InitialValue, uint32_t MaxCount )) { #if DMOD_USE_PTHREAD - sem_t* Semaphore = Dmod_Malloc(sizeof(sem_t)); + if( ( MaxCount == 0 ) || ( InitialValue > MaxCount ) ) + { + DMOD_LOG_ERROR("Cannot create new semaphore - invalid initial or max value\n"); + return NULL; + } + + Dmod_Semaphore_t* Semaphore = Dmod_Malloc(sizeof(Dmod_Semaphore_t)); if( Semaphore == NULL ) { DMOD_LOG_ERROR("Cannot create new semaphore - cannot allocate memory\n"); return NULL; } - if( sem_init(Semaphore, 0, InitialValue) != 0 ) + if( sem_init(&Semaphore->Semaphore, 0, InitialValue) != 0 ) { DMOD_LOG_ERROR("Cannot create new semaphore - cannot initialize semaphore\n"); Dmod_Free(Semaphore); return NULL; } + Semaphore->MaxCount = MaxCount; return Semaphore; #else (void)InitialValue; + (void)MaxCount; return NULL; #endif } @@ -226,7 +243,7 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semapho return -EINVAL; } - return sem_wait(Semaphore); + return sem_wait(&((Dmod_Semaphore_t*)Semaphore)->Semaphore); #else if( Semaphore == NULL ) { @@ -256,7 +273,21 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Post, ( void* Semapho return -EINVAL; } - return sem_post(Semaphore); + Dmod_Semaphore_t* SemaphoreObj = (Dmod_Semaphore_t*)Semaphore; + int SemaphoreValue = 0; + if( sem_getvalue(&SemaphoreObj->Semaphore, &SemaphoreValue) != 0 ) + { + DMOD_LOG_ERROR("Cannot post semaphore - cannot get semaphore value\n"); + return -errno; + } + + if( SemaphoreValue >= (int)SemaphoreObj->MaxCount ) + { + DMOD_LOG_ERROR("Cannot post semaphore - maximum value reached\n"); + return -EOVERFLOW; + } + + return sem_post(&SemaphoreObj->Semaphore); #else if( Semaphore == NULL ) { @@ -284,7 +315,7 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void, _Semaphore_Delete, ( void* Sema return; } - if( sem_destroy(Semaphore) != 0 ) + if( sem_destroy(&((Dmod_Semaphore_t*)Semaphore)->Semaphore) != 0 ) { DMOD_LOG_ERROR("Cannot delete semaphore - cannot destroy semaphore\n"); } diff --git a/tests/system/public/tests_dmod_semaphore.cpp b/tests/system/public/tests_dmod_semaphore.cpp index da68ce9..a6a6d79 100644 --- a/tests/system/public/tests_dmod_semaphore.cpp +++ b/tests/system/public/tests_dmod_semaphore.cpp @@ -4,7 +4,7 @@ TEST(DmodSemaphoreTest, NewWaitPostDelete) { - void* semaphore = Dmod_Semaphore_New(1); + void* semaphore = Dmod_Semaphore_New(1, 2); ASSERT_NE(semaphore, nullptr); EXPECT_EQ(Dmod_Semaphore_Wait(semaphore), 0); @@ -14,6 +14,24 @@ TEST(DmodSemaphoreTest, NewWaitPostDelete) Dmod_Semaphore_Delete(semaphore); } +TEST(DmodSemaphoreTest, HandlesMaxCount) +{ + void* semaphore = Dmod_Semaphore_New(1, 1); + ASSERT_NE(semaphore, nullptr); + + EXPECT_EQ(Dmod_Semaphore_Post(semaphore), -EOVERFLOW); + EXPECT_EQ(Dmod_Semaphore_Wait(semaphore), 0); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore), 0); + + Dmod_Semaphore_Delete(semaphore); +} + +TEST(DmodSemaphoreTest, RejectsInvalidInitialOrMaxCount) +{ + EXPECT_EQ(Dmod_Semaphore_New(1, 0), nullptr); + EXPECT_EQ(Dmod_Semaphore_New(2, 1), nullptr); +} + TEST(DmodSemaphoreTest, HandlesNullSemaphore) { EXPECT_EQ(Dmod_Semaphore_Wait(nullptr), -EINVAL); From 728e69050b9dd7d35925d77af45a126b211cc4c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Jun 2026 10:55:42 +0000 Subject: [PATCH 3/3] feat: add quantity support for semaphore wait/post --- inc/dmod_sal.h | 4 +- src/system/if/dmod_if_rtos.c | 42 +++++++++++++++++--- tests/system/public/tests_dmod_semaphore.cpp | 30 ++++++++++---- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/inc/dmod_sal.h b/inc/dmod_sal.h index e185312..ed57f5f 100644 --- a/inc/dmod_sal.h +++ b/inc/dmod_sal.h @@ -324,8 +324,8 @@ DMOD_BUILTIN_API(Dmod, 1.0, int , _Mutex_Lock, ( void* Mutex ) ); DMOD_BUILTIN_API(Dmod, 1.0, int , _Mutex_Unlock, ( void* Mutex ) ); DMOD_BUILTIN_API(Dmod, 1.0, void , _Mutex_Delete, ( void* Mutex ) ); DMOD_BUILTIN_API(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t InitialValue, uint32_t MaxCount ) ); -DMOD_BUILTIN_API(Dmod, 1.0, int , _Semaphore_Wait, ( void* Semaphore ) ); -DMOD_BUILTIN_API(Dmod, 1.0, int , _Semaphore_Post, ( void* Semaphore ) ); +DMOD_BUILTIN_API(Dmod, 1.0, int , _Semaphore_Wait, ( void* Semaphore, uint32_t Count ) ); +DMOD_BUILTIN_API(Dmod, 1.0, int , _Semaphore_Post, ( void* Semaphore, uint32_t Count ) ); DMOD_BUILTIN_API(Dmod, 1.0, void , _Semaphore_Delete, ( void* Semaphore ) ); DMOD_BUILTIN_API(Dmod, 1.0, size_t, _GetLeftStackSize, ( void ) ); diff --git a/src/system/if/dmod_if_rtos.c b/src/system/if/dmod_if_rtos.c index e2c7ffd..b4524c1 100644 --- a/src/system/if/dmod_if_rtos.c +++ b/src/system/if/dmod_if_rtos.c @@ -231,10 +231,11 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t Ini * @brief Wait for semaphore * * @param Semaphore Semaphore to wait for + * @param Count Number of semaphore units to wait for * * @return 0 on success, negative errno on error */ -DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semaphore )) +DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semaphore, uint32_t Count )) { #if DMOD_USE_PTHREAD if( Semaphore == NULL ) @@ -243,7 +244,20 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semapho return -EINVAL; } - return sem_wait(&((Dmod_Semaphore_t*)Semaphore)->Semaphore); + Dmod_Semaphore_t* SemaphoreObj = (Dmod_Semaphore_t*)Semaphore; + for( uint32_t i = 0; i < Count; i++ ) + { + while( sem_wait(&SemaphoreObj->Semaphore) != 0 ) + { + if( errno != EINTR ) + { + DMOD_LOG_ERROR("Cannot wait for semaphore - cannot wait semaphore unit\n"); + return -errno; + } + } + } + + return 0; #else if( Semaphore == NULL ) { @@ -251,6 +265,7 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semapho } else { + (void)Count; DMOD_LOG_WARN("Dmod_Semaphore_Wait interface not implemented\n"); return -ENOSYS; } @@ -261,10 +276,11 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semapho * @brief Post semaphore * * @param Semaphore Semaphore to post + * @param Count Number of semaphore units to post * * @return 0 on success, negative errno on error */ -DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Post, ( void* Semaphore )) +DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Post, ( void* Semaphore, uint32_t Count )) { #if DMOD_USE_PTHREAD if( Semaphore == NULL ) @@ -281,13 +297,28 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Post, ( void* Semapho return -errno; } - if( SemaphoreValue >= (int)SemaphoreObj->MaxCount ) + if( Count > SemaphoreObj->MaxCount ) + { + DMOD_LOG_ERROR("Cannot post semaphore - maximum value reached\n"); + return -EOVERFLOW; + } + + if( ( SemaphoreValue >= 0 ) && ( (uint32_t)SemaphoreValue > ( SemaphoreObj->MaxCount - Count ) ) ) { DMOD_LOG_ERROR("Cannot post semaphore - maximum value reached\n"); return -EOVERFLOW; } - return sem_post(&SemaphoreObj->Semaphore); + for( uint32_t i = 0; i < Count; i++ ) + { + if( sem_post(&SemaphoreObj->Semaphore) != 0 ) + { + DMOD_LOG_ERROR("Cannot post semaphore - cannot signal semaphore unit\n"); + return -errno; + } + } + + return 0; #else if( Semaphore == NULL ) { @@ -295,6 +326,7 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Post, ( void* Semapho } else { + (void)Count; DMOD_LOG_WARN("Dmod_Semaphore_Post interface not implemented\n"); return -ENOSYS; } diff --git a/tests/system/public/tests_dmod_semaphore.cpp b/tests/system/public/tests_dmod_semaphore.cpp index a6a6d79..dbafccd 100644 --- a/tests/system/public/tests_dmod_semaphore.cpp +++ b/tests/system/public/tests_dmod_semaphore.cpp @@ -7,9 +7,9 @@ TEST(DmodSemaphoreTest, NewWaitPostDelete) void* semaphore = Dmod_Semaphore_New(1, 2); ASSERT_NE(semaphore, nullptr); - EXPECT_EQ(Dmod_Semaphore_Wait(semaphore), 0); - EXPECT_EQ(Dmod_Semaphore_Post(semaphore), 0); - EXPECT_EQ(Dmod_Semaphore_Wait(semaphore), 0); + EXPECT_EQ(Dmod_Semaphore_Wait(semaphore, 1), 0); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore, 1), 0); + EXPECT_EQ(Dmod_Semaphore_Wait(semaphore, 1), 0); Dmod_Semaphore_Delete(semaphore); } @@ -19,9 +19,23 @@ TEST(DmodSemaphoreTest, HandlesMaxCount) void* semaphore = Dmod_Semaphore_New(1, 1); ASSERT_NE(semaphore, nullptr); - EXPECT_EQ(Dmod_Semaphore_Post(semaphore), -EOVERFLOW); - EXPECT_EQ(Dmod_Semaphore_Wait(semaphore), 0); - EXPECT_EQ(Dmod_Semaphore_Post(semaphore), 0); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore, 1), -EOVERFLOW); + EXPECT_EQ(Dmod_Semaphore_Wait(semaphore, 1), 0); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore, 1), 0); + + Dmod_Semaphore_Delete(semaphore); +} + +TEST(DmodSemaphoreTest, HandlesWaitAndPostCount) +{ + void* semaphore = Dmod_Semaphore_New(2, 3); + ASSERT_NE(semaphore, nullptr); + + EXPECT_EQ(Dmod_Semaphore_Wait(semaphore, 2), 0); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore, 2), 0); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore, 2), -EOVERFLOW); + EXPECT_EQ(Dmod_Semaphore_Post(semaphore, 0), 0); + EXPECT_EQ(Dmod_Semaphore_Wait(semaphore, 0), 0); Dmod_Semaphore_Delete(semaphore); } @@ -34,7 +48,7 @@ TEST(DmodSemaphoreTest, RejectsInvalidInitialOrMaxCount) TEST(DmodSemaphoreTest, HandlesNullSemaphore) { - EXPECT_EQ(Dmod_Semaphore_Wait(nullptr), -EINVAL); - EXPECT_EQ(Dmod_Semaphore_Post(nullptr), -EINVAL); + EXPECT_EQ(Dmod_Semaphore_Wait(nullptr, 1), -EINVAL); + EXPECT_EQ(Dmod_Semaphore_Post(nullptr, 1), -EINVAL); EXPECT_NO_FATAL_FAILURE(Dmod_Semaphore_Delete(nullptr)); }