3636
3737#if MICROPY_PY_THREAD
3838
39- #define MP_THREAD_MIN_STACK_SIZE (5 * 1024)
40- #define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024)
41- #define MP_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 2)
42-
43- typedef struct {
44- rt_thread_t thread ;
45- /* whether the thread is ready and running */
46- rt_bool_t ready ;
47- /* thread Python args, a GC root pointer */
48- void * arg ;
49- /* pointer to the stack */
50- void * stack ;
51- void * tcb ;
52- /* number of words in the stack */
53- size_t stack_len ;
54- rt_list_t list ;
55- } mp_thread , * mp_thread_t ;
56-
57- typedef struct {
58- rt_mutex_t mutex ;
59- rt_list_t list ;
60- } mp_mutex , * mp_mutex_t ;
39+ #define MP_THREAD_MIN_STACK_SIZE (4 * 1024)
40+ #define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024)
41+ #define MP_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 2)
42+
43+ #define MP_THREAD_STATUS_READY 0
44+ #define MP_THREAD_STATUS_RUNNING 1
45+ #define MP_THREAD_STATUS_FINISH 2
46+
47+ typedef struct _thread_t {
48+ rt_thread_t id ; // system id of thread
49+ int status ; // whether the thread is ready, running and finish
50+ void * arg ; // thread Python args, a GC root pointer
51+ void * stack ; // pointer to the stack
52+ size_t stack_len ; // number of words in the stack
53+ struct _thread_t * next ;
54+ } thread_t ;
6155
6256// the mutex controls access to the linked list
6357STATIC mp_thread_mutex_t thread_mutex ;
64- STATIC rt_list_t thread_list , mutex_list ;
65- STATIC mp_thread thread_entry0 ;
66- /* root pointer, handled by mp_thread_gc_others */
67- STATIC mp_thread * main_thread ;
58+ STATIC thread_t thread_root_node ;
59+ STATIC thread_t * thread_root ; // root pointer, handled by mp_thread_gc_others
6860
6961/**
7062 * thread port initialization
7163 *
7264 * @param stack MicroPython main thread stack
73- * @param stack_len MicroPython main thread stack, unit: word
65+ * @param stack_len MicroPython main thread stack
7466 */
7567void mp_thread_init (void * stack , uint32_t stack_len ) {
7668 mp_thread_set_state (& mp_state_ctx .thread );
7769
78- main_thread = & thread_entry0 ;
79- main_thread -> thread = rt_thread_self ();
80- main_thread -> ready = RT_TRUE ;
81- main_thread -> arg = NULL ;
82- main_thread -> stack = stack ;
83- main_thread -> stack_len = stack_len ;
84-
85- rt_list_init (& thread_list );
86- rt_list_init (& mutex_list );
87-
88- rt_list_insert_before (& thread_list , & (main_thread -> list ));
70+ thread_root = & thread_root_node ;
71+ thread_root -> id = rt_thread_self ();
72+ thread_root -> status = MP_THREAD_STATUS_RUNNING ;
73+ thread_root -> arg = NULL ;
74+ thread_root -> stack = stack ;
75+ thread_root -> stack_len = stack_len ;
76+ thread_root -> next = NULL ;
8977
9078 mp_thread_mutex_init (& thread_mutex );
9179}
9280
9381void mp_thread_gc_others (void ) {
94- struct rt_list_node * list = & thread_list , * node = NULL ;
95- mp_thread_t cur_thread_node = NULL ;
9682
9783 mp_thread_mutex_lock (& thread_mutex , 1 );
84+ for (thread_t * th = thread_root ; th != NULL ; th = th -> next ) {
85+ if (th == & thread_root_node ) {
86+ continue ;
87+ }
88+ gc_collect_root ((void * * )& th , 1 );
89+ gc_collect_root (& th -> arg , 1 ); // probably not needed
9890
99- for (node = list -> next ; node != list ; node = node -> next ) {
100- cur_thread_node = rt_list_entry (node , mp_thread , list );
101- gc_collect_root ((void * * )& cur_thread_node -> thread , 1 );
102- /* probably not needed */
103- gc_collect_root (& cur_thread_node -> arg , 1 );
104- if (cur_thread_node -> thread == rt_thread_self ()) {
91+ if (th -> id == rt_thread_self ()) {
10592 continue ;
10693 }
107- if (! cur_thread_node -> ready ) {
94+ if (th -> status != MP_THREAD_STATUS_FINISH ) {
10895 continue ;
10996 }
110- /* probably not needed */
111- gc_collect_root (cur_thread_node -> stack , cur_thread_node -> stack_len );
97+ gc_collect_root (( void * * ) & th -> id , 1 ); // probably not needed
98+ gc_collect_root (( void * * ) & th -> stack , th -> stack_len ); // probably not needed
11299 }
113-
114100 mp_thread_mutex_unlock (& thread_mutex );
115101}
116102
@@ -123,80 +109,53 @@ void mp_thread_set_state(void *state) {
123109}
124110
125111void mp_thread_start (void ) {
126- struct rt_list_node * list = & thread_list , * node = NULL ;
127- mp_thread_t cur_thread_node = NULL ;
128-
129112 mp_thread_mutex_lock (& thread_mutex , 1 );
130-
131- for (node = list -> next ; node != list ; node = node -> next ) {
132- cur_thread_node = rt_list_entry (node , mp_thread , list );
133- if (cur_thread_node -> thread == rt_thread_self ()) {
134- cur_thread_node -> ready = RT_TRUE ;
113+ for (thread_t * th = thread_root ; th != NULL ; th = th -> next ) {
114+ if (th -> id == rt_thread_self ()) {
115+ th -> status = MP_THREAD_STATUS_RUNNING ;
135116 break ;
136117 }
137118 }
138-
139119 mp_thread_mutex_unlock (& thread_mutex );
140120}
141121
142- STATIC void * (* ext_thread_entry )(void * ) = NULL ;
143-
144- STATIC void rtthread_entry (void * arg ) {
145- if (ext_thread_entry ) {
146- ext_thread_entry (arg );
147- }
148-
149- rt_thread_detach (rt_thread_self ());
150- }
151-
152122void mp_thread_create_ex (void * (* entry )(void * ), void * arg , size_t * stack_size , int priority , char * name ) {
153- // store thread entry function into a global variable so we can access it
154- ext_thread_entry = entry ;//(void (*)(void *parameter))
123+ static uint8_t count = 0 ;
155124
156125 if (* stack_size == 0 ) {
157126 * stack_size = MP_THREAD_DEFAULT_STACK_SIZE ; // default stack size
158127 } else if (* stack_size < MP_THREAD_MIN_STACK_SIZE ) {
159128 * stack_size = MP_THREAD_MIN_STACK_SIZE ; // minimum stack size
160129 }
161130
162- // allocate TCB, stack and linked-list node (must be outside thread_mutex lock)
163- rt_thread_t th = m_new_obj (struct rt_thread );
131+ // allocate the linked-list node, TCB and stack (must be outside thread_mutex lock)
132+ thread_t * th = m_new_obj (thread_t );
164133 if (th == NULL ) {
165- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't create thread TCB " ));
134+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't create thread obj " ));
166135 }
167- uint8_t * stack = m_new ( uint8_t , * stack_size );
168- if (stack == NULL ) {
169- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't create thread stack " ));
136+ th -> id = m_new_obj ( struct rt_thread );
137+ if (th -> id == NULL ) {
138+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't create thread id " ));
170139 }
171- mp_thread * node = m_new_obj ( mp_thread );
172- if (node == NULL ) {
173- nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't create thread list node " ));
140+ th -> stack = m_new ( uint8_t , * stack_size );
141+ if (th -> stack == NULL ) {
142+ nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "can't create thread stack " ));
174143 }
175- // adjust the stack_size to provide room to recover from hitting the limit
176- * stack_size -= 1024 ;
177-
178- node -> ready = RT_FALSE ;
179- node -> arg = arg ;
180- node -> stack = stack ;
181- node -> stack_len = * stack_size / 4 ;
182144
183145 mp_thread_mutex_lock (& thread_mutex , 1 );
184146
185- rt_thread_init (th , name , rtthread_entry , arg , stack , * stack_size , priority , 0 );
147+ // adjust the stack_size to provide room to recover from hitting the limit
148+ * stack_size -= 1024 ;
186149
187150 // add thread to linked list of all threads
188- {
189- rt_base_t level ;
190-
191- level = rt_hw_interrupt_disable ();
192-
193- node -> thread = th ;
194- rt_list_insert_before (& thread_list , & (node -> list ));
195-
196- rt_hw_interrupt_enable (level );
197- }
151+ th -> status = MP_THREAD_STATUS_READY ;
152+ th -> arg = arg ;
153+ th -> stack_len = * stack_size ;
154+ th -> next = thread_root ;
155+ thread_root = th ;
198156
199- rt_thread_startup (th );
157+ rt_thread_init (th -> id , name , (void (* )(void * ))entry , arg , th -> stack , * stack_size , priority , count ++ );
158+ rt_thread_startup (th -> id );
200159
201160 mp_thread_mutex_unlock (& thread_mutex );
202161}
@@ -206,96 +165,64 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
206165 char name [RT_NAME_MAX ];
207166
208167 /* build name */
209- rt_snprintf (name , sizeof (name ), "mp%02d" , count ++ );
168+ rt_snprintf (name , sizeof (name ), "mp%02d" , count ++ );
210169
211170 mp_thread_create_ex (entry , arg , stack_size , MP_THREAD_PRIORITY , name );
212171}
213172
214173void mp_thread_finish (void ) {
215- struct rt_list_node * list = & thread_list , * node = NULL ;
216- mp_thread_t cur_thread_node = NULL ;
174+ thread_t * prev = NULL ;
217175
218176 mp_thread_mutex_lock (& thread_mutex , 1 );
219-
220- for (node = list -> next ; node != list ; node = node -> next ) {
221- cur_thread_node = rt_list_entry (node , mp_thread , list );
222- if (cur_thread_node -> thread == rt_thread_self ()) {
223- cur_thread_node -> ready = RT_FALSE ;
177+ for (thread_t * th = thread_root ; th != NULL ;prev = th , th = th -> next ) {
178+ // unlink the node from the list
179+ if (th -> id == rt_thread_self ()) {
180+
181+ if (prev != NULL ) {
182+ prev -> next = th -> next ;
183+ } else {
184+ // move the start pointer
185+ thread_root = th -> next ;
186+ }
187+ th -> status = MP_THREAD_STATUS_FINISH ;
224188 // explicitly release all its memory
225- m_del (rt_thread_t , cur_thread_node -> thread , 1 );
226- m_del (uint8_t , cur_thread_node -> stack , cur_thread_node -> stack_len );
227- // m_del(mp_thread, cur_thread_node, 1);
228- rt_list_remove (node );
189+ m_del_obj (struct rt_thread , th -> id );
190+ m_del (uint8_t , th -> stack , th -> stack_len );
191+ m_del_obj (thread_t , th );
229192 break ;
230193 }
231194 }
232-
233195 mp_thread_mutex_unlock (& thread_mutex );
234-
235- rt_thread_detach (rt_thread_self ());
236196}
237197
238198void mp_thread_mutex_init (mp_thread_mutex_t * mutex ) {
239199 static uint8_t count = 0 ;
240200 char name [RT_NAME_MAX ];
241- rt_base_t level ;
242201
243- level = rt_hw_interrupt_disable ();
244-
245- mp_mutex * node = rt_malloc ( sizeof (mp_mutex ) );
246- if ( node == NULL ) {
247- nlr_raise ( mp_obj_new_exception_msg ( & mp_type_OSError , "can't create mutex list node" )) ;
202+ if (! mutex -> is_init ) {
203+ /* build name */
204+ rt_snprintf ( name , sizeof (name ), "mp%02d" , count ++ );
205+ rt_mutex_init ( & ( mutex -> mutex ), name , RT_IPC_FLAG_FIFO );
206+ mutex -> is_init = 1 ;
248207 }
249-
250- /* build name */
251- rt_snprintf (name , sizeof (name ), "mp%02d" , count ++ );
252-
253- rt_mutex_init ((rt_mutex_t ) mutex , name , RT_IPC_FLAG_FIFO );
254-
255- // add mutex to linked list of all mutexs
256- node -> mutex = (rt_mutex_t )mutex ;
257- rt_list_insert_before (& mutex_list , & (node -> list ));
258-
259- rt_hw_interrupt_enable (level );
260208}
261209
262210int mp_thread_mutex_lock (mp_thread_mutex_t * mutex , int wait ) {
263- return (RT_EOK == rt_mutex_take (( rt_mutex_t ) mutex , wait ? RT_WAITING_FOREVER : 0 ));
211+ return (RT_EOK == rt_mutex_take (& ( mutex -> mutex ) , wait ? RT_WAITING_FOREVER : 0 ));
264212}
265213
266214void mp_thread_mutex_unlock (mp_thread_mutex_t * mutex ) {
267- rt_mutex_release (( rt_mutex_t ) mutex );
215+ rt_mutex_release (& ( mutex -> mutex ) );
268216}
269217
270218void mp_thread_deinit (void ) {
271- rt_base_t level ;
272-
273- level = rt_hw_interrupt_disable ();
274- /* remove all thread node on list */
275- {
276- struct rt_list_node * list = & thread_list , * node = NULL ;
277- mp_thread_t cur_thread_node = NULL ;
278-
279- for (node = list -> next ; node != list ; node = node -> next ) {
280- cur_thread_node = rt_list_entry (node , mp_thread , list );
281- if (cur_thread_node -> thread != main_thread -> thread ) {
282- rt_thread_detach (cur_thread_node -> thread );
283- }
284- }
285- }
286- /* remove all mutex node on list */
287- {
288- struct rt_list_node * list = & mutex_list , * node = NULL ;
289- mp_mutex_t cur_mutex_node = NULL ;
290-
291- for (node = list -> next ; node != list ; node = node -> next ) {
292- cur_mutex_node = rt_list_entry (node , mp_mutex , list );
293- rt_mutex_detach (cur_mutex_node -> mutex );
294- rt_free (cur_mutex_node );
219+ // detach all ready and running mpy thread
220+ for (thread_t * th = thread_root ; th != NULL ; th = th -> next ) {
221+ if (th != & thread_root_node && th -> status != MP_THREAD_STATUS_FINISH ) {
222+ rt_thread_detach (th -> id );
295223 }
296224 }
297225
298- rt_hw_interrupt_enable (level );
299226 // allow RT-Thread to clean-up the threads
300227 rt_thread_delay (200 );
301228}
0 commit comments