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; if (*stack_size == 0) { *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size } else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) { *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size } // allocate TCB, stack and linked-list node (must be outside thread_mutex lock) StackType_t *stack = NULL; // thread_t *th = m_new_obj(thread_t); thread_t *th = (thread_t*)malloc(sizeof(thread_t)); mp_thread_mutex_lock(&thread_mutex, 1); // create thread TaskHandle_t thread_id; TaskStatus_t task_status; //todo add schedule processor xTaskCreateAtProcessor(0, // processor entry, // function entry name, //task name *stack_size / sizeof(StackType_t), //stack_deepth arg, //function arg priority, //task priority,please don't change this parameter,because it will impack function running &thread_id);//task handle //mp_printf(&mp_plat_print, "[MAIXPY]: thread_id %p created \n",thread_id); if (thread_id == NULL) { // m_del_obj(thread_t,th); free(th); mp_thread_mutex_unlock(&thread_mutex); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); } vTaskGetInfo(thread_id,&task_status,(BaseType_t)pdTRUE,(eTaskState)eInvalid); stack = task_status.pxStackBase; // adjust the stack_size to provide room to recover from hitting the limit *stack_size -= 1024; // add thread to linked list of all threads th->id = thread_id; th->ready = 0; th->arg = arg; th->stack = stack; //stack_len may be a bug,because that k210 addr width is 64 bit ,but addr width is 32bit //the StackType_t type is a type of the uintprt_t,uintprt_t in k210 is 64bit th->stack_len = *stack_size / sizeof(StackType_t); th->next = thread; thread = th; mp_thread_mutex_unlock(&thread_mutex); }
STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); // TODO check if already unlocked self->locked = false; MP_THREAD_GIL_EXIT(); mp_thread_mutex_unlock(&self->mutex); MP_THREAD_GIL_ENTER(); return mp_const_none; }
STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); // TODO check if already unlocked self->locked = false; #if !MICROPY_PY_THREAD_GIL mp_thread_mutex_unlock(&self->mutex); #endif return mp_const_none; }
void mp_thread_start(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 1; break; } } mp_thread_mutex_unlock(&thread_mutex); }
STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); if (!self->locked) { mp_raise_msg(&mp_type_RuntimeError, NULL); } self->locked = false; MP_THREAD_GIL_EXIT(); mp_thread_mutex_unlock(&self->mutex); MP_THREAD_GIL_ENTER(); return mp_const_none; }
void mp_thread_finish(void) { mp_thread_mutex_lock(&thread_mutex, 1); // TODO unlink from list for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 0; break; } } mp_thread_mutex_unlock(&thread_mutex); }
int mp_thread_gc_others(void) { /* mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { gc_collect_root((void**)&th, 1); gc_collect_root(&th->arg, 1); // probably not needed if (th->id == xTaskGetCurrentTaskHandle()) { continue; } if (!th->ready) { continue; } gc_collect_root(th->stack, th->stack_len); // probably not needed } mp_thread_mutex_unlock(&thread_mutex); */ int n_th = 0; void **ptrs; mp_state_thread_t *state; mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (!th->ready) continue; // thread not ready //if (th->type == THREAD_TYPE_SERVICE) continue; // Only scan PYTHON threads if (th->id == xTaskGetCurrentTaskHandle()) continue; // Do not process the running thread //state = (mp_state_thread_t *)th->state_thread; n_th++; // Mark the root pointers on thread //gc_collect_root((void **)state->dict_locals, 1); if (th->arg) { // Mark the pointers on thread arguments ptrs = (void**)(void*)&th->arg; gc_collect_root(ptrs, 1); } #if MICROPY_ENABLE_PYSTACK // Mark the pointers on thread pystack //ptrs = (void**)(void*)state->pystack_start; //gc_collect_root(ptrs, (state->pystack_cur - state->pystack_start) / sizeof(void*)); #endif // If PyStack is used, no pointers to MPy heap are placed on tasks stack #if !MICROPY_ENABLE_PYSTACK // Mark the pointers on thread stack //gc_collect_root(th->curr_sp, ((void *)state->stack_top - th->curr_sp) / sizeof(void*)); // probably not needed #endif } mp_thread_mutex_unlock(&thread_mutex); return n_th; }
void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { // store thread entry function into a global variable so we can access it ext_thread_entry = entry; if (*stack_size == 0) { *stack_size = 4096; // default stack size } else if (*stack_size < 2048) { *stack_size = 2048; // minimum stack size } // allocate TCB, stack and linked-list node (must be outside thread_mutex lock) StaticTask_t *tcb = m_new(StaticTask_t, 1); StackType_t *stack = m_new(StackType_t, *stack_size / sizeof(StackType_t)); thread_t *th = m_new_obj(thread_t); mp_thread_mutex_lock(&thread_mutex, 1); // create thread TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", *stack_size / sizeof(void*), arg, 2, stack, tcb); if (id == NULL) { mp_thread_mutex_unlock(&thread_mutex); mp_raise_msg(&mp_type_OSError, "can't create thread"); } // add thread to linked list of all threads th->id = id; th->ready = 0; th->arg = arg; th->stack = stack; th->stack_len = *stack_size / sizeof(StackType_t); th->next = thread; thread = th; mp_thread_mutex_unlock(&thread_mutex); // adjust stack_size to provide room to recover from hitting the limit *stack_size -= 512; }
void mp_thread_finish(void) { mp_thread_mutex_lock(&thread_mutex, 1); thread_t *th = thread; thread_t *pre_th = NULL; for (th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { th->ready = 0; //mp_thread_delete(pre_th,th);//TODO:wether need to delete threand to free memory break; } pre_th = th; } mp_thread_mutex_unlock(&thread_mutex); }
void mp_thread_gc_others(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { gc_collect_root((void**)&th, 1); gc_collect_root(&th->arg, 1); // probably not needed if (th->id == xTaskGetCurrentTaskHandle()) { continue; } if (!th->ready) { continue; } gc_collect_root(th->stack, th->stack_len); // probably not needed } mp_thread_mutex_unlock(&thread_mutex); }
void mp_thread_deinit(void) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { // don't delete the current task if (th->id == xTaskGetCurrentTaskHandle()) { continue; } vTaskDelete(th->id); // m_del_obj(thread_t,th); free(th); } mp_thread_mutex_unlock(&thread_mutex); // allow FreeRTOS to clean-up the threads vTaskDelay(2); }