Skip to content

Commit 6762192

Browse files
committed
【完善】多线程功能的适配。
Signed-off-by: armink <[email protected]>
1 parent c90cc71 commit 6762192

File tree

5 files changed

+96
-164
lines changed

5 files changed

+96
-164
lines changed

lib/utils/pyexec.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ int pyexec_friendly_repl(void) {
446446
} else if (ret == CHAR_CTRL_D) {
447447
// exit for a soft reset
448448
mp_hal_stdout_tx_str("\r\n");
449-
vstr_clear(&line);
449+
//TODO it will occur assert on RT-Thread platform, so comment it
450+
// vstr_clear(&line);
450451
return PYEXEC_FORCED_EXIT;
451452
} else if (ret == CHAR_CTRL_E) {
452453
// paste mode

port/genhdr/qstrdefs.generated.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,5 +679,6 @@ QDEF(MP_QSTR_irq, (const byte*)"\x8f\x03" "irq")
679679
QDEF(MP_QSTR_onewire, (const byte*)"\x28\x07" "onewire")
680680
QDEF(MP_QSTR___dir__, (const byte*)"\x7a\x07" "__dir__")
681681
QDEF(MP_QSTR___int__, (const byte*)"\x16\x07" "__int__")
682+
QDEF(MP_QSTR_schedule, (const byte*)"\xe0\x08" "schedule")
682683

683684
// This file was automatically generated by makeqstrdata.py

port/mpthreadport.c

Lines changed: 85 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -36,81 +36,67 @@
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
6357
STATIC 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
*/
7567
void 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

9381
void 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

125111
void 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-
152122
void 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

214173
void 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

238198
void 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

262210
int 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

266214
void 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

270218
void 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
}

port/mpthreadport.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@
2929

3030
#include "rtthread.h"
3131

32-
typedef struct rt_mutex mp_thread_mutex_t;
32+
typedef struct _mp_thread_mutex_t {
33+
struct rt_mutex mutex;
34+
int is_init;
35+
} mp_thread_mutex_t;
3336

3437
void mp_thread_init(void *stack, uint32_t stack_len);
3538
void mp_thread_gc_others(void);

port/mpy_main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,14 @@ void mpy_main(const char *filename) {
138138
}
139139
}
140140

141-
#if MICROPY_PY_THREAD
142-
mp_thread_deinit();
143-
#endif
144-
145141
gc_sweep_all();
146142

147143
mp_deinit();
148144

145+
#if MICROPY_PY_THREAD
146+
mp_thread_deinit();
147+
#endif
148+
149149
rt_free(heap);
150150

151151
rtt_getchar_deinit();

0 commit comments

Comments
 (0)