1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-07-25 Shell first version
9 * 2023-11-25 Shell Add pgrp, session lock API
10 */
11
12 #define DBG_TAG "lwp.internal"
13 #define DBG_LVL DBG_INFO
14 #include <rtdbg.h>
15
16 #include <stdlib.h>
17 #include "lwp_internal.h"
18
_mutex_take_safe(rt_mutex_t mtx,rt_int32_t timeout,int flags)19 static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags)
20 {
21 LWP_DEF_RETURN_CODE(rc);
22 int retry;
23 rt_int32_t effect_timeout;
24
25 #ifdef LWP_DEBUG
26 rt_thread_t thread = rt_thread_self();
27 #endif
28
29 if (mtx)
30 {
31 effect_timeout = timeout;
32 #if DBG_LVL == DBG_LOG && defined(LWP_DEBUG)
33 int exception;
34 rt_list_t *node = RT_NULL;
35 struct rt_mutex *tak_obj = RT_NULL;
36 if (!rt_list_isempty(&(thread->taken_object_list)) && timeout == RT_WAITING_FOREVER)
37 {
38 exception = 1;
39 effect_timeout = 0;
40 }
41 else
42 {
43 exception = 0;
44 }
45 #endif /* DBG_LOG && defined(LWP_DEBUG) */
46
47 do {
48 retry = 0;
49 if (flags & LWP_MTX_FLAGS_INTR)
50 rc = rt_mutex_take_interruptible(mtx, effect_timeout);
51 else
52 rc = rt_mutex_take_killable(mtx, effect_timeout);
53
54 #ifdef LWP_DEBUG
55 if (rc == RT_EOK)
56 {
57 if (!(flags & LWP_MTX_FALGS_NESTED) && rt_mutex_get_hold(mtx) > 1)
58 {
59 LOG_W("Already hold the lock");
60 rt_backtrace();
61 }
62 }
63 else if (rc == -RT_ETIMEOUT)
64 {
65 #if DBG_LVL == DBG_LOG
66 if (exception)
67 {
68 rt_list_for_each(node, &(thread->taken_object_list))
69 {
70 tak_obj = rt_list_entry(node, struct rt_mutex, taken_list);
71 if (rt_mutex_get_owner(tak_obj)->stat & RT_THREAD_SUSPEND_MASK)
72 LOG_D("Potential dead lock - Taken: %s, Try take: %s",
73 tak_obj->parent.parent.name, mtx->parent.parent.name);
74 }
75 rt_backtrace();
76 retry = 1;
77 exception = 0;
78 }
79 #endif
80 }
81 else if (rc != -RT_EINTR)
82 {
83 char tname[RT_NAME_MAX];
84 rt_thread_get_name(thread, tname, sizeof(tname));
85 LOG_W("Possible kernel corruption detected on thread %s with errno %ld", tname, rc);
86 }
87 #endif /* LWP_DEBUG */
88 } while (retry);
89 }
90 else
91 {
92 rc = -RT_ERROR;
93 LOG_W("%s: mtx should not be NULL", __func__);
94 RT_ASSERT(0);
95 }
96
97 LWP_RETURN(rc);
98 }
99
lwp_mutex_take_safe(rt_mutex_t mtx,rt_int32_t timeout,int flags)100 rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags)
101 {
102 LWP_DEF_RETURN_CODE(rc);
103 rc = _mutex_take_safe(mtx, timeout, flags);
104 LWP_RETURN(rc);
105 }
106
lwp_mutex_release_safe(rt_mutex_t mtx)107 rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx)
108 {
109 LWP_DEF_RETURN_CODE(rc);
110
111 rc = rt_mutex_release(mtx);
112 if (rc)
113 {
114 LOG_I("%s: release failed with code %ld", __func__, rc);
115 rt_backtrace();
116 }
117
118 LWP_RETURN(rc);
119 }
120
lwp_critical_enter(struct rt_lwp * lwp,int flags)121 rt_err_t lwp_critical_enter(struct rt_lwp *lwp, int flags)
122 {
123 rt_err_t rc;
124 do {
125 rc = lwp_mutex_take_safe(&lwp->lwp_lock, RT_WAITING_FOREVER, flags);
126 } while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
127
128 /* if current process is force killed */
129 if (rc != RT_EOK && rc != -RT_EINTR)
130 {
131 LOG_I("%s: unexpected return code = %ld", __func__, rc);
132 }
133
134 return rc;
135 }
136
lwp_critical_exit(struct rt_lwp * lwp)137 rt_err_t lwp_critical_exit(struct rt_lwp *lwp)
138 {
139 return lwp_mutex_release_safe(&lwp->lwp_lock);
140 }
141
lwp_pgrp_critical_enter(struct rt_processgroup * pgrp,int flags)142 rt_err_t lwp_pgrp_critical_enter(struct rt_processgroup *pgrp, int flags)
143 {
144 rt_err_t rc;
145 do {
146 rc = lwp_mutex_take_safe(&pgrp->mutex, RT_WAITING_FOREVER, flags);
147 } while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
148
149 /* if current process is force killed */
150 if (rc != RT_EOK && rc != -RT_EINTR)
151 {
152 LOG_I("%s: unexpected return code = %ld", __func__, rc);
153 }
154
155 return rc;
156 }
157
lwp_pgrp_critical_exit(struct rt_processgroup * pgrp)158 rt_err_t lwp_pgrp_critical_exit(struct rt_processgroup *pgrp)
159 {
160 return lwp_mutex_release_safe(&pgrp->mutex);
161 }
162
lwp_sess_critical_enter(struct rt_session * sess,int flags)163 rt_err_t lwp_sess_critical_enter(struct rt_session *sess, int flags)
164 {
165 rt_err_t rc;
166 do {
167 rc = lwp_mutex_take_safe(&sess->mutex, RT_WAITING_FOREVER, flags);
168 } while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
169
170 /* if current process is force killed */
171 if (rc != RT_EOK && rc != -RT_EINTR)
172 {
173 LOG_I("%s: unexpected return code = %ld", __func__, rc);
174 }
175
176 return rc;
177 }
178
lwp_sess_critical_exit(struct rt_session * sess)179 rt_err_t lwp_sess_critical_exit(struct rt_session *sess)
180 {
181 return lwp_mutex_release_safe(&sess->mutex);
182 }
183