//---------------------------------------------------------------------------- void task_curr_to_wait_action(CDLL_QUEUE * wait_que, int wait_reason, unsigned long timeout) { task_to_non_runnable(tn_curr_run_task); tn_curr_run_task->task_state = TSK_STATE_WAIT; tn_curr_run_task->task_wait_reason = wait_reason; tn_curr_run_task->tick_count = timeout; //--- Add to the wait queue - FIFO if(wait_que == NULL) //-- Thanks to Vavilov D.O. { queue_reset(&(tn_curr_run_task->task_queue)); } else { queue_add_tail(wait_que, &(tn_curr_run_task->task_queue)); tn_curr_run_task->pwait_queue = wait_que; } //--- Add to the timers queue if(timeout != TN_WAIT_INFINITE) queue_add_tail(&tn_wait_timeout_list, &(tn_curr_run_task->timer_queue)); }
/** * * @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*/ }
//---------------------------------------------------------------------------- // If the task is runnable, it is moved to the SUSPENDED state. If the task // is in the WAITING state, it is moved to the WAITINGSUSPENDED state. //---------------------------------------------------------------------------- int tn_task_suspend(TN_TCB * task) { TN_INTSAVE_DATA int rc; #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(); if(task->task_state & TSK_STATE_SUSPEND) rc = TERR_OVERFLOW; else { if(task->task_state == TSK_STATE_DORMANT) rc = TERR_WSTATE; else { if(task->task_state == TSK_STATE_RUNNABLE) { task->task_state = TSK_STATE_SUSPEND; task_to_non_runnable(task); tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } else { task->task_state |= TSK_STATE_SUSPEND; rc = TERR_NO_ERR; } } } tn_enable_interrupt(); return rc; }
/** * * @param task * * @return TN_RETVAL */ TN_RETVAL tnec_task_suspend (TN_TCB_S *task) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_RETVAL rc; 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(); if (task->task_state & TSK_STATE_SUSPEND) { rc = TERR_OVERFLOW; } else { if (task->task_state == TSK_STATE_DORMANT) { rc = TERR_WSTATE; } else { if (task == tn_curr_run_task && !(tn_enable_switch_context) ) { rc = TERR_WCONTEXT; } else { if (task->task_state == TSK_STATE_RUNNABLE) { task->task_state = TSK_STATE_SUSPEND; task_to_non_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; } else { task->task_state |= TSK_STATE_SUSPEND; rc = TERR_NO_ERR; } } } } tn_enable_interrupt(); return rc; }
//----------------------------------------------------------------------------- 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_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; }