1.修复删除所有消息接口的bug

2.完善初始化时的错误处理
3.添加freeRTOS的支持
4.添加rt-thread的支持
5.消除一些编译警告
This commit is contained in:
2026-01-08 17:30:22 +08:00
parent 403447b4bd
commit 2f4c00fd3d
5 changed files with 221 additions and 113 deletions

View File

@@ -1,6 +1,5 @@
这个软件用于代码模块之间的消息传递,采用发布-订阅的方式传递消息
使用方法:
1. 在 has_task_msg_os_port.h 选择操作系统更改宏MSG_OPT_OS。或选择自定义自己实现接口。
2. 在 has_task_msg.h 中添加自己负责的软件模块id号has_module_ID_e并且完成订阅表 SUBSCIBE_INFO
填表要把模块的id、模块要订阅的id等信息填好。
1. 在 has_task_msg_os_port.h 选择操作系统更改宏MSG_OPT_OS。或选择自定义自己实现接口如果自己定义需要自己实现has_task_msg_os_port.c的相应接口
2. 在 has_task_msg.h 中添加自己负责的软件模块id号has_module_ID_e并且完成订阅表 SUBSCIBE_INFO 要把模块的id、模块要订阅的id等信息填好。
3. 代码中使用:初始化、发布、订阅和消息回调即可。请参考示例 msg_example.c

View File

@@ -15,21 +15,25 @@ typedef enum {
MODULE_MAX
} has_module_ID_e;
#define CHECK_SUBSCIBE_INFO // 如果打开,代码初始化时会检查订阅表是否写错,开发时应该打开
/* 格式:模块 订阅数量 订阅模块 */
#define SUBSCIBE_INFO \
{ \
{GUI, 4, {ACM, SENSOR, WIFI, VOICE}}, \
{SENSOR, 1, {GUI}}, \
{SENSOR, 2, {GUI, WIFI}}, \
{WIFI, 0}, \
}
// #define SUBSCIBE_INFO \
// { \
// {GUI, 4, {ACM, WIFI, VOICE, SENSOR}}, \
// {SENSOR, 5, {ACM, GUI, WIFI, VOICE, SENSOR}}, \
// {ACM, 4, {GUI, WIFI, VOICE, SENSOR}}, \
// {WIFI, 4, {ACM, GUI, VOICE, SENSOR}}, \
// {VOICE, 4, {ACM, WIFI, GUI, SENSOR}}, \
// }
/*
#define SUBSCIBE_INFO \
{ \
{GUI, 4, {ACM, WIFI, VOICE, SENSOR}}, \
{SENSOR, 5, {ACM, GUI, WIFI, VOICE, SENSOR}}, \
{ACM, 4, {GUI, WIFI, VOICE, SENSOR}}, \
{WIFI, 4, {ACM, GUI, VOICE, SENSOR}}, \
{VOICE, 4, {ACM, WIFI, GUI, SENSOR}}, \
}
*/
/**
* @brief 消息处理回调类型

View File

@@ -26,7 +26,8 @@
#define msg_debug(fmt, ...)
#endif
#define MSG_ASSERT {while(1);}
#define MSG_ASSERT \
{msg_printf("!!!!!wrong config!!!!! file:%s line:%d\n", __FILE__, __LINE__);while(1);}
#pragma pack(1)
/* 消息数据 */
@@ -71,7 +72,7 @@ typedef struct {
struct list_head msg_list; // 消息链表
} has_static_sub_list_t;
static has_static_sub_list_t g_sub_list[] = SUBSCIBE_INFO;
static unsigned char g_sub_list_index[MODULE_MAX]; // 订阅表id索引
static unsigned char g_sub_list_index[MODULE_MAX]; // 订阅表id索引,同时表示模块是否可用
/* 检查ID是否合法id:检查的IDret:不合法时return的值 */
@@ -87,17 +88,19 @@ if (g_sub_list_index[(id)] == MODULE_MAX) { \
return (ret);}
/**
* @brief 初始化消息表
* @brief 初始化消息表,必须在所有接口调用之前调用init
*
* @return 0:成功 -1失败
*/
int has_msg_init()
{
int j;
has_static_pub_list_t *pub_list;
/* 设置无效,标记是否初始化 */
memset(g_sub_list_index, MODULE_MAX, sizeof(g_sub_list_index));
memset(g_pub_list, 0, sizeof(g_pub_list));
for (int i = 0; i < (sizeof(g_sub_list) / sizeof(g_sub_list[0])); i++) {
for (unsigned int i = 0; i < (sizeof(g_sub_list) / sizeof(g_sub_list[0])); i++) {
#ifdef CHECK_SUBSCIBE_INFO
/* 检查各模块ID是否配置正确 */
if ((g_sub_list[i].module_id >= MODULE_MAX) || (g_sub_list[i].module_id == INVALID_ID)) {
msg_printf("module_id:%d is invalid, please check the macro:SUBSCIBE_INFO row:%d\n"
@@ -107,8 +110,8 @@ int has_msg_init()
}
/* 已经被初始化了,配置错误 */
if (g_sub_list_index[g_sub_list[i].module_id] != MODULE_MAX) {
msg_printf("[msg]warning: msg two same module id:%d\n", g_sub_list[i].module_id);
continue;
msg_printf("[msg warning]: msg two same module id:%d\n", g_sub_list[i].module_id);
MSG_ASSERT; // 配置都能写错,必须进断言
}
/* 检查订阅表ID是否配置正确 */
@@ -131,24 +134,38 @@ int has_msg_init()
MSG_ASSERT; // 配置都能写错,必须进断言
return -1;
}
g_sub_list_index[g_sub_list[i].module_id] = i; // 索引表赋值
#endif
/* 通知发布者,需要发给此模块 */
for (int k = 0; k < g_sub_list[i].sub_module_cnt; k++) { // 寻找发布者
if (g_pub_list[g_sub_list[i].sub_module[k]].pub_num == 0) {
msg_mutex_init(&g_pub_list[g_sub_list[i].sub_module[k]].buffer_mutex);
pub_list = &g_pub_list[g_sub_list[i].sub_module[k]];
#ifdef MSG_OPT_MUTEX_SEM
if (pub_list->pub_num == 0) {
if (msg_mutex_init(&pub_list->buffer_mutex) != 0) {
msg_printf("[msg warning]:pub mutex init err! pub id:%d\n"
, g_sub_list[i].sub_module[k]);
/* 使用计数没有加锁释放msg的内存时有可能出错 */
continue;
}
}
#endif
/* 注册所找到发布者的发布表 */
g_pub_list[g_sub_list[i].sub_module[k]].
pub_module[g_pub_list[g_sub_list[i].sub_module[k]].pub_num]
= g_sub_list[i].module_id;
g_pub_list[g_sub_list[i].sub_module[k]].pub_num ++;
pub_list->pub_module[pub_list->pub_num] = g_sub_list[i].module_id;
pub_list->pub_num ++;
}
msg_mutex_init(&g_sub_list[i].msg_mutex); // 初始化该模块互斥量
INIT_LIST_HEAD(&g_sub_list[i].msg_list); // 初始化订阅链表
#ifdef MSG_OPT_MUTEX_SEM
msg_sem_init(&g_sub_list[i].sem); // 初始化同步量
if (msg_sem_init(&g_sub_list[i].sem) != 0) { // 初始化该模块同步量
msg_printf("[msg warning]:sub sem init err! sub id:%d\n", i);
continue;
}
if (msg_mutex_init(&g_sub_list[i].msg_mutex) != 0) { // 初始化该模块互斥量
msg_printf("[msg warning]:sub mutex init err! sub id:%d\n", i);
continue;
}
#endif
g_sub_list_index[g_sub_list[i].module_id] = i; // 索引表赋值,相当于enable
}
#ifdef MSG_OPT_DEBUG
// msg_printf("show index:\n");
@@ -184,23 +201,26 @@ int has_msg_init()
*/
int has_msg_init_module(has_module_ID_e module_id)
{
int i, j;
unsigned int i;
int j;
has_static_pub_list_t *pub_list;
/* 检查ID */
#ifdef CHECK_SUBSCIBE_INFO
if ((module_id >= MODULE_MAX) || (module_id == INVALID_ID)) {
msg_printf("%s:module_id:%d is invalid\n", __func__, module_id);
MSG_ASSERT; // 配置都能写错,必须进断言
return -1;
}
#endif
/* 初始化该模块订阅表 */
for (i = 0; i < (sizeof(g_sub_list) / sizeof(g_sub_list[0])); i++)
{
if (g_sub_list[i].module_id == (unsigned char)module_id) {
// g_sub_list_index[module_id] = MODULE_MAX;
// g_pub_list[module_id].pub_num = 0;
#ifdef CHECK_SUBSCIBE_INFO
/* 已经被初始化了,配置错误 */
if (g_sub_list_index[module_id] != MODULE_MAX) {
msg_printf("[msg]warning: msg two same module id:%d\n", module_id);
break;
msg_printf("[msg warning]: msg two same module id:%d\n", module_id);
MSG_ASSERT; // 配置都能写错,必须进断言
}
/* 检查订阅表ID是否配置正确 */
for (j = 0; j < (MODULE_MAX - 1); j++) {
@@ -223,24 +243,38 @@ int has_msg_init_module(has_module_ID_e module_id)
MSG_ASSERT; // 配置都能写错,必须进断言
return -1;
}
g_sub_list_index[module_id] = i; // 索引表赋值
#endif
/* 通知发布者,需要发给此模块 */
for (int k = 0; k < g_sub_list[i].sub_module_cnt; k++) { // 寻找发布者
if (g_pub_list[g_sub_list[i].sub_module[k]].pub_num == 0) {
msg_mutex_init(&g_pub_list[g_sub_list[i].sub_module[k]].buffer_mutex);
pub_list = &g_pub_list[g_sub_list[i].sub_module[k]];
#ifdef MSG_OPT_MUTEX_SEM
if (pub_list->pub_num == 0) {
if (msg_mutex_init(&pub_list->buffer_mutex) != 0) {
msg_printf("[msg warning]:pub mutex init err! pub id:%d\n"
, g_sub_list[i].sub_module[k]);
/* 使用计数没有加锁释放msg的内存时有可能出错 */
continue;
}
}
#endif
/* 注册所找到发布者的发布表 */
g_pub_list[g_sub_list[i].sub_module[k]].
pub_module[g_pub_list[g_sub_list[i].sub_module[k]].pub_num] = module_id;
g_pub_list[g_sub_list[i].sub_module[k]].pub_num ++;
pub_list->pub_module[pub_list->pub_num] = module_id;
pub_list->pub_num ++;
}
msg_mutex_init(&g_sub_list[i].msg_mutex); // 初始化该模块互斥量
INIT_LIST_HEAD(&g_sub_list[i].msg_list); // 初始化订阅链表
#ifdef MSG_OPT_MUTEX_SEM
msg_sem_init(&g_sub_list[i].sem); // 初始化同步量
if (msg_sem_init(&g_sub_list[i].sem) != 0) { // 初始化该模块同步量
msg_printf("[msg warning]:sub sem init err! sub id:%d\n", i);
break;
}
if (msg_mutex_init(&g_sub_list[i].msg_mutex) != 0) { // 初始化该模块互斥量
msg_printf("[msg warning]:sub mutex init err! sub id:%d\n", i);
break;
}
#endif
g_sub_list_index[module_id] = i; // 索引表赋值,相当于enable
break;
}
}
@@ -264,6 +298,7 @@ int has_msg_os_init()
{
has_msg_init_module(i);
}
return 0;
}
/* TODO:更合理的方式是每个消息一个互斥量但是可能会导致每个消息malloc和free的时候频繁init和deinit */
@@ -309,9 +344,9 @@ int has_msg_publish(has_module_ID_e module_id, void *buffer, unsigned int length
has_static_pub_list_t *pub_list;
has_static_sub_list_t *sub_list;
MSG_CHECK_MODULE_ID(module_id, -1);
MSG_CHECK_ID_AND_INDEX(module_id, -1);
// MSG_CHECK_MODULE_ID 如果使用这个宏检查,未初始化的模块也可以发布
pub_list = &g_pub_list[module_id];
// MSG_CHECK_ID_AND_INDEX TODO:如果使用这个,未初始化的模块也不能发布
if (pub_list->pub_num == 0) {
// msg_printf("no one subscribe you:%d\n", module_id);
return 0;
@@ -342,7 +377,7 @@ int has_msg_publish(has_module_ID_e module_id, void *buffer, unsigned int length
list_del(&node[i].list); // 添加失败,删除链表
msg_mutex_unlock(&sub_list->msg_mutex);
msg_check_and_free_message(&node[i]);
msg_printf("warning:Failed to add msg on module:%d !!!\n"
msg_printf("[msg warning]:Failed to add msg on module:%d !!!\n"
, sub_list->module_id);
continue;
}
@@ -660,7 +695,7 @@ int has_msg_delete_all_message(has_module_ID_e module_id)
list_add_tail(&node->list, &free_list); // 加入临时链表
}
}
INIT_LIST_HEAD(&sub_list->msg_list);
// INIT_LIST_HEAD(&sub_list->msg_list);
msg_mutex_unlock(&sub_list->msg_mutex);
/* 释放内存 */
list_for_each_entry_safe(node, temp, &free_list, list) {

View File

@@ -9,7 +9,41 @@
#include <stdint.h>
#include "has_task_msg_os_port.h"
// TODO: 信号量限制最大数量
#ifdef MSG_OPT_MUTEX_SEM
/**
* @brief 互斥量初始化
*
* @param mutex:互斥量
* @return 0:成功 -1失败
*/
int msg_mutex_init(msg_mutex_t *mutex)
{
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
if (pthread_mutex_init(mutex, NULL) != 0) {
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
*mutex = xSemaphoreCreateMutex();
if (*mutex == NULL) {
msg_printf("create mutex err!!\n\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
*mutex = rt_mutex_create("has_msg", RT_IPC_FLAG_FIFO);
if (*mutex == RT_NULL) {
msg_printf("create mutex err!!\n\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
/* to be done */
#endif
}
/**
* @brief 信号量初始化
*
@@ -21,16 +55,28 @@ int msg_sem_init(msg_sem_t *sem)
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
sem->poll_fd.fd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK);
if (sem->poll_fd.fd == -1) {
printf("create eventfd error!\n");
msg_printf("create eventfd error!\n");
return -1;
}
sem->poll_fd.events = POLLIN; // 监控可读事件
sem->poll_fd.revents = 0;
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
*sem = xSemaphoreCreateCounting(UINT_MAX, 0)
if (*sem == NULL) {
msg_printf("create counting sem error!\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#elif (MSG_OPT_OS == MSG_OPT_OS_NONE_OR_OSAL)
*sem = rt_sem_create("has_sem", 0, RT_IPC_FLAG_FIFO)
if (*sem == RT_NULL) {
msg_printf("create counting sem error!\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
/* to be done */
#endif
}
@@ -45,14 +91,24 @@ int msg_sem_notify(msg_sem_t *sem)
#if (MSG_OPT_OS == MSG_OPT_OS_LINUX)
uint64_t val = 1;
if (write(sem->poll_fd.fd, &val, sizeof(val)) != sizeof(val)) {
printf("notify thread err!\n");
msg_printf("notify thread err!\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
if (xSemaphoreGive(*sem) != pdTRUE) {
msg_printf("notify thread err!\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#elif (MSG_OPT_OS == MSG_OPT_OS_NONE_OR_OSAL)
if (rt_sem_release(*sem) != RT_EOK) {
msg_printf("notify thread err!\n");
return -1;
}
return 0;
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
/* to be done */
#endif
}
@@ -75,27 +131,57 @@ enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout)
perror("poll fail\n");
return WAIT_FAIL;
} else if (ret == 0) {
// printf("poll timeout\n");
// msg_printf("poll timeout\n");
return WAIT_TIMEOUT;
}
if (sem->poll_fd.revents & POLLIN) {
if (read(sem->poll_fd.fd, &val, sizeof(val)) == sizeof(val)) { // 清零
// printf("read %ld\n", val);
// msg_printf("read %ld\n", val);
return WAIT_MSG_COME;
}
else {
printf("read error\n");
msg_printf("read error\n");
}
}
// 检查错误事件
printf("something err happened,revents:%x\n", sem->poll_fd.revents);
msg_printf("something err happened,revents:%x\n", sem->poll_fd.revents);
return WAIT_FAIL;
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
const TickType_t xTicksToWait;
if (ms_timeout < 0) {
xTicksToWait = portMAX_DELAY;
} else {
xTicksToWait = pdMS_TO_TICKS(ms_timeout);
}
if (xSemaphoreTake(*sem, xTicksToWait) != pdTRUE) {
msg_printf("sem take fail\n");
return WAIT_FAIL;
}
return WAIT_MSG_COME;
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#elif (MSG_OPT_OS == MSG_OPT_OS_NONE_OR_OSAL)
rt_err_t ret;
rt_int32_t time;
if (ms_timeout < 0) {
time = RT_WAITING_FOREVER;
} else {
time = rt_tick_from_millisecond(ms_timeout);
}
ret = rt_sem_take(*sem, time);
if (ret == RT_EOK) {
return WAIT_MSG_COME;
} else if (ret == (-RT_ETIMEOUT)) {
return WAIT_TIMEOUT;
} else {
msg_printf("sem take fail\n");
return WAIT_FAIL;
}
#elif (MSG_OPT_OS == MSG_OPT_OS_USER_DEFINED)
/* to be done */
#endif
}

View File

@@ -36,7 +36,6 @@ enum MSG_WAIT_RET{
#include <sys/eventfd.h>
#include <unistd.h>
#define msg_mutex_t pthread_mutex_t
#define msg_mutex_init(m) pthread_mutex_init(m, NULL)
#define msg_mutex_lock(m) pthread_mutex_lock(m)
#define msg_mutex_unlock(m) pthread_mutex_unlock(m)
typedef struct {
@@ -44,12 +43,12 @@ typedef struct {
} sync_t;
#define msg_sem_t sync_t
int msg_mutex_init(msg_mutex_t *mutex);
int msg_sem_init(msg_sem_t *sem);
int msg_sem_notify(msg_sem_t *sem);
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#else
#define msg_mutex_t
#define msg_mutex_init(m)
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif
@@ -62,85 +61,74 @@ enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#elif (MSG_OPT_OS == MSG_OPT_OS_freeRTOS)
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include "FreeRTOS.h"
#include "semphr.h"
#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t SemaphoreHandle_t
static inline void msg_mutex_init(void *mutex) {
*mutex = xSemaphoreCreateMutex();
if (*mutex == NULL) {
printf("create mutex err!!\n\n");
}
}
static inline void msg_mutex_lock(void *mutex) {
if (xSemaphoreTake(*mutex, portMAX_DELAY) != pdTRUE) {
printf("lock mutex err!!\n\n");
}
}
static inline void msg_mutex_unlock(void *mutex) {
xSemaphoreGive(*mutex);
}
#define msg_sem_t int
int msg_sem_init(msg_sem_t *sem);
int msg_sem_notify(msg_sem_t *sem);
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#else
#define msg_mutex_t
#define msg_mutex_init(m)
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif
#define msg_malloc pvPortMalloc
#define msg_free vPortFree
#define msg_printf printf
/* ----------------------- for RT-thread ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#include <stdlib.h>
#include <stdio.h>
#include <rtthread.h>
#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t rt_mutex_t
static inline void msg_mutex_init(void *mutex) {
*mutex = rt_mutex_create("has_msg", RT_IPC_FLAG_FIFO);
if (*mutex == RT_NULL) {
printf("create mutex err!!\n\n");
#define msg_mutex_t SemaphoreHandle_t
static inline void msg_mutex_lock(msg_mutex_t *mutex) {
if (xSemaphoreTake(*mutex, portMAX_DELAY) != pdTRUE) {
msg_printf("lock mutex err!!\n\n");
}
}
static inline void msg_mutex_lock(void *mutex) {
if (rt_mutex_take(*mutex, RT_WAITING_FOREVER) != RT_EOK) {
printf("lock mutex err!!\n\n");
}
static inline void msg_mutex_unlock(msg_mutex_t *mutex) {
xSemaphoreGive(*mutex);
}
static inline void msg_mutex_unlock(void *mutex) {
rt_mutex_release(*mutex);
}
#define msg_sem_t int
#define msg_sem_t SemaphoreHandle_t
int msg_mutex_init(msg_mutex_t *mutex);
int msg_sem_init(msg_sem_t *sem);
int msg_sem_notify(msg_sem_t *sem);
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#else
#define msg_mutex_t
#define msg_mutex_init(m)
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif
/* ----------------------- for RT-thread ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_RT_THREAD)
#include <stdlib.h>
#include <stdio.h>
#include <rtthread.h>
#define msg_malloc rt_malloc
#define msg_free rt_free
#define msg_printf printf
#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t rt_mutex_t
static inline void msg_mutex_lock(msg_mutex_t *mutex) {
if (rt_mutex_take(*mutex, RT_WAITING_FOREVER) != RT_EOK) {
msg_printf("lock mutex err!!\n\n");
}
}
static inline void msg_mutex_unlock(msg_mutex_t *mutex) {
rt_mutex_release(*mutex);
}
#define msg_sem_t rt_sem_t
int msg_mutex_init(msg_mutex_t *mutex);
int msg_sem_init(msg_sem_t *sem);
int msg_sem_notify(msg_sem_t *sem);
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#else
#define msg_mutex_t
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif
/* ----------------------- for none os ----------------------- */
#elif (MSG_OPT_OS == MSG_OPT_OS_NONE_OR_OSAL)
#include <stdlib.h>
@@ -148,7 +136,6 @@ enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#undef MSG_OPT_MUTEX_SEM
#define msg_mutex_t
#define msg_mutex_init(m)
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
@@ -163,27 +150,24 @@ enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#ifdef MSG_OPT_MUTEX_SEM
#define msg_mutex_t int/* to be done */
static inline void msg_mutex_init(void *mutex) {
/* to be done */
}
static inline void msg_mutex_lock(void *mutex) {
static inline void msg_mutex_lock(msg_mutex_t *mutex) {
/* to be done */
}
static inline void msg_mutex_unlock(void *mutex) {
static inline void msg_mutex_unlock(msg_mutex_t *mutex) {
/* to be done */
}
#define msg_sem_t int // to be done
int msg_mutex_init(msg_mutex_t *mutex);
int msg_sem_init(msg_sem_t *sem);
int msg_sem_notify(msg_sem_t *sem);
enum MSG_WAIT_RET msg_sem_wait(msg_sem_t *sem, int ms_timeout);
#else
#define msg_mutex_t
#define msg_mutex_init(m)
#define msg_mutex_lock(m)
#define msg_mutex_unlock(m)
#endif