4646 * 2022-10-16 Bernard add prioceiling feature in mutex
4747 * 2023-04-16 Xin-zheqi redesigen queue recv and send function return real message size
4848 * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
49+ * 2025-11-23 Rbb666 fix thread error code to avoid spurious error display in ps
4950 */
5051
5152#include <rtthread.h>
@@ -87,6 +88,31 @@ rt_inline rt_err_t _ipc_object_init(struct rt_ipc_object *ipc)
8788 return RT_EOK ;
8889}
8990
91+ /**
92+ * @brief This function normalizes the thread error code after IPC wait operation.
93+ *
94+ * @note This function translates the internal RT_EWAITPEND sentinel value back to RT_EINTR
95+ * for the caller. If the error code is still RT_EWAITPEND after scheduling, it means
96+ * the thread was interrupted by an interrupted system call rather than successfully
97+ * acquiring the resource or timing out.
98+ *
99+ * @param thread is a pointer to the thread object whose error code needs to be checked.
100+ *
101+ * @return Return the thread's error code. When the return value is RT_EOK, the IPC operation succeeded.
102+ * When the return value is RT_EINTR, the operation was interrupted (interrupted system call).
103+ * When the return value is RT_ETIMEOUT, the operation timed out.
104+ *
105+ * @see _ipc_mark_thread_waiting()
106+ */
107+ static rt_err_t _ipc_wait_result (rt_thread_t thread )
108+ {
109+ if (thread -> error == - RT_EWAITPEND )
110+ {
111+ /* translate wait pending sentinel back to EINTR for callers */
112+ thread -> error = - RT_EINTR ;
113+ }
114+ return thread -> error ;
115+ }
90116
91117/**
92118 * @brief Dequeue a thread from suspended list and set it to ready. The 2 are
@@ -597,8 +623,8 @@ static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag)
597623 /* get current thread */
598624 thread = rt_thread_self ();
599625
600- /* reset thread error number */
601- thread -> error = RT_EINTR ;
626+ /* mark wait pending errno */
627+ thread -> error = - RT_EWAITPEND ;
602628
603629 LOG_D ("sem take: suspend thread - %s" , thread -> parent .name );
604630
@@ -630,9 +656,11 @@ static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t timeout, int suspend_flag)
630656 /* do schedule */
631657 rt_schedule ();
632658
633- if (thread -> error != RT_EOK )
659+ /* normalize any sentinel errno before returning to caller */
660+ ret = _ipc_wait_result (thread );
661+ if (ret != RT_EOK )
634662 {
635- return thread -> error > 0 ? - thread -> error : thread -> error ;
663+ return ret > 0 ? - ret : ret ;
636664 }
637665 }
638666 }
@@ -1403,6 +1431,9 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend
14031431 LOG_D ("mutex_take: suspend thread: %s" ,
14041432 thread -> parent .name );
14051433
1434+ /* mark wait pending errno */
1435+ thread -> error = - RT_EWAITPEND ;
1436+
14061437 /* suspend current thread */
14071438 ret = rt_thread_suspend_to_list (thread , & (mutex -> parent .suspend_thread ),
14081439 mutex -> parent .parent .flag , suspend_flag );
@@ -1452,13 +1483,16 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend
14521483
14531484 rt_spin_lock (& (mutex -> spinlock ));
14541485
1486+ /* translate sentinel back to EINTR or timeout */
1487+ ret = _ipc_wait_result (thread );
1488+
14551489 if (mutex -> owner == thread )
14561490 {
14571491 /**
14581492 * get mutex successfully
1459- * Note: assert to avoid an unexpected resume
1493+ * Note: clear any temporary error from interruptible wait
14601494 */
1461- RT_ASSERT ( thread -> error == RT_EOK ) ;
1495+ thread -> error = RT_EOK ;
14621496 }
14631497 else
14641498 {
@@ -1467,9 +1501,6 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend
14671501 rt_bool_t need_update = RT_FALSE ;
14681502 RT_ASSERT (mutex -> owner != thread );
14691503
1470- /* get value first before calling to other APIs */
1471- ret = thread -> error ;
1472-
14731504 /* unexpected resume */
14741505 if (ret == RT_EOK )
14751506 {
@@ -1673,6 +1704,9 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
16731704 /* cleanup pending object */
16741705 next_thread -> pending_object = RT_NULL ;
16751706
1707+ /* clear any temporary error from interruptible wait */
1708+ next_thread -> error = RT_EOK ;
1709+
16761710 /* update mutex priority */
16771711 if (!rt_list_isempty (& (mutex -> parent .suspend_thread )))
16781712 {
@@ -2121,8 +2155,6 @@ static rt_err_t _rt_event_recv(rt_event_t event,
21212155 status = - RT_ERROR ;
21222156 /* get current thread */
21232157 thread = rt_thread_self ();
2124- /* reset thread error */
2125- thread -> error = - RT_EINTR ;
21262158
21272159 RT_OBJECT_HOOK_CALL (rt_object_trytake_hook , (& (event -> parent .parent )));
21282160
@@ -2176,6 +2208,9 @@ static rt_err_t _rt_event_recv(rt_event_t event,
21762208 thread -> event_set = set ;
21772209 thread -> event_info = option ;
21782210
2211+ /* mark wait pending errno */
2212+ thread -> error = - RT_EWAITPEND ;
2213+
21792214 /* put thread to suspended thread list */
21802215 ret = rt_thread_suspend_to_list (thread , & (event -> parent .suspend_thread ),
21812216 event -> parent .parent .flag , suspend_flag );
@@ -2201,10 +2236,15 @@ static rt_err_t _rt_event_recv(rt_event_t event,
22012236 /* do a schedule */
22022237 rt_schedule ();
22032238
2204- if (thread -> error != RT_EOK )
2239+ /* unwrap sentinel: signal -> -RT_EINTR, timeout already set */
2240+ /* convert sentinel back to EINTR/timeout semantics */
2241+ /* translate sentinel back to EINTR or timeout */
2242+ /* normalize sentinel before reporting to caller */
2243+ ret = _ipc_wait_result (thread );
2244+ if (ret != RT_EOK )
22052245 {
22062246 /* return error */
2207- return thread -> error ;
2247+ return ret ;
22082248 }
22092249
22102250 /* received an event, disable interrupt to protect */
@@ -2600,9 +2640,6 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb,
26002640 /* mailbox is full */
26012641 while (mb -> entry == mb -> size )
26022642 {
2603- /* reset error number in thread */
2604- thread -> error = - RT_EINTR ;
2605-
26062643 /* no waiting, return timeout */
26072644 if (timeout == 0 )
26082645 {
@@ -2611,6 +2648,9 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb,
26112648 return - RT_EFULL ;
26122649 }
26132650
2651+ /* mark wait pending errno */
2652+ thread -> error = - RT_EWAITPEND ;
2653+
26142654 /* suspend current thread */
26152655 ret = rt_thread_suspend_to_list (thread , & (mb -> suspend_sender_thread ),
26162656 mb -> parent .parent .flag , suspend_flag );
@@ -2643,10 +2683,12 @@ static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb,
26432683 rt_schedule ();
26442684
26452685 /* resume from suspend state */
2646- if (thread -> error != RT_EOK )
2686+ /* normalize sentinel before continuing with mailbox recv */
2687+ ret = _ipc_wait_result (thread );
2688+ if (ret != RT_EOK )
26472689 {
26482690 /* return error */
2649- return thread -> error ;
2691+ return ret ;
26502692 }
26512693
26522694 level = rt_spin_lock_irqsave (& (mb -> spinlock ));
@@ -2880,9 +2922,6 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo
28802922 /* mailbox is empty */
28812923 while (mb -> entry == 0 )
28822924 {
2883- /* reset error number in thread */
2884- thread -> error = - RT_EINTR ;
2885-
28862925 /* no waiting, return timeout */
28872926 if (timeout == 0 )
28882927 {
@@ -2893,6 +2932,9 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo
28932932 return - RT_ETIMEOUT ;
28942933 }
28952934
2935+ /* mark wait pending errno */
2936+ thread -> error = - RT_EWAITPEND ;
2937+
28962938 /* suspend current thread */
28972939 ret = rt_thread_suspend_to_list (thread , & (mb -> parent .suspend_thread ),
28982940 mb -> parent .parent .flag , suspend_flag );
@@ -2925,10 +2967,11 @@ static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeo
29252967 rt_schedule ();
29262968
29272969 /* resume from suspend state */
2928- if (thread -> error != RT_EOK )
2970+ ret = _ipc_wait_result (thread );
2971+ if (ret != RT_EOK )
29292972 {
29302973 /* return error */
2931- return thread -> error ;
2974+ return ret ;
29322975 }
29332976 level = rt_spin_lock_irqsave (& (mb -> spinlock ));
29342977
@@ -3428,9 +3471,6 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq,
34283471 /* message queue is full */
34293472 while ((msg = (struct rt_mq_message * )mq -> msg_queue_free ) == RT_NULL )
34303473 {
3431- /* reset error number in thread */
3432- thread -> error = - RT_EINTR ;
3433-
34343474 /* no waiting, return timeout */
34353475 if (timeout == 0 )
34363476 {
@@ -3439,6 +3479,9 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq,
34393479 return - RT_EFULL ;
34403480 }
34413481
3482+ /* mark wait pending errno */
3483+ thread -> error = - RT_EWAITPEND ;
3484+
34423485 /* suspend current thread */
34433486 ret = rt_thread_suspend_to_list (thread , & (mq -> suspend_sender_thread ),
34443487 mq -> parent .parent .flag , suspend_flag );
@@ -3471,10 +3514,11 @@ static rt_err_t _rt_mq_send_wait(rt_mq_t mq,
34713514 rt_schedule ();
34723515
34733516 /* resume from suspend state */
3474- if (thread -> error != RT_EOK )
3517+ ret = _ipc_wait_result (thread );
3518+ if (ret != RT_EOK )
34753519 {
34763520 /* return error */
3477- return thread -> error ;
3521+ return ret ;
34783522 }
34793523 level = rt_spin_lock_irqsave (& (mq -> spinlock ));
34803524
@@ -3805,9 +3849,6 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq,
38053849 /* message queue is empty */
38063850 while (mq -> entry == 0 )
38073851 {
3808- /* reset error number in thread */
3809- thread -> error = - RT_EINTR ;
3810-
38113852 /* no waiting, return timeout */
38123853 if (timeout == 0 )
38133854 {
@@ -3819,6 +3860,9 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq,
38193860 return - RT_ETIMEOUT ;
38203861 }
38213862
3863+ /* mark wait pending errno */
3864+ thread -> error = - RT_EWAITPEND ;
3865+
38223866 /* suspend current thread */
38233867 ret = rt_thread_suspend_to_list (thread , & (mq -> parent .suspend_thread ),
38243868 mq -> parent .parent .flag , suspend_flag );
@@ -3851,10 +3895,11 @@ static rt_ssize_t _rt_mq_recv(rt_mq_t mq,
38513895 rt_schedule ();
38523896
38533897 /* recv message */
3854- if (thread -> error != RT_EOK )
3898+ ret = _ipc_wait_result (thread );
3899+ if (ret != RT_EOK )
38553900 {
38563901 /* return error */
3857- return thread -> error ;
3902+ return ret ;
38583903 }
38593904
38603905 level = rt_spin_lock_irqsave (& (mq -> spinlock ));
0 commit comments