Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,10 @@ It is also **recommended** (but not mandatory) to define those:
| `Dmod_Mutex_Delete` | *Releases mutex memory* |
| `Dmod_Mutex_Lock` | *Locks the mutex* |
| `Dmod_Mutex_Unlock` | *Unlocks the mutex* |
| `Dmod_Semaphore_New` | *Creates new semaphore* |
| `Dmod_Semaphore_Wait`| *Waits for semaphore* |
| `Dmod_Semaphore_Post`| *Signals semaphore* |
| `Dmod_Semaphore_Delete`| *Releases semaphore memory* |

6. **Initialize the Dmod system**: Before using any Dmod functions, you must call `Dmod_Initialize()` to initialize the system's global variables. This function should be called once at the beginning of your application, before loading any modules.

Expand Down Expand Up @@ -868,4 +872,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

4 changes: 4 additions & 0 deletions inc/dmod_sal.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,10 @@ 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, 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 ) );
DMOD_BUILTIN_API(Dmod, 1.0, size_t, _GetLeftStackSize, ( void ) );

//! @}
Expand Down
124 changes: 124 additions & 0 deletions src/system/if/dmod_if_rtos.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#if DMOD_USE_PTHREAD
# define __USE_UNIX98
# include <pthread.h>
# include <semaphore.h>
# ifdef __linux__
/* Forward declarations for Linux-specific thread attribute functions */
extern int pthread_getattr_np(pthread_t th, pthread_attr_t *attr);
Expand Down Expand Up @@ -178,6 +179,129 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void, _Mutex_Delete, ( void* Mutex ))
#endif
}

/**
* @brief Create new semaphore
*
* @param InitialValue Initial semaphore value
*
* @return Pointer to new semaphore
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void*, _Semaphore_New, ( uint32_t InitialValue ))
{
#if DMOD_USE_PTHREAD
sem_t* Semaphore = Dmod_Malloc(sizeof(sem_t));
if( Semaphore == NULL )
{
DMOD_LOG_ERROR("Cannot create new semaphore - cannot allocate memory\n");
return NULL;
}

if( sem_init(Semaphore, 0, InitialValue) != 0 )
{
DMOD_LOG_ERROR("Cannot create new semaphore - cannot initialize semaphore\n");
Dmod_Free(Semaphore);
return NULL;
}

return Semaphore;
#else
(void)InitialValue;
return NULL;
#endif
}

/**
* @brief Wait for semaphore
*
* @param Semaphore Semaphore to wait for
*
* @return 0 on success, negative errno on error
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Wait, ( void* Semaphore ))
{
#if DMOD_USE_PTHREAD
if( Semaphore == NULL )
{
DMOD_LOG_ERROR("Cannot wait for semaphore - invalid semaphore\n");
return -EINVAL;
}

return sem_wait(Semaphore);
#else
if( Semaphore == NULL )
{
return 0; // No-op if semaphore is NULL
}
else
{
DMOD_LOG_WARN("Dmod_Semaphore_Wait interface not implemented\n");
return -ENOSYS;
}
#endif
}

/**
* @brief Post semaphore
*
* @param Semaphore Semaphore to post
*
* @return 0 on success, negative errno on error
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, int, _Semaphore_Post, ( void* Semaphore ))
{
#if DMOD_USE_PTHREAD
if( Semaphore == NULL )
{
DMOD_LOG_ERROR("Cannot post semaphore - invalid semaphore\n");
return -EINVAL;
}

return sem_post(Semaphore);
#else
if( Semaphore == NULL )
{
return 0; // No-op if semaphore is NULL
}
else
{
DMOD_LOG_WARN("Dmod_Semaphore_Post interface not implemented\n");
return -ENOSYS;
}
#endif
}

/**
* @brief Delete semaphore
*
* @param Semaphore Semaphore to delete
*/
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void, _Semaphore_Delete, ( void* Semaphore ))
{
#if DMOD_USE_PTHREAD
if( Semaphore == NULL )
{
DMOD_LOG_ERROR("Cannot delete semaphore - invalid semaphore\n");
return;
}

if( sem_destroy(Semaphore) != 0 )
{
DMOD_LOG_ERROR("Cannot delete semaphore - cannot destroy semaphore\n");
}

Dmod_Free(Semaphore);
#else
if( Semaphore == NULL )
{
return; // No-op if semaphore is NULL
}
else
{
DMOD_LOG_WARN("Dmod_Semaphore_Delete interface not implemented\n");
}
#endif
}

/**
* @brief Get the remaining stack size in the current thread
*
Expand Down
1 change: 1 addition & 0 deletions tests/system/public/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(TEST_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_readnextmodule.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_loadfile_package_path.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_irq.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_semaphore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_verify_apis.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_api_signature.cpp
PARENT_SCOPE
Expand Down
22 changes: 22 additions & 0 deletions tests/system/public/tests_dmod_semaphore.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <errno.h>
#include <gtest/gtest.h>
#include "dmod.h"

TEST(DmodSemaphoreTest, NewWaitPostDelete)
{
void* semaphore = Dmod_Semaphore_New(1);
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);

Dmod_Semaphore_Delete(semaphore);
}

TEST(DmodSemaphoreTest, HandlesNullSemaphore)
{
EXPECT_EQ(Dmod_Semaphore_Wait(nullptr), -EINVAL);
EXPECT_EQ(Dmod_Semaphore_Post(nullptr), -EINVAL);
EXPECT_NO_FATAL_FAILURE(Dmod_Semaphore_Delete(nullptr));
}
Loading