/** * * @param attr */ void tnec_task_exit (TN_UWORD attr) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_TCB_S *task; CDLL_QUEUE_S *que; TN_MUTEX_S *mutex; TN_UWORD *ptr_stack; if (tn_is_non_task_context()) return; tn_save_sr(); /* just for PIC24/dsPIC */ tn_disable_interrupt(); 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_queue(que); do_unlock_mutex(mutex); } 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->stk_size, task->task_func_param ); task->task_stk = ptr_stack; if (task->activate_count > 0) { task->activate_count--; task_to_runnable(task); } else { /* Alex B. - delete task only if activate counter = 0 ! */ if (attr == TN_EXIT_AND_DELETE_TASK) { queue_remove_entry(&(task->create_queue)); tn_created_tasks_qty--; task->id_task = TN_ID_UNKNOWN; } } tn_switch_context_exit(tn_save_status_reg); /* Exit from task with restore saved SR*/ }
//----------------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------------- //---------------------------------------------------------------------------- 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() }
//----------------------------------------------------------------------------- int tn_task_create(TN_TCB * task, //-- task TCB void (*task_func)(void *param), //-- task function int priority, //-- task priority unsigned int * task_stack_start, //-- task stack first addr in memory (bottom) int task_stack_size, //-- task stack size (in sizeof(void*),not bytes) void * param, //-- task function parameter int option) //-- Creation option { TN_INTSAVE_DATA int rc; unsigned int * ptr_stack; int i; //-- Light weight checking of system tasks recreation if((priority == 0 && ((option & TN_TASK_TIMER) == 0)) || (priority == TN_NUM_PRIORITY-1 && (option & TN_TASK_IDLE) == 0)) return TERR_WRONG_PARAM; if((priority < 0 || priority > TN_NUM_PRIORITY-1) || task_stack_size < TN_MIN_STACK_SIZE || task_func == NULL || task == NULL || task_stack_start == NULL || task->id_task != 0) //-- recreation return TERR_WRONG_PARAM; rc = TERR_NO_ERR; TN_CHECK_NON_INT_CONTEXT if(tn_system_state == TN_ST_STATE_RUNNING) tn_disable_interrupt(); //--- Init task TCB task->task_func_addr = (void*)task_func; task->task_func_param = param; task->stk_start = (unsigned int*)task_stack_start; //-- Base address of task stack space task->stk_size = task_stack_size; //-- Task stack size (in bytes) task->base_priority = priority; //-- Task base priority task->activate_count = 0; //-- Activation request count task->id_task = TN_ID_TASK; //-- Fill all task stack space by TN_FILL_STACK_VAL - only inside create_task for(ptr_stack = task->stk_start,i = 0;i < task->stk_size; i++) *ptr_stack-- = TN_FILL_STACK_VAL; task_set_dormant_state(task); //--- Init task stack 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 //-- Add task to created task queue queue_add_tail(&tn_create_queue,&(task->create_queue)); tn_created_tasks_qty++; if((option & TN_TASK_START_ON_CREATION) != 0) task_to_runnable(task); if(tn_system_state == TN_ST_STATE_RUNNING) 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) { #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() }
/** * * @param task * * @return TN_RETVAL */ TN_RETVAL tnnc_task_terminate (TN_TCB_S *task) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_RETVAL rc; TN_UWORD *ptr_stack; CDLL_QUEUE_S *que; TN_MUTEX_S *mutex; /* Not check parameter error if (task == TN_NULL) return TERR_WRONG_PARAM; */ if (task->id_task != TN_ID_TASK) return TERR_NOEXS; if (tn_is_non_task_context()) { return TERR_WCONTEXT; } tn_disable_interrupt(); rc = TERR_NO_ERR; if ((task->task_state == TSK_STATE_DORMANT) || (tn_curr_run_task == task)) { rc = TERR_WCONTEXT; } else { if (task->task_state == TSK_STATE_RUNNABLE) { task_to_non_runnable(task); } else if (task->task_state & TSK_STATE_WAIT) { queue_remove_entry(&(task->task_queue)); if (queue_contains_entry(&tn_blocked_tasks_list, &(task->block_queue))) { queue_remove_entry(&(task->block_queue)); } if (task->tick_count != TN_WAIT_INFINITE) { queue_remove_entry(&(task->timer_queue)); } } while (!is_queue_empty(&(task->mutex_queue))) { que = queue_remove_head(&(task->mutex_queue)); mutex = get_mutex_by_mutex_queue(que); do_unlock_mutex(mutex); } task_set_dormant_state(task); ptr_stack = tn_stack_init(task->task_func_addr, task->stk_start, task->stk_size, task->task_func_param ); task->task_stk = ptr_stack; if (task->activate_count > 0) { task->activate_count--; task_to_runnable(task); tn_enable_interrupt(); if ((tn_next_task_to_run != tn_curr_run_task) && (tn_enable_switch_context != TN_FALSE)) { tn_switch_context(); } return TERR_NO_ERR; } } tn_enable_interrupt(); return rc; }