Przeglądaj źródła

【完善】多线程功能的适配。

Signed-off-by: armink <armink.ztl@gmail.com>
armink 7 lat temu
rodzic
commit
6762192433
5 zmienionych plików z 96 dodań i 164 usunięć
  1. 2 1
      lib/utils/pyexec.c
  2. 1 0
      port/genhdr/qstrdefs.generated.h
  3. 85 158
      port/mpthreadport.c
  4. 4 1
      port/mpthreadport.h
  5. 4 4
      port/mpy_main.c

+ 2 - 1
lib/utils/pyexec.c

@@ -446,7 +446,8 @@ friendly_repl_reset:
         } else if (ret == CHAR_CTRL_D) {
             // exit for a soft reset
             mp_hal_stdout_tx_str("\r\n");
-            vstr_clear(&line);
+            //TODO it will occur assert on RT-Thread platform, so comment it
+//            vstr_clear(&line);
             return PYEXEC_FORCED_EXIT;
         } else if (ret == CHAR_CTRL_E) {
             // paste mode

+ 1 - 0
port/genhdr/qstrdefs.generated.h

@@ -679,5 +679,6 @@ QDEF(MP_QSTR_irq, (const byte*)"\x8f\x03" "irq")
 QDEF(MP_QSTR_onewire, (const byte*)"\x28\x07" "onewire")
 QDEF(MP_QSTR___dir__, (const byte*)"\x7a\x07" "__dir__")
 QDEF(MP_QSTR___int__, (const byte*)"\x16\x07" "__int__")
+QDEF(MP_QSTR_schedule, (const byte*)"\xe0\x08" "schedule")
 
 // This file was automatically generated by makeqstrdata.py

+ 85 - 158
port/mpthreadport.c

@@ -36,81 +36,67 @@
 
 #if MICROPY_PY_THREAD
 
-#define MP_THREAD_MIN_STACK_SIZE                        (5 * 1024)
-#define MP_THREAD_DEFAULT_STACK_SIZE                    (MP_THREAD_MIN_STACK_SIZE + 1024)
-#define MP_THREAD_PRIORITY                              (RT_THREAD_PRIORITY_MAX / 2)
-
-typedef struct {
-    rt_thread_t thread;
-    /* whether the thread is ready and running */
-    rt_bool_t ready;
-    /* thread Python args, a GC root pointer */
-    void *arg;
-    /* pointer to the stack */
-    void *stack;
-    void *tcb;
-    /* number of words in the stack */
-    size_t stack_len;
-    rt_list_t list;
-} mp_thread, *mp_thread_t;
-
-typedef struct {
-    rt_mutex_t mutex;
-    rt_list_t list;
-} mp_mutex, *mp_mutex_t;
+#define MP_THREAD_MIN_STACK_SIZE                 (4 * 1024)
+#define MP_THREAD_DEFAULT_STACK_SIZE             (MP_THREAD_MIN_STACK_SIZE + 1024)
+#define MP_THREAD_PRIORITY                       (RT_THREAD_PRIORITY_MAX / 2)
+
+#define MP_THREAD_STATUS_READY                   0
+#define MP_THREAD_STATUS_RUNNING                 1
+#define MP_THREAD_STATUS_FINISH                  2
+
+typedef struct _thread_t {
+    rt_thread_t id;         // system id of thread
+    int status;              // whether the thread is ready, running and finish
+    void *arg;              // thread Python args, a GC root pointer
+    void *stack;            // pointer to the stack
+    size_t stack_len;       // number of words in the stack
+    struct _thread_t *next;
+} thread_t;
 
 // the mutex controls access to the linked list
 STATIC mp_thread_mutex_t thread_mutex;
-STATIC rt_list_t thread_list, mutex_list;
-STATIC mp_thread thread_entry0;
-/* root pointer, handled by mp_thread_gc_others */
-STATIC mp_thread *main_thread;
+STATIC thread_t thread_root_node;
+STATIC thread_t *thread_root; // root pointer, handled by mp_thread_gc_others
 
 /**
  * thread port initialization
  *
  * @param stack MicroPython main thread stack
- * @param stack_len MicroPython main thread stack, unit: word
+ * @param stack_len MicroPython main thread stack
  */
 void mp_thread_init(void *stack, uint32_t stack_len) {
     mp_thread_set_state(&mp_state_ctx.thread);
 
-    main_thread = &thread_entry0;
-    main_thread->thread = rt_thread_self();
-    main_thread->ready = RT_TRUE;
-    main_thread->arg = NULL;
-    main_thread->stack = stack;
-    main_thread->stack_len = stack_len;
-
-    rt_list_init(&thread_list);
-    rt_list_init(&mutex_list);
-
-    rt_list_insert_before(&thread_list, &(main_thread->list));
+    thread_root = &thread_root_node;
+    thread_root->id = rt_thread_self();
+    thread_root->status = MP_THREAD_STATUS_RUNNING;
+    thread_root->arg = NULL;
+    thread_root->stack = stack;
+    thread_root->stack_len = stack_len;
+    thread_root->next = NULL;
 
     mp_thread_mutex_init(&thread_mutex);
 }
 
 void mp_thread_gc_others(void) {
-    struct rt_list_node *list = &thread_list, *node = NULL;
-    mp_thread_t cur_thread_node = NULL;
 
     mp_thread_mutex_lock(&thread_mutex, 1);
+    for (thread_t *th = thread_root; th != NULL; th = th->next) {
+        if (th == &thread_root_node) {
+            continue;
+        }
+        gc_collect_root((void**)&th, 1);
+        gc_collect_root(&th->arg, 1); // probably not needed
 
-    for (node = list->next; node != list; node = node->next) {
-        cur_thread_node = rt_list_entry(node, mp_thread, list);
-        gc_collect_root((void **)&cur_thread_node->thread, 1);
-        /* probably not needed */
-        gc_collect_root(&cur_thread_node->arg, 1);
-        if (cur_thread_node->thread == rt_thread_self()) {
+        if (th->id == rt_thread_self()) {
             continue;
         }
-        if (!cur_thread_node->ready) {
+        if (th->status != MP_THREAD_STATUS_FINISH) {
             continue;
         }
-        /* probably not needed */
-        gc_collect_root(cur_thread_node->stack, cur_thread_node->stack_len);
+        gc_collect_root((void**)&th->id, 1); // probably not needed
+        gc_collect_root((void**)&th->stack, th->stack_len); // probably not needed
     }
-
     mp_thread_mutex_unlock(&thread_mutex);
 }
 
@@ -123,35 +109,18 @@ void mp_thread_set_state(void *state) {
 }
 
 void mp_thread_start(void) {
-    struct rt_list_node *list = &thread_list, *node = NULL;
-    mp_thread_t cur_thread_node = NULL;
-
     mp_thread_mutex_lock(&thread_mutex, 1);
-
-    for (node = list->next; node != list; node = node->next) {
-        cur_thread_node = rt_list_entry(node, mp_thread, list);
-        if (cur_thread_node->thread == rt_thread_self()) {
-            cur_thread_node->ready = RT_TRUE;
+    for (thread_t *th = thread_root; th != NULL; th = th->next) {
+        if (th->id == rt_thread_self()) {
+            th->status = MP_THREAD_STATUS_RUNNING;
             break;
         }
     }
-
     mp_thread_mutex_unlock(&thread_mutex);
 }
 
-STATIC void *(*ext_thread_entry)(void*) = NULL;
-
-STATIC void rtthread_entry(void *arg) {
-    if (ext_thread_entry) {
-        ext_thread_entry(arg);
-    }
-
-    rt_thread_detach(rt_thread_self());
-}
-
 void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, int priority, char *name) {
-    // store thread entry function into a global variable so we can access it
-    ext_thread_entry = entry;//(void (*)(void *parameter))
+    static uint8_t count = 0;
 
     if (*stack_size == 0) {
         *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size
@@ -159,44 +128,34 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i
         *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size
     }
 
-    // allocate TCB, stack and linked-list node (must be outside thread_mutex lock)
-    rt_thread_t th = m_new_obj(struct rt_thread);
+    // allocate the linked-list node, TCB and stack (must be outside thread_mutex lock)
+    thread_t *th = m_new_obj(thread_t);
     if (th == NULL) {
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread TCB"));
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread obj"));
     }
-    uint8_t *stack = m_new(uint8_t, *stack_size);
-    if (stack == NULL) {
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread stack"));
+    th->id = m_new_obj(struct rt_thread);
+    if (th->id == NULL) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread id"));
     }
-    mp_thread *node = m_new_obj(mp_thread);
-    if (node == NULL) {
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread list node"));
+    th->stack = m_new(uint8_t, *stack_size);
+    if (th->stack == NULL) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread stack"));
     }
-    // adjust the stack_size to provide room to recover from hitting the limit
-    *stack_size -= 1024;
-
-    node->ready = RT_FALSE;
-    node->arg = arg;
-    node->stack = stack;
-    node->stack_len = *stack_size / 4;
 
     mp_thread_mutex_lock(&thread_mutex, 1);
 
-    rt_thread_init(th, name, rtthread_entry, arg, stack, *stack_size, priority, 0);
+    // adjust the stack_size to provide room to recover from hitting the limit
+    *stack_size -= 1024;
 
     // add thread to linked list of all threads
-    {
-        rt_base_t level;
-
-        level = rt_hw_interrupt_disable();
-
-        node->thread = th;
-        rt_list_insert_before(&thread_list, &(node->list));
-
-        rt_hw_interrupt_enable(level);
-    }
+    th->status = MP_THREAD_STATUS_READY;
+    th->arg = arg;
+    th->stack_len = *stack_size;
+    th->next = thread_root;
+    thread_root = th;
 
-    rt_thread_startup(th);
+    rt_thread_init(th->id, name, (void (*)(void *))entry, arg, th->stack, *stack_size, priority, count++);
+    rt_thread_startup(th->id);
 
     mp_thread_mutex_unlock(&thread_mutex);
 }
@@ -206,96 +165,64 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
     char name[RT_NAME_MAX];
 
     /* build name */
-    rt_snprintf(name, sizeof(name), "mp%02d", count ++);
+    rt_snprintf(name, sizeof(name), "mp%02d", count++);
 
     mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, name);
 }
 
 void mp_thread_finish(void) {
-    struct rt_list_node *list = &thread_list, *node = NULL;
-    mp_thread_t cur_thread_node = NULL;
+    thread_t *prev = NULL;
 
     mp_thread_mutex_lock(&thread_mutex, 1);
-
-    for (node = list->next; node != list; node = node->next) {
-        cur_thread_node = rt_list_entry(node, mp_thread, list);
-        if (cur_thread_node->thread == rt_thread_self()) {
-            cur_thread_node->ready = RT_FALSE;
+    for (thread_t *th = thread_root; th != NULL;prev = th, th = th->next) {
+        // unlink the node from the list
+        if (th->id == rt_thread_self()) {
+
+            if (prev != NULL) {
+                prev->next = th->next;
+            } else {
+                // move the start pointer
+                thread_root = th->next;
+            }
+            th->status = MP_THREAD_STATUS_FINISH;
             // explicitly release all its memory
-            m_del(rt_thread_t, cur_thread_node->thread, 1);
-            m_del(uint8_t, cur_thread_node->stack, cur_thread_node->stack_len);
-//            m_del(mp_thread, cur_thread_node, 1);
-            rt_list_remove(node);
+            m_del_obj(struct rt_thread, th->id);
+            m_del(uint8_t, th->stack, th->stack_len);
+            m_del_obj(thread_t, th);
             break;
         }
     }
-
     mp_thread_mutex_unlock(&thread_mutex);
-
-    rt_thread_detach(rt_thread_self());
 }
 
 void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
     static uint8_t count = 0;
     char name[RT_NAME_MAX];
-    rt_base_t level;
 
-    level = rt_hw_interrupt_disable();
-
-    mp_mutex *node = rt_malloc(sizeof(mp_mutex));
-    if (node == NULL) {
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create mutex list node"));
+    if (!mutex->is_init) {
+        /* build name */
+        rt_snprintf(name, sizeof(name), "mp%02d", count++);
+        rt_mutex_init(&(mutex->mutex), name, RT_IPC_FLAG_FIFO);
+        mutex->is_init = 1;
     }
-
-    /* build name */
-    rt_snprintf(name, sizeof(name), "mp%02d", count ++);
-
-    rt_mutex_init((rt_mutex_t) mutex, name, RT_IPC_FLAG_FIFO);
-
-    // add mutex to linked list of all mutexs
-    node->mutex = (rt_mutex_t)mutex;
-    rt_list_insert_before(&mutex_list, &(node->list));
-
-    rt_hw_interrupt_enable(level);
 }
 
 int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
-    return (RT_EOK == rt_mutex_take((rt_mutex_t) mutex, wait ? RT_WAITING_FOREVER : 0));
+    return (RT_EOK == rt_mutex_take(&(mutex->mutex), wait ? RT_WAITING_FOREVER : 0));
 }
 
 void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
-    rt_mutex_release((rt_mutex_t) mutex);
+    rt_mutex_release(&(mutex->mutex));
 }
 
 void mp_thread_deinit(void) {
-    rt_base_t level;
-
-    level = rt_hw_interrupt_disable();
-    /* remove all thread node on list */
-    {
-        struct rt_list_node *list = &thread_list, *node = NULL;
-        mp_thread_t cur_thread_node = NULL;
-
-        for (node = list->next; node != list; node = node->next) {
-            cur_thread_node = rt_list_entry(node, mp_thread, list);
-            if (cur_thread_node->thread != main_thread->thread) {
-                rt_thread_detach(cur_thread_node->thread);
-            }
-        }
-    }
-    /* remove all mutex node on list */
-    {
-        struct rt_list_node *list = &mutex_list, *node = NULL;
-        mp_mutex_t cur_mutex_node = NULL;
-
-        for (node = list->next; node != list; node = node->next) {
-            cur_mutex_node = rt_list_entry(node, mp_mutex, list);
-            rt_mutex_detach(cur_mutex_node->mutex);
-            rt_free(cur_mutex_node);
+    // detach all ready and running mpy thread
+    for (thread_t *th = thread_root; th != NULL; th = th->next) {
+        if (th != &thread_root_node && th->status != MP_THREAD_STATUS_FINISH) {
+            rt_thread_detach(th->id);
         }
     }
 
-    rt_hw_interrupt_enable(level);
     // allow RT-Thread to clean-up the threads
     rt_thread_delay(200);
 }

+ 4 - 1
port/mpthreadport.h

@@ -29,7 +29,10 @@
 
 #include "rtthread.h"
 
-typedef struct rt_mutex mp_thread_mutex_t;
+typedef struct _mp_thread_mutex_t {
+    struct rt_mutex mutex;
+    int is_init;
+} mp_thread_mutex_t;
 
 void mp_thread_init(void *stack, uint32_t stack_len);
 void mp_thread_gc_others(void);

+ 4 - 4
port/mpy_main.c

@@ -138,14 +138,14 @@ void mpy_main(const char *filename) {
         }
     }
 
-#if MICROPY_PY_THREAD
-    mp_thread_deinit();
-#endif
-
     gc_sweep_all();
 
     mp_deinit();
 
+#if MICROPY_PY_THREAD
+    mp_thread_deinit();
+#endif
+
     rt_free(heap);
 
     rtt_getchar_deinit();