From 89cf5886aa19b96b02ebeeeb8f7b07a25318cd7d Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 3 Jan 2021 06:19:14 +0800 Subject: [PATCH] add rt_mb_urgent() and rt_mb_urgent_wait() --- src/ipc.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/src/ipc.c b/src/ipc.c index 4261f617b0..a3069b1f37 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -37,6 +37,7 @@ * 2020-07-29 Meco Man fix thread->event_set/event_info when received an * event without pending * 2020-10-11 Meco Man add value overflow-check code + * 2021-01-03 Meco Man add rt_mb_urgent() and rt_mb_urgent_wait() */ #include @@ -1654,6 +1655,169 @@ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value) } RTM_EXPORT(rt_mb_send); +/** + * This function will send an urgent mail to mailbox object. If the mailbox is full, + * current thread will be suspended until timeout. + * + * @param mb the mailbox object + * @param value the mail + * @param timeout the waiting time + * + * @return the error code + */ +rt_err_t rt_mb_urgent_wait(rt_mailbox_t mb, + rt_ubase_t value, + rt_int32_t timeout) +{ + struct rt_thread *thread; + register rt_ubase_t temp; + rt_uint32_t tick_delta; + + /* parameter check */ + RT_ASSERT(mb != RT_NULL); + RT_ASSERT(rt_object_get_type(&mb->parent.parent) == RT_Object_Class_MailBox); + + /* initialize delta tick */ + tick_delta = 0; + /* get current thread */ + thread = rt_thread_self(); + + RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mb->parent.parent))); + + /* disable interrupt */ + temp = rt_hw_interrupt_disable(); + + /* for non-blocking call */ + if (mb->entry == mb->size && timeout == 0) + { + rt_hw_interrupt_enable(temp); + + return -RT_EFULL; + } + + /* mailbox is full */ + while (mb->entry == mb->size) + { + /* reset error number in thread */ + thread->error = RT_EOK; + + /* no waiting, return timeout */ + if (timeout == 0) + { + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + + return -RT_EFULL; + } + + RT_DEBUG_IN_THREAD_CONTEXT; + /* suspend current thread */ + rt_ipc_list_suspend(&(mb->suspend_sender_thread), + thread, + mb->parent.parent.flag); + + /* has waiting time, start thread timer */ + if (timeout > 0) + { + /* get the start tick of timer */ + tick_delta = rt_tick_get(); + + RT_DEBUG_LOG(RT_DEBUG_IPC, ("mb_send_wait: start timer of thread:%s\n", + thread->name)); + + /* reset the timeout of thread timer and start it */ + rt_timer_control(&(thread->thread_timer), + RT_TIMER_CTRL_SET_TIME, + &timeout); + rt_timer_start(&(thread->thread_timer)); + } + + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + + /* re-schedule */ + rt_schedule(); + + /* resume from suspend state */ + if (thread->error != RT_EOK) + { + /* return error */ + return thread->error; + } + + /* disable interrupt */ + temp = rt_hw_interrupt_disable(); + + /* if it's not waiting forever and then re-calculate timeout tick */ + if (timeout > 0) + { + tick_delta = rt_tick_get() - tick_delta; + timeout -= tick_delta; + if (timeout < 0) + timeout = 0; + } + } + + /* rewind to the previous position */ + if(mb->out_offset > 0) + { + mb->out_offset --; + } + else + { + mb->out_offset = mb->size - 1; + } + + /* set ptr */ + mb->msg_pool[mb->out_offset] = value; + + if(mb->entry < RT_MB_ENTRY_MAX) + { + /* increase message entry */ + mb->entry ++; + } + else + { + rt_hw_interrupt_enable(temp); /* enable interrupt */ + return -RT_EFULL; /* value overflowed */ + } + + /* resume suspended thread */ + if (!rt_list_isempty(&mb->parent.suspend_thread)) + { + rt_ipc_list_resume(&(mb->parent.suspend_thread)); + + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + + rt_schedule(); + + return RT_EOK; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(temp); + + return RT_EOK; +} +RTM_EXPORT(rt_mb_urgent_wait); + +/** + * This function will send an urgent mail to mailbox object, if there are threads + * suspended on mailbox object, it will be waked up. This function will return + * immediately, if you want blocking send, use rt_mb_urgent_wait instead. + * + * @param mb the mailbox object + * @param value the mail + * + * @return the error code + */ +rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value) +{ + return rt_mb_urgent_wait(mb, value, 0); +} +RTM_EXPORT(rt_mb_urgent); + /** * This function will receive a mail from mailbox object, if there is no mail * in mailbox object, the thread shall wait for a specified time.