//----------------------------------------------------------------------------- int tn_task_terminate(TN_TCB * task) { TN_INTSAVE_DATA int rc; /* see the structure purpose in tn_task_exit() */ struct // v.2.7 { #ifdef USE_MUTEXES CDLL_QUEUE * que; TN_MUTEX * mutex; #endif volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT]; }data; #if TN_CHECK_PARAM if(task == NULL) return TERR_WRONG_PARAM; if(task->id_task != TN_ID_TASK) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); //-------------------------------------------------- rc = TERR_NO_ERR; if(task->task_state == TSK_STATE_DORMANT || tn_curr_run_task == task) rc = TERR_WCONTEXT; //-- Cannot terminate running task else { if(task->task_state == TSK_STATE_RUNNABLE) task_to_non_runnable(task); else if(task->task_state & TSK_STATE_WAIT) { //-- Free all queues, involved in the 'waiting' queue_remove_entry(&(task->task_queue)); //----------------------------------------- if(task->tick_count != TN_WAIT_INFINITE) queue_remove_entry(&(task->timer_queue)); } //-- Unlock all mutexes, locked by the task #ifdef USE_MUTEXES while(!is_queue_empty(&(task->mutex_queue))) { data.que = queue_remove_head(&(task->mutex_queue)); data.mutex = get_mutex_by_mutex_queque(data.que); do_unlock_mutex(data.mutex); } #endif task_set_dormant_state(task); //-- Pointer to task top of the stack when not running task->task_stk = tn_stack_init(task->task_func_addr, task->stk_start, task->task_func_param); if(task->activate_count > 0) //-- Cannot terminate { task->activate_count--; task_to_runnable(task); tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } } tn_enable_interrupt(); return rc; }
//----------------------------------------------------------------------------- int tn_task_terminate(TN_TCB * task) { TN_INTSAVE_DATA int rc; unsigned int * ptr_stack; #ifdef USE_MUTEXES CDLL_QUEUE * que; TN_MUTEX * mutex; #endif volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT]; #if TN_CHECK_PARAM if(task == NULL) return TERR_WRONG_PARAM; if(task->id_task != TN_ID_TASK) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); //-- To use stack_exp[] and avoid warning message stack_exp[0] = (int)tn_system_state; ptr_stack =(unsigned int *)stack_exp[0]; //-------------------------------------------------- rc = TERR_NO_ERR; if(task->task_state == TSK_STATE_DORMANT || tn_curr_run_task == task) rc = TERR_WCONTEXT; //-- Cannot terminate running task else { if(task->task_state == TSK_STATE_RUNNABLE) task_to_non_runnable(task); else if(task->task_state & TSK_STATE_WAIT) { //-- Free all queues, involved in the 'waiting' queue_remove_entry(&(task->task_queue)); //----------------------------------------- if(task->tick_count != TN_WAIT_INFINITE) queue_remove_entry(&(task->timer_queue)); } #if (TN_SUPPORT_FPU == 2) if (tn_fpu_owner_task == task) { tn_fpu_owner_task = NULL; } #endif //-- Unlock all mutexes, locked by the task #ifdef USE_MUTEXES while(!is_queue_empty(&(task->mutex_queue))) { que = queue_remove_head(&(task->mutex_queue)); mutex = get_mutex_by_mutex_queque(que); do_unlock_mutex(mutex); } #endif task_set_dormant_state(task); ptr_stack = tn_stack_init(task->task_func_addr, task->stk_start, task->task_func_param); task->task_stk = ptr_stack; //-- Pointer to task top of the stack //-- when not running if(task->activate_count > 0) //-- Cannot terminate { task->activate_count--; task_to_runnable(task); tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void tn_task_exit(int attr) { /* The structure is used to force GCC compiler properly locate and use 'stack_exp' - thanks to Angelo R. Di Filippo */ struct // v.2.7 { #ifdef USE_MUTEXES CDLL_QUEUE * que; TN_MUTEX * mutex; #endif TN_TCB * task; volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT]; }data; TN_CHECK_NON_INT_CONTEXT_NORETVAL #ifdef TNKERNEL_PORT_MSP430X __disable_interrupt(); #else tn_cpu_save_sr(); //-- For ARM - disable interrupts without saving SPSR #endif //-------------------------------------------------- //-- Unlock all mutexes, locked by the task #ifdef USE_MUTEXES while(!is_queue_empty(&(tn_curr_run_task->mutex_queue))) { data.que = queue_remove_head(&(tn_curr_run_task->mutex_queue)); data.mutex = get_mutex_by_mutex_queque(data.que); do_unlock_mutex(data.mutex); } #endif data.task = tn_curr_run_task; task_to_non_runnable(tn_curr_run_task); task_set_dormant_state(data.task); //-- Pointer to task top of stack,when not running data.task->task_stk = tn_stack_init(data.task->task_func_addr, data.task->stk_start, data.task->task_func_param); if(data.task->activate_count > 0) //-- Cannot exit { data.task->activate_count--; task_to_runnable(data.task); } else // V 2.6 Thanks to Alex Borisov { if(attr == TN_EXIT_AND_DELETE_TASK) { queue_remove_entry(&(data.task->create_queue)); tn_created_tasks_qty--; data.task->id_task = 0; } } tn_switch_context_exit(); // interrupts will be enabled inside tn_switch_context_exit() }
//---------------------------------------------------------------------------- void tn_task_exit(int attr) { #ifdef USE_MUTEXES CDLL_QUEUE * que; TN_MUTEX * mutex; #endif TN_TCB * task; unsigned int * ptr_stack; volatile int stack_exp[TN_PORT_STACK_EXPAND_AT_EXIT]; TN_CHECK_NON_INT_CONTEXT_NORETVAL #ifdef TNKERNEL_PORT_MSP430X __disable_interrupt(); #else tn_cpu_save_sr(); //-- For ARM - disable interrupts without saving SPSR #endif //-- To use stack_exp[] and avoid warning message stack_exp[0] = (int)tn_system_state; ptr_stack =(unsigned int *)stack_exp[0]; //-------------------------------------------------- //-- Unlock all mutexes, locked by the task #ifdef USE_MUTEXES while(!is_queue_empty(&(tn_curr_run_task->mutex_queue))) { que = queue_remove_head(&(tn_curr_run_task->mutex_queue)); mutex = get_mutex_by_mutex_queque(que); do_unlock_mutex(mutex); } #endif task = tn_curr_run_task; task_to_non_runnable(tn_curr_run_task); task_set_dormant_state(task); ptr_stack = tn_stack_init(task->task_func_addr, task->stk_start, task->task_func_param); task->task_stk = ptr_stack; //-- Pointer to task top of stack,when not running if(task->activate_count > 0) //-- Cannot exit { task->activate_count--; task_to_runnable(task); } else // V 2.6 Thanks to Alex Borisov { if(attr == TN_EXIT_AND_DELETE_TASK) { queue_remove_entry(&(task->create_queue)); tn_created_tasks_qty--; task->id_task = 0; } } tn_switch_context_exit(); // interrupts will be enabled inside tn_switch_context_exit() }