1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-01-15 shaojinchun first version
9 * 2023-11-16 xqyjlj Fix the case where tid is 0
10 */
11
12 #define DBG_TAG "lwp.tid"
13 #define DBG_LVL DBG_LOG
14 #include <rtdbg.h>
15
16 #include <rthw.h>
17 #include <rtthread.h>
18
19 #include "lwp_internal.h"
20
21 #ifdef ARCH_MM_MMU
22 #include "lwp_user_mm.h"
23 #endif
24
25 #define TID_MAX 10000
26
27 #define TID_CT_ASSERT(name, x) \
28 struct assert_##name {char ary[2 * (x) - 1];}
29
30 TID_CT_ASSERT(tid_min_nr, LWP_TID_MAX_NR > 1);
31 TID_CT_ASSERT(tid_max_nr, LWP_TID_MAX_NR < TID_MAX);
32
33 static struct lwp_avl_struct lwp_tid_ary[LWP_TID_MAX_NR];
34 static struct lwp_avl_struct *lwp_tid_free_head = RT_NULL;
35 static int lwp_tid_ary_alloced = 0;
36 static struct lwp_avl_struct *lwp_tid_root = RT_NULL;
37 static int current_tid = 0;
38
39 static struct rt_mutex tid_lock;
40
lwp_tid_init(void)41 int lwp_tid_init(void)
42 {
43 return rt_mutex_init(&tid_lock, "tidmtx", RT_IPC_FLAG_PRIO);
44 }
45
lwp_tid_get(void)46 int lwp_tid_get(void)
47 {
48 struct lwp_avl_struct *p;
49 int tid = 0;
50
51 lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
52 p = lwp_tid_free_head;
53 if (p)
54 {
55 lwp_tid_free_head = (struct lwp_avl_struct *)p->avl_right;
56 }
57 else if (lwp_tid_ary_alloced < LWP_TID_MAX_NR)
58 {
59 p = lwp_tid_ary + lwp_tid_ary_alloced;
60 lwp_tid_ary_alloced++;
61 }
62 if (p)
63 {
64 int found_noused = 0;
65
66 RT_ASSERT(p->data == RT_NULL);
67 for (tid = current_tid + 1; tid < TID_MAX; tid++)
68 {
69 if (!lwp_avl_find(tid, lwp_tid_root))
70 {
71 found_noused = 1;
72 break;
73 }
74 }
75 if (!found_noused)
76 {
77 for (tid = 1; tid <= current_tid; tid++)
78 {
79 if (!lwp_avl_find(tid, lwp_tid_root))
80 {
81 found_noused = 1;
82 break;
83 }
84 }
85 }
86 p->avl_key = tid;
87 lwp_avl_insert(p, &lwp_tid_root);
88 current_tid = tid;
89 }
90 lwp_mutex_release_safe(&tid_lock);
91
92 if (tid <= 0)
93 {
94 LOG_W("resource TID exhausted.");
95 }
96
97 return tid;
98 }
99
lwp_tid_put(int tid)100 void lwp_tid_put(int tid)
101 {
102 struct lwp_avl_struct *p;
103 rt_thread_t thread;
104 rt_thread_t current;
105
106 lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
107 p = lwp_avl_find(tid, lwp_tid_root);
108 if (p)
109 {
110 thread = p->data;
111 p->data = RT_NULL;
112 lwp_avl_remove(p, &lwp_tid_root);
113 p->avl_right = lwp_tid_free_head;
114 lwp_tid_free_head = p;
115 }
116 else
117 thread = RT_NULL;
118
119 if (thread && thread->tid_ref_count)
120 {
121 current = rt_thread_self();
122 RT_ASSERT(thread->susp_recycler == RT_NULL);
123 thread->susp_recycler = current;
124
125 rt_enter_critical();
126 rt_thread_suspend_with_flag(current, RT_UNINTERRUPTIBLE);
127 lwp_mutex_release_safe(&tid_lock);
128 rt_exit_critical();
129
130 rt_schedule();
131 }
132 else
133 lwp_mutex_release_safe(&tid_lock);
134 }
135
lwp_tid_get_thread_raw(int tid)136 rt_thread_t lwp_tid_get_thread_raw(int tid)
137 {
138 struct lwp_avl_struct *p;
139 rt_thread_t thread = RT_NULL;
140
141 p = lwp_avl_find(tid, lwp_tid_root);
142 if (p)
143 {
144 thread = (rt_thread_t)p->data;
145 }
146 return thread;
147 }
148
lwp_tid_get_thread_and_inc_ref(int tid)149 rt_thread_t lwp_tid_get_thread_and_inc_ref(int tid)
150 {
151 rt_thread_t thread = RT_NULL;
152
153 lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
154 thread = tid ? lwp_tid_get_thread_raw(tid) : rt_thread_self();
155 if (thread != RT_NULL)
156 {
157 thread->tid_ref_count += 1;
158 }
159 lwp_mutex_release_safe(&tid_lock);
160 return thread;
161 }
162
lwp_tid_dec_ref(rt_thread_t thread)163 void lwp_tid_dec_ref(rt_thread_t thread)
164 {
165 rt_thread_t susp_putter;
166 if (thread)
167 {
168 RT_ASSERT(rt_object_get_type(&thread->parent) == RT_Object_Class_Thread);
169 susp_putter = thread->susp_recycler;
170 lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
171
172 RT_ASSERT(thread->tid_ref_count > 0);
173 thread->tid_ref_count -= 1;
174 if (!thread->tid_ref_count && susp_putter)
175 {
176 rt_thread_resume(susp_putter);
177 }
178 lwp_mutex_release_safe(&tid_lock);
179 }
180 }
181
lwp_tid_set_thread(int tid,rt_thread_t thread)182 void lwp_tid_set_thread(int tid, rt_thread_t thread)
183 {
184 struct lwp_avl_struct *p;
185
186 lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
187 p = lwp_avl_find(tid, lwp_tid_root);
188 if (p)
189 {
190 RT_ASSERT(p->data == RT_NULL);
191 p->data = thread;
192 }
193 lwp_mutex_release_safe(&tid_lock);
194 }
195