os_mb.c
2026/7/20大约 7 分钟附录源码附录
os_mb.c
路径: kernel\source\os_mb.c
功能: 邮箱(Mailbox)功能实现。邮箱是 OneOS 中高效的 IPC 机制,用于任务间传递固定大小的指针/数据。与消息队列不同,邮箱每次只传递一个 os_ubase_t 大小的邮件(通常用于传递地址指针),开销更小,适合高频小数据传递场景。
核心数据结构:
os_mailbox_t: 邮箱控制块,包含mail_pool(邮箱池)、read_index/write_index(读写索引)、capacity(容量)、used_mails(已用邮件数)send_task_list_head/recv_task_list_head: 发送/接收阻塞任务链表
关键 API:
| 函数 | 说明 |
|---|---|
os_mailbox_create_dynamic | 动态创建邮箱(控制块+邮箱池均从堆分配) |
os_mailbox_create_static | 静态初始化邮箱(用户提供控制块和邮箱池) |
os_mailbox_destroy | 销毁邮箱,自动释放阻塞任务 |
os_mailbox_send | 发送邮件(支持阻塞等待 timeout) |
os_mailbox_recv | 接收邮件(支持阻塞等待 timeout) |
os_mailbox_set_wake_type | 设置唤醒类型(PRIO 优先级 / FIFO 先进先出) |
os_mailbox_reset | 重置邮箱(清空所有邮件,释放阻塞任务) |
os_mailbox_is_empty | 查询邮箱是否为空 |
os_mailbox_is_full | 查询邮箱是否已满 |
os_mailbox_get_capacity | 获取邮箱容量 |
os_mailbox_get_used_mails | 获取已用邮件数 |
os_mailbox_get_unused_mails | 获取剩余可用邮件数 |
关键设计点:
- 零拷贝传递: 邮件通过
task->swap_data字段直接在发送/接收任务间传递,无需经过邮箱池中转 - 邮箱池按需使用: 仅当没有任务阻塞在对方等待队列时,才将邮件存入邮箱池
- 读写索引循环:
read_index/write_index在达到capacity时回绕到 0,实现循环缓冲区 - SMP 安全: 支持
os_spin_lock保护多核并发访问
Shell 命令: show_mb — 查看所有邮箱信息,包括邮件数、阻塞任务列表
/**
***********************************************************************************************************************
* Copyright (c) 2021, China Mobile Communications Group Co.,Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* @file os_mb.c
*
* @brief This file implements the mailbox functions.
*
* @revision
* Date Author Notes
* 2021-01-08 OneOS Team First Version
***********************************************************************************************************************
*/
#include <oneos_config.h>
#include <os_stddef.h>
#include <os_errno.h>
#include <os_clock.h>
#include <arch_interrupt.h>
#include <os_mb.h>
#include <string.h>
#include <os_spinlock.h>
#include "os_kernel_internal.h"
#ifdef OS_USING_MAILBOX
#define MB_TAG "MAILBOX"
static os_list_node_t gs_os_mb_resource_list_head = OS_LIST_INIT(gs_os_mb_resource_list_head);
static OS_DEFINE_SPINLOCK(gs_os_mb_resource_list_lock);
static void _k_mb_modify_read_index(os_mailbox_t *mb)
{
mb->read_index++;
if (mb->read_index >= mb->capacity)
{
mb->read_index = 0U;
}
mb->used_mails--;
return;
}
static void _k_mb_modify_write_index(os_mailbox_t *mb)
{
mb->write_index++;
if (mb->write_index >= mb->capacity)
{
mb->write_index = 0U;
}
mb->used_mails++;
return;
}
static os_err_t _k_mailbox_init(os_mailbox_t *mb,
const char *name,
void *mail_pool,
os_size_t mail_pool_size,
uint8_t object_alloc_type)
{
void *pool_align_begin;
void *pool_end;
os_err_t ret;
ret = OS_SUCCESS;
/* The address of mail pool need to be aligned. */
pool_align_begin = (void *)OS_ALIGN_UP((os_ubase_t)mail_pool, sizeof(os_ubase_t));
pool_end = (void *)((uint8_t *)mail_pool + mail_pool_size);
mb->capacity = (uint16_t)(((os_ubase_t)pool_end - (os_ubase_t)pool_align_begin) / sizeof(os_ubase_t));
if (mb->capacity > 0U)
{
mb->mail_pool = mail_pool;
mb->mail_pool_align = pool_align_begin;
mb->used_mails = 0U;
mb->read_index = 0U;
mb->write_index = 0U;
mb->object_alloc_type = object_alloc_type;
mb->wake_type = OS_MB_WAKE_TYPE_PRIO;
if (OS_NULL != name)
{
(void)strncpy(&mb->name[0], name, OS_NAME_MAX);
mb->name[OS_NAME_MAX] = '\0';
}
else
{
mb->name[0] = '\0';
}
os_list_init(&mb->send_task_list_head);
os_list_init(&mb->recv_task_list_head);
#ifdef OS_USING_SMP
os_spin_lock_init(&mb->lock);
#endif
}
else
{
OS_KERN_LOG(KERN_ERROR, MB_TAG, "The count of calculated mail entry is less than 1.");
ret = OS_NOMEM;
}
return ret;
}
#ifdef OS_USING_HEAP
os_mailbox_id os_mailbox_create_dynamic(const char *name, os_size_t max_mails)
{
os_mailbox_t *mb;
void *mail_pool;
os_size_t mail_pool_size;
os_err_t ret;
OS_ASSERT(max_mails > 0U);
OS_ASSERT(OS_FALSE == os_is_irq_active());
mail_pool_size = max_mails * sizeof(os_ubase_t);
mb = (os_mailbox_t *)OS_KERNEL_MALLOC(sizeof(os_mailbox_t));
mail_pool = OS_KERNEL_MALLOC_ALIGN(sizeof(os_ubase_t), mail_pool_size);
if ((OS_NULL == mb) || (OS_NULL == mail_pool))
{
OS_KERN_LOG(KERN_ERROR, MB_TAG, "Malloc failed, mb(%p), mail_pool(%p)", mb, mail_pool);
if (OS_NULL != mb)
{
OS_KERNEL_FREE(mb);
mb = OS_NULL;
}
if (OS_NULL != mail_pool)
{
OS_KERNEL_FREE(mail_pool);
mail_pool = OS_NULL;
}
}
else
{
ret = _k_mailbox_init(mb, name, mail_pool, mail_pool_size, OS_KOBJ_ALLOC_TYPE_DYNAMIC);
if (OS_SUCCESS == ret)
{
os_spin_lock(&gs_os_mb_resource_list_lock);
os_list_add_tail(&gs_os_mb_resource_list_head, &mb->resource_node);
os_spin_unlock(&gs_os_mb_resource_list_lock);
mb->object_inited = OS_KOBJ_INITED;
}
else
{
OS_KERNEL_FREE(mb);
OS_KERNEL_FREE(mail_pool);
mb = OS_NULL;
mail_pool = OS_NULL;
}
}
return OS_TYPE_CONVERT(os_mailbox_id, mb);
}
#endif /* OS_USING_HEAP */
os_mailbox_id
os_mailbox_create_static(os_mailbox_dummy_t *mailbox_cb, const char *name, void *mail_pool, os_size_t mail_pool_size)
{
os_mailbox_t *iter_mb;
os_list_node_t *pos;
os_err_t ret;
os_mailbox_t *mb;
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_cb);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_NULL != mail_pool);
OS_ASSERT(mail_pool_size > 0);
OS_ASSERT(OS_FALSE == os_is_irq_active());
os_spin_lock(&gs_os_mb_resource_list_lock);
os_list_for_each(pos, &gs_os_mb_resource_list_head)
{
iter_mb = os_list_entry(pos, os_mailbox_t, resource_node);
if (iter_mb == mb)
{
OS_KERN_LOG(KERN_ERROR, MB_TAG, "The mb(addr: %p, name: %s) has been exist", iter_mb, iter_mb->name);
mb = OS_NULL;
break;
}
}
if (OS_NULL != mb)
{
os_list_add_tail(&gs_os_mb_resource_list_head, &mb->resource_node);
os_spin_unlock(&gs_os_mb_resource_list_lock);
ret = _k_mailbox_init(mb, name, mail_pool, mail_pool_size, OS_ALLOC_TYPE_STATIC);
if (OS_SUCCESS == ret)
{
mb->object_inited = OS_KOBJ_INITED;
}
else
{
os_spin_lock(&gs_os_mb_resource_list_lock);
os_list_del(&mb->resource_node);
os_spin_unlock(&gs_os_mb_resource_list_lock);
mb = OS_NULL;
}
}
else
{
os_spin_unlock(&gs_os_mb_resource_list_lock);
}
return OS_TYPE_CONVERT(os_mailbox_id, mb);
}
os_err_t os_mailbox_destroy(os_mailbox_id mailbox_id)
{
os_bool_t need_sched;
os_mailbox_t *mb;
OS_KERNEL_INIT();
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT(OS_FALSE == os_is_irq_active());
#ifndef OS_USING_HEAP
OS_ASSERT(OS_ALLOC_TYPE_STATIC == mb->object_alloc_type);
#endif
need_sched = OS_FALSE;
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
#else
OS_KERNEL_ENTER();
#endif
mb->object_inited = OS_KOBJ_DEINITED;
if (OS_TRUE == k_cancel_all_blocked_task(&mb->send_task_list_head))
{
need_sched = OS_TRUE;
}
if (OS_TRUE == k_cancel_all_blocked_task(&mb->recv_task_list_head))
{
need_sched = OS_TRUE;
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
if (OS_TRUE == need_sched)
{
OS_KERNEL_ENTER();
OS_KERNEL_EXIT_SCHED();
}
#else
if (OS_TRUE == need_sched)
{
OS_KERNEL_EXIT_SCHED();
}
else
{
OS_KERNEL_EXIT();
}
#endif
os_spin_lock(&gs_os_mb_resource_list_lock);
os_list_del(&mb->resource_node);
os_spin_unlock(&gs_os_mb_resource_list_lock);
#ifdef OS_USING_HEAP
if (OS_KOBJ_ALLOC_TYPE_DYNAMIC == mb->object_alloc_type)
{
OS_KERNEL_FREE(mb->mail_pool);
mb->mail_pool = OS_NULL;
OS_KERNEL_FREE(mb);
mb = OS_NULL;
}
#endif
return OS_SUCCESS;
}
os_err_t os_mailbox_send(os_mailbox_id mailbox_id, os_ubase_t value, os_tick_t timeout)
{
os_task_t *current_task;
os_task_t *block_task;
os_bool_t need_sched;
os_err_t ret;
os_mailbox_t *mb;
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_KERNEL_INIT();
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT((OS_NO_WAIT == timeout) || (OS_NULL == k_task_self()) || (OS_FALSE == os_is_irq_active()));
OS_ASSERT((OS_NO_WAIT == timeout) || (OS_NULL == k_task_self()) || (OS_FALSE == os_is_irq_disabled()));
OS_ASSERT((OS_NO_WAIT == timeout) || (OS_NULL == k_task_self()) || (OS_FALSE == os_is_schedule_locked()));
OS_ASSERT((timeout < (OS_TICK_MAX / 2)) || (OS_WAIT_FOREVER == timeout));
ret = OS_SUCCESS;
need_sched = OS_FALSE;
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
k_kernel_spin_lock();
#else
OS_KERNEL_ENTER();
#endif
if (!os_list_empty(&mb->recv_task_list_head))
{
block_task = os_list_first_entry(&mb->recv_task_list_head, os_task_t, task_node);
need_sched = k_unblock_task(block_task);
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
k_kernel_spin_unlock();
#endif
block_task->swap_data = value;
}
else
{
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
k_kernel_spin_unlock();
#endif
if (mb->used_mails == mb->capacity)
{
if (OS_NO_WAIT == timeout)
{
ret = OS_FULL;
}
else
{
current_task = _k_task_self();
OS_ASSERT((OS_NULL != current_task));
current_task->swap_data = value;
if (OS_MB_WAKE_TYPE_PRIO == mb->wake_type)
{
ret = k_block_task(&mb->lock, irq_save, &mb->send_task_list_head, timeout, OS_TRUE);
}
else
{
ret = k_block_task(&mb->lock, irq_save, &mb->send_task_list_head, timeout, OS_FALSE);
}
return ret;
}
}
else
{
*((os_ubase_t *)mb->mail_pool_align + mb->write_index) = value;
_k_mb_modify_write_index(mb);
}
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
if (OS_TRUE == need_sched)
{
OS_KERNEL_ENTER();
OS_KERNEL_EXIT_SCHED();
}
#else
if (OS_TRUE == need_sched)
{
OS_KERNEL_EXIT_SCHED();
}
else
{
OS_KERNEL_EXIT();
}
#endif
return ret;
}
os_err_t os_mailbox_recv(os_mailbox_id mailbox_id, os_ubase_t *value, os_tick_t timeout)
{
os_task_t *current_task;
os_task_t *block_task;
os_bool_t need_sched;
os_bool_t modify_read_index;
os_err_t ret;
os_mailbox_t *mb;
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_KERNEL_INIT();
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_NULL != value);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT((OS_NO_WAIT == timeout) || (OS_NULL == k_task_self()) || (OS_FALSE == os_is_irq_active()));
OS_ASSERT((OS_NO_WAIT == timeout) || (OS_NULL == k_task_self()) || (OS_FALSE == os_is_irq_disabled()));
OS_ASSERT((OS_NO_WAIT == timeout) || (OS_NULL == k_task_self()) || (OS_FALSE == os_is_schedule_locked()));
OS_ASSERT((timeout < (OS_TICK_MAX / 2)) || (OS_WAIT_FOREVER == timeout));
ret = OS_SUCCESS;
need_sched = OS_FALSE;
modify_read_index = OS_TRUE;
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
#else
OS_KERNEL_ENTER();
#endif
if (0U != mb->used_mails)
{
*value = *((os_ubase_t *)mb->mail_pool_align + mb->read_index);
}
else
{
if (OS_NO_WAIT == timeout)
{
ret = OS_EMPTY;
}
else
{
current_task = _k_task_self();
OS_ASSERT((OS_NULL != current_task));
if (OS_MB_WAKE_TYPE_PRIO == mb->wake_type)
{
ret = k_block_task(&mb->lock, irq_save, &mb->recv_task_list_head, timeout, OS_TRUE);
}
else
{
ret = k_block_task(&mb->lock, irq_save, &mb->recv_task_list_head, timeout, OS_FALSE);
}
if (OS_SUCCESS == ret)
{
*value = current_task->swap_data;
modify_read_index = OS_FALSE;
}
return ret;
}
}
if ((OS_SUCCESS == ret) && (OS_TRUE == modify_read_index))
{
_k_mb_modify_read_index(mb);
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
k_kernel_spin_lock();
#endif
if (!os_list_empty(&mb->send_task_list_head))
{
block_task = os_list_first_entry(&mb->send_task_list_head, os_task_t, task_node);
need_sched = k_unblock_task(block_task);
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
k_kernel_spin_unlock();
#endif
*((os_ubase_t *)mb->mail_pool_align + mb->write_index) = block_task->swap_data;
_k_mb_modify_write_index(mb);
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
else
{
k_kernel_spin_unlock();
}
#endif
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
if (OS_TRUE == need_sched)
{
OS_KERNEL_ENTER();
OS_KERNEL_EXIT_SCHED();
}
#else
if (OS_TRUE == need_sched)
{
OS_KERNEL_EXIT_SCHED();
}
else
{
OS_KERNEL_EXIT();
}
#endif
return ret;
}
os_err_t os_mailbox_set_wake_type(os_mailbox_id mailbox_id, uint8_t wake_type)
{
os_err_t ret;
os_mailbox_t *mb;
OS_KERNEL_INIT();
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT((OS_MB_WAKE_TYPE_PRIO == wake_type) || (OS_MB_WAKE_TYPE_FIFO == wake_type));
ret = OS_BUSY;
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
k_kernel_spin_lock();
#else
OS_KERNEL_ENTER();
#endif
if (os_list_empty(&mb->recv_task_list_head) && os_list_empty(&mb->send_task_list_head))
{
mb->wake_type = wake_type;
ret = OS_SUCCESS;
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
k_kernel_spin_unlock();
os_spin_unlock_irq(&mb->lock, irq_save);
#else
OS_KERNEL_EXIT();
#endif
return ret;
}
os_err_t os_mailbox_reset(os_mailbox_id mailbox_id)
{
os_bool_t need_sched;
os_mailbox_t *mb;
OS_KERNEL_INIT();
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
need_sched = OS_FALSE;
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
#else
OS_KERNEL_ENTER();
#endif
mb->read_index = 0U;
mb->write_index = 0U;
mb->used_mails = 0U;
if (OS_TRUE == k_cancel_all_blocked_task(&mb->send_task_list_head))
{
need_sched = OS_TRUE;
}
if (OS_TRUE == k_cancel_all_blocked_task(&mb->recv_task_list_head))
{
need_sched = OS_TRUE;
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
if (OS_TRUE == need_sched)
{
OS_KERNEL_ENTER();
OS_KERNEL_EXIT_SCHED();
}
#else
if (OS_TRUE == need_sched)
{
OS_KERNEL_EXIT_SCHED();
}
else
{
OS_KERNEL_EXIT();
}
#endif
return OS_SUCCESS;
}
os_err_t os_mailbox_is_empty(os_mailbox_id mailbox_id, os_bool_t *empty_flag)
{
os_mailbox_t *mb;
OS_KERNEL_INIT();
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT(OS_NULL != empty_flag);
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
#else
OS_KERNEL_ENTER();
#endif
if (0U == mb->used_mails)
{
*empty_flag = OS_TRUE;
}
else
{
*empty_flag = OS_FALSE;
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
#else
OS_KERNEL_EXIT();
#endif
return OS_SUCCESS;
}
os_err_t os_mailbox_is_full(os_mailbox_id mailbox_id, os_bool_t *full_flag)
{
os_mailbox_t *mb;
OS_KERNEL_INIT();
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT(OS_NULL != full_flag);
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
#else
OS_KERNEL_ENTER();
#endif
if (mb->used_mails == mb->capacity)
{
*full_flag = OS_TRUE;
}
else
{
*full_flag = OS_FALSE;
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
#else
OS_KERNEL_EXIT();
#endif
return OS_SUCCESS;
}
os_err_t os_mailbox_get_capacity(os_mailbox_id mailbox_id, uint16_t *capacity)
{
os_mailbox_t *mb;
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT(OS_NULL != capacity);
*capacity = mb->capacity;
return OS_SUCCESS;
}
os_err_t os_mailbox_get_used_mails(os_mailbox_id mailbox_id, uint16_t *used_mails)
{
os_mailbox_t *mb;
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT(OS_NULL != used_mails);
*used_mails = mb->used_mails;
return OS_SUCCESS;
}
os_err_t os_mailbox_get_unused_mails(os_mailbox_id mailbox_id, uint16_t *unused_mails)
{
uint16_t unused_entry_cnt;
os_mailbox_t *mb;
OS_KERNEL_INIT();
mb = OS_TYPE_CONVERT(os_mailbox_t *, mailbox_id);
OS_ASSERT(OS_NULL != mb);
OS_ASSERT(OS_KOBJ_INITED == mb->object_inited);
OS_ASSERT(OS_NULL != unused_mails);
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
#else
OS_KERNEL_ENTER();
#endif
unused_entry_cnt = mb->capacity - mb->used_mails;
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_unlock_irq(&mb->lock, irq_save);
#else
OS_KERNEL_EXIT();
#endif
*unused_mails = unused_entry_cnt;
return OS_SUCCESS;
}
#if defined(OS_USING_SHELL)
#include <shell.h>
#define SH_SHOW_TASK_CNT_MAX 10
typedef struct
{
os_mailbox_t *mb;
uint16_t used_mails;
uint16_t send_block_task_count;
uint16_t recv_block_task_count;
block_task_info_t send_block_task[SH_SHOW_TASK_CNT_MAX];
block_task_info_t recv_block_task[SH_SHOW_TASK_CNT_MAX];
} sh_mb_info_t;
static os_err_t os_mb_show(os_mailbox_t *mb)
{
sh_mb_info_t mb_info;
os_task_t *iter_task;
uint16_t task_send_index;
uint16_t task_recv_index;
OS_KERNEL_INIT();
if ((OS_NULL == mb) || (OS_KOBJ_INITED != mb->object_inited))
{
os_kprintf("The input parameter is an illegal mailbox object.\r\n");
return OS_FAILURE;
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
os_spin_lock_irq(&mb->lock, &irq_save);
k_kernel_spin_lock();
#else
OS_KERNEL_ENTER();
#endif
mb_info.mb = mb;
mb_info.used_mails = mb->used_mails;
mb_info.send_block_task_count = os_list_len(&mb->send_task_list_head);
mb_info.recv_block_task_count = os_list_len(&mb->recv_task_list_head);
task_send_index = 0;
os_list_for_each_entry(iter_task, &mb->send_task_list_head, os_task_t, task_node)
{
mb_info.send_block_task[task_send_index].current_priority = iter_task->current_priority;
mb_info.send_block_task[task_send_index].name = iter_task->name;
task_send_index++;
if (task_send_index >= SH_SHOW_TASK_CNT_MAX)
{
break;
}
}
task_recv_index = 0;
os_list_for_each_entry(iter_task, &mb->recv_task_list_head, os_task_t, task_node)
{
mb_info.recv_block_task[task_recv_index].current_priority = iter_task->current_priority;
mb_info.recv_block_task[task_recv_index].name = iter_task->name;
task_recv_index++;
if (task_recv_index >= SH_SHOW_TASK_CNT_MAX)
{
break;
}
}
#if defined(OS_USING_SMP) && !defined(OS_IPC_MONOLOCK_MODE)
k_kernel_spin_unlock();
os_spin_unlock_irq(&mb->lock, irq_save);
#else
OS_KERNEL_EXIT();
#endif
os_kprintf("%-*s %-12u %-11u ",
OS_NAME_MAX,
(mb_info.mb->name[0] != '\0') ? mb_info.mb->name : "-",
mb_info.used_mails,
mb_info.mb->capacity);
if (mb_info.send_block_task_count > 0)
{
os_kprintf("%-6u(send):", mb_info.send_block_task_count);
k_show_blocked_task(mb_info.send_block_task, task_send_index);
if (mb_info.send_block_task_count > task_send_index)
{
os_kprintf("/...\r\n");
}
else
{
os_kprintf("\r\n");
}
}
else if (mb_info.recv_block_task_count > 0)
{
os_kprintf("%-6u(recv):", mb_info.recv_block_task_count);
k_show_blocked_task(mb_info.recv_block_task, task_recv_index);
if (mb_info.recv_block_task_count > task_recv_index)
{
os_kprintf("/...\r\n");
}
else
{
os_kprintf("\r\n");
}
}
else
{
os_kprintf("%-6u\r\n", 0);
}
return OS_SUCCESS;
}
static os_err_t sh_show_mb_info(int32_t argc, char *const *argv)
{
os_mailbox_t *iter_mb;
os_mailbox_t *mb_tmp;
uint16_t len;
OS_UNREFERENCE(argc);
OS_UNREFERENCE(argv);
os_kprintf("%-*s %-10s %-13s %-10s\r\n", OS_NAME_MAX, "Mailbox", "Mail Count", "Mailbox depth", "Block Task");
len = OS_NAME_MAX;
while ((len--) != 0)
{
os_kprintf("-");
}
os_kprintf(" ---------- ------------- ----------\r\n");
if (argc >= 2)
{
if ((argv[1] != OS_NULL))
{
mb_tmp = (os_mailbox_t *)strtoul(argv[1], OS_NULL, 0);
os_spin_lock(&gs_os_mb_resource_list_lock);
os_list_for_each_entry(iter_mb, &gs_os_mb_resource_list_head, os_mailbox_t, resource_node)
{
if (mb_tmp == iter_mb)
{
os_mb_show(mb_tmp);
os_spin_unlock(&gs_os_mb_resource_list_lock);
return OS_SUCCESS;
}
}
os_spin_unlock(&gs_os_mb_resource_list_lock);
}
os_kprintf("Invalid Mb Object.\r\n");
return OS_FAILURE;
}
os_spin_lock(&gs_os_mb_resource_list_lock);
os_list_for_each_entry(iter_mb, &gs_os_mb_resource_list_head, os_mailbox_t, resource_node)
{
os_mb_show(iter_mb);
}
os_spin_unlock(&gs_os_mb_resource_list_lock);
return OS_SUCCESS;
}
SH_CMD_EXPORT(show_mb, sh_show_mb_info, "Show mailbox information");
#endif /* defined(OS_USING_SHELL)*/
#endif /* end of OS_USING_MAILBOX */