* @brief This function will send an mail to the mailbox object. If there is a thread suspended on the mailbox, * the thread will be resumed. * * @note When using this function to send a mail, if the mailbox if fully used, the current thread will * wait for a timeout. If the set timeout time is reached and there is still no space available, * the sending th
| 2564 | * @warning This function can be called in interrupt context and thread context. |
| 2565 | */ |
| 2566 | static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb, |
| 2567 | rt_ubase_t value, |
| 2568 | rt_int32_t timeout, |
| 2569 | int suspend_flag) |
| 2570 | { |
| 2571 | struct rt_thread *thread; |
| 2572 | rt_base_t level; |
| 2573 | rt_uint32_t tick_delta; |
| 2574 | rt_err_t ret; |
| 2575 | |
| 2576 | /* parameter check */ |
| 2577 | RT_ASSERT(mb != RT_NULL); |
| 2578 | RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox); |
| 2579 | |
| 2580 | /* current context checking */ |
| 2581 | RT_DEBUG_SCHEDULER_AVAILABLE(timeout != 0); |
| 2582 | |
| 2583 | /* initialize delta tick */ |
| 2584 | tick_delta = 0; |
| 2585 | /* get current thread */ |
| 2586 | thread = rt_thread_self(); |
| 2587 | |
| 2588 | RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent))); |
| 2589 | |
| 2590 | /* disable interrupt */ |
| 2591 | level = rt_spin_lock_irqsave(&(mb->spinlock)); |
| 2592 | |
| 2593 | /* for non-blocking call */ |
| 2594 | if (mb->entry == mb->size && timeout == 0) |
| 2595 | { |
| 2596 | rt_spin_unlock_irqrestore(&(mb->spinlock), level); |
| 2597 | return -RT_EFULL; |
| 2598 | } |
| 2599 | |
| 2600 | /* mailbox is full */ |
| 2601 | while (mb->entry == mb->size) |
| 2602 | { |
| 2603 | /* reset error number in thread */ |
| 2604 | thread->error = -RT_EINTR; |
| 2605 | |
| 2606 | /* no waiting, return timeout */ |
| 2607 | if (timeout == 0) |
| 2608 | { |
| 2609 | rt_spin_unlock_irqrestore(&(mb->spinlock), level); |
| 2610 | |
| 2611 | return -RT_EFULL; |
| 2612 | } |
| 2613 | |
| 2614 | /* suspend current thread */ |
| 2615 | ret = rt_thread_suspend_to_list(thread, &(mb->suspend_sender_thread), |
| 2616 | mb->parent.parent.flag, suspend_flag); |
| 2617 | |
| 2618 | if (ret != RT_EOK) |
| 2619 | { |
| 2620 | rt_spin_unlock_irqrestore(&(mb->spinlock), level); |
| 2621 | return ret; |
| 2622 | } |
| 2623 |
no test coverage detected