//---------------------------------------------------------------------------- int tn_fmem_release(TN_FMP * fmp,void * p_data) { TN_INTSAVE_DATA CDLL_QUEUE * que; TN_TCB * task; #if TN_CHECK_PARAM if(fmp == NULL || p_data == NULL) return TERR_WRONG_PARAM; if(fmp->id_fmp != TN_ID_FSMEMORYPOOL) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); if(!is_queue_empty(&(fmp->wait_queue))) { que = queue_remove_head(&(fmp->wait_queue)); task = get_task_by_tsk_queue(que); task->data_elem = p_data; if(task_wait_complete(task)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } } else fm_put(fmp,p_data); tn_enable_interrupt(); return TERR_NO_ERR; }
//---------------------------------------------------------------------------- int tn_fmem_delete(TN_FMP * fmp) { TN_INTSAVE_DATA CDLL_QUEUE * que; TN_TCB * task; #if TN_CHECK_PARAM if(fmp == NULL) return TERR_WRONG_PARAM; if(fmp->id_fmp != TN_ID_FSMEMORYPOOL) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT while(!is_queue_empty(&(fmp->wait_queue))) { tn_disable_interrupt(); //--- delete from sem wait queue que = queue_remove_head(&(fmp->wait_queue)); task = get_task_by_tsk_queue(que); if(task_wait_complete(task)) { task->task_wait_rc = TERR_DLT; tn_enable_interrupt(); tn_switch_context(); } } if(tn_chk_irq_disabled() == 0) tn_disable_interrupt(); fmp->id_fmp = 0; //-- Fixed-size memory pool not exists now tn_enable_interrupt(); return TERR_NO_ERR; }
//---------------------------------------------------------------------------- int tn_sem_delete(TN_SEM * sem) { TN_INTSAVE_DATA CDLL_QUEUE * que; TN_TCB * task; #if TN_CHECK_PARAM if(sem == NULL) return TERR_WRONG_PARAM; if(sem->id_sem != TN_ID_SEMAPHORE) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT while(!is_queue_empty(&(sem->wait_queue))) { tn_disable_interrupt(); //--- delete from the sem wait queue que = queue_remove_head(&(sem->wait_queue)); task = get_task_by_tsk_queue(que); if(task_wait_complete(task)) { task->task_wait_rc = TERR_DLT; tn_enable_interrupt(); tn_switch_context(); } } if(tn_chk_irq_disabled() == 0) // int enable tn_disable_interrupt(); sem->id_sem = 0; // Semaphore not exists now tn_enable_interrupt(); return TERR_NO_ERR; }
//---------------------------------------------------------------------------- static void tn_timer_task_func(void * par) { TN_INTSAVE_DATA volatile TN_TCB * task; volatile CDLL_QUEUE * curr_que; //-- User application init - user's objects initial (tasks etc.) creation tn_app_init(); //-- Enable interrupt here ( include tick int) tn_cpu_int_enable(); //------------------------------------------------------------------------- for(;;) { //------------ OS timer tick ------------------------------------- tn_disable_interrupt(); curr_que = tn_wait_timeout_list.next; while(curr_que != &tn_wait_timeout_list) { task = get_task_by_timer_queque((CDLL_QUEUE*)curr_que); if(task->tick_count != TN_WAIT_INFINITE) { if(task->tick_count > 0) { task->tick_count--; if(task->tick_count == 0) //-- Time out expiried { queue_remove_entry(&(((TN_TCB*)task)->task_queue)); task_wait_complete((TN_TCB*)task); task->task_wait_rc = TERR_TIMEOUT; } } } curr_que = curr_que->next; } task_curr_to_wait_action(NULL, TSK_WAIT_REASON_SLEEP, TN_WAIT_INFINITE); tn_enable_interrupt(); tn_switch_context(); } }
//---------------------------------------------------------------------------- int tn_task_resume(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_WSTATE; else { if(!(task->task_state & TSK_STATE_WAIT)) //- The task is not in the WAIT-SUSPEND state { task_to_runnable(task); tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } else //-- Just remove TSK_STATE_SUSPEND from the task state { task->task_state &= ~TSK_STATE_SUSPEND; rc = TERR_NO_ERR; } } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_task_activate(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_DORMANT) { task_to_runnable(task); tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } else { if(task->activate_count == 0) { task->activate_count++; rc = TERR_NO_ERR; } else rc = TERR_OVERFLOW; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_event_wait_polling(TN_EVENT * evf, unsigned int wait_pattern, int wait_mode, unsigned int * p_flags_pattern) { TN_INTSAVE_DATA int rc; int fCond; #if TN_CHECK_PARAM if(evf == NULL || wait_pattern == 0 || p_flags_pattern == NULL) return TERR_WRONG_PARAM; if(evf->id_event != TN_ID_EVENT) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); //-- If event attr is TN_EVENT_ATTR_SINGLE and another task already //-- in event wait queue - return ERROR without checking release condition if((evf->attr & TN_EVENT_ATTR_SINGLE) && !is_queue_empty(&(evf->wait_queue))) { rc = TERR_ILUSE; } else { //-- Check release condition if(wait_mode & TN_EVENT_WCOND_OR) //-- any setted bit is enough for release condition fCond = ((evf->pattern & wait_pattern) != 0); else //-- TN_EVENT_WCOND_AND is default mode fCond = ((evf->pattern & wait_pattern) == wait_pattern); if(fCond) { *p_flags_pattern = evf->pattern; if(evf->attr & TN_EVENT_ATTR_CLR) evf->pattern = 0; rc = TERR_NO_ERR; } else rc = TERR_TIMEOUT; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_event_delete(TN_EVENT * evf) { TN_INTSAVE_DATA CDLL_QUEUE * que; TN_TCB * task; #if TN_CHECK_PARAM if(evf == NULL) return TERR_WRONG_PARAM; if(evf->id_event != TN_ID_EVENT) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); // v.2.7 - thanks to Eugene Scopal while(!is_queue_empty(&(evf->wait_queue))) { //--- delete from sem wait queue que = queue_remove_head(&(evf->wait_queue)); task = get_task_by_tsk_queue(que); if(task_wait_complete(task)) { task->task_wait_rc = TERR_DLT; tn_enable_interrupt(); tn_switch_context(); tn_disable_interrupt(); // v.2.7 } } evf->id_event = 0; // Event not exists now tn_enable_interrupt(); return TERR_NO_ERR; }
//---------------------------------------------------------------------------- int tn_event_delete(TN_EVENT * evf) { TN_INTSAVE_DATA CDLL_QUEUE * que; TN_TCB * task; if(evf == NULL) return TERR_WRONG_PARAM; if(evf->id_event != TN_ID_EVENT) return TERR_NOEXS; TN_CHECK_NON_INT_CONTEXT while(!is_queue_empty(&(evf->wait_queue))) { if(tn_chk_irq_disabled() == 0) // int enable tn_disable_interrupt(); //--- delete from sem wait queue que = queue_remove_head(&(evf->wait_queue)); task = get_task_by_tsk_queue(que); if(task_wait_complete(task,FALSE)) { task->task_wait_rc = TERR_DLT; tn_enable_interrupt(); tn_switch_context(); } } if(tn_chk_irq_disabled() == 0) // int enable tn_disable_interrupt(); evf->id_event = 0; // Event not exists now tn_enable_interrupt(); return TERR_NO_ERR; }
//---------------------------------------------------------------------------- int tn_task_release_wait(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_WAIT) == 0) { rc = TERR_WCONTEXT; } else { queue_remove_entry(&(task->task_queue)); if(task_wait_complete(task)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } rc = TERR_NO_ERR; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_fmem_get(TN_FMP * fmp,void ** p_data,unsigned int timeout) { TN_INTSAVE_DATA int rc; //-- return code void * ptr; if(fmp == NULL || p_data == NULL || timeout == 0) return TERR_WRONG_PARAM; if(fmp->id_fmp != TN_ID_FSMEMORYPOOL) return TERR_NOEXS; TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); ptr = fm_get(fmp); if(ptr != NULL) //-- Get memory { *p_data = ptr; rc = TERR_NO_ERR; } else { task_curr_to_wait_action(&(fmp->wait_queue), TSK_WAIT_REASON_WFIXMEM,timeout); tn_enable_interrupt(); tn_switch_context(); //-- When return to this point,in data_elem have to be valid value *p_data = tn_curr_run_task->data_elem; //-- Return to caller return tn_curr_run_task->task_wait_rc; // return TERR_NO_ERR; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- // Acquire Semaphore Resource //---------------------------------------------------------------------------- int tn_sem_acquire(TN_SEM * sem, unsigned long timeout) { TN_INTSAVE_DATA int rc; //-- return code #if TN_CHECK_PARAM if(sem == NULL || timeout == 0) return TERR_WRONG_PARAM; if(sem->max_count == 0) return TERR_WRONG_PARAM; if(sem->id_sem != TN_ID_SEMAPHORE) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); if(sem->count >= 1) { sem->count--; rc = TERR_NO_ERR; } else { task_curr_to_wait_action(&(sem->wait_queue), TSK_WAIT_REASON_SEM, timeout); tn_enable_interrupt(); tn_switch_context(); return tn_curr_run_task->task_wait_rc; } tn_enable_interrupt(); return rc; }
S32 pushToCirBuf(CIR_BUFFER *circular_buf, U8 *buffer, U32 size ) { S32 retval=0; U32 i; U32 BufSize=0; TN_INTSAVE_DATA tn_disable_interrupt(); if ( circular_buf != NULL ) { BufSize = getCirBufAvailableSize (circular_buf); if (BufSize >= size) { for(i=0; i<size ; i++) { circular_buf->Buffer[ circular_buf->writePos ] = buffer [i] ; if( circular_buf->writePos+1 == circular_buf->size ) { circular_buf->overflow = 1 ; circular_buf->writePos = 0 ; } else { circular_buf->writePos ++ ; } } retval = size; } else if(BufSize < size ) { retval = BufSize; } } else { retval = -1; } tn_enable_interrupt(); return retval; }
/** * * @param fmp * @param p_data * * @return TN_RETVAL */ TN_RETVAL tnnc_fmem_get_polling (TN_FMP_S *fmp, void **p_data) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_RETVAL rc; void *ptr; /* Not check parameter error if (fmp == TN_NULL || p_data == TN_NULL) return TERR_WRONG_PARAM; */ if (fmp->id_fmp != TN_ID_FSMEMORYPOOL) return TERR_NOEXS; if (tn_is_non_task_context()) { return TERR_WCONTEXT; } tn_disable_interrupt(); ptr = fm_get(fmp); if (ptr != TN_NULL) { /* Get memory */ *p_data = ptr; rc = TERR_NO_ERR; } else { rc = TERR_TIMEOUT; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_queue_receive_polling(TN_DQUE * dque,void ** data_ptr) { TN_INTSAVE_DATA int rc; CDLL_QUEUE * que; TN_TCB * task; #if TN_CHECK_PARAM if(dque == NULL || data_ptr == NULL) return TERR_WRONG_PARAM; if(dque->id_dque != TN_ID_DATAQUEUE) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); rc = dque_fifo_read(dque,data_ptr); if(rc == TERR_NO_ERR) //-- There was entry(s) in data queue { if(!is_queue_empty(&(dque->wait_send_list))) { que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); dque_fifo_write(dque,task->data_elem); //-- Put to data FIFO if(task_wait_complete(task)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } } } else //-- data FIFO is empty { if(!is_queue_empty(&(dque->wait_send_list))) { que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); *data_ptr = task->data_elem; //-- Return to caller if(task_wait_complete(task)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } rc = TERR_NO_ERR; } else //-- wait_send_list is empty rc = TERR_TIMEOUT; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_queue_receive(TN_DQUE * dque,void ** data_ptr,unsigned long timeout) { TN_INTSAVE_DATA int rc; //-- return code CDLL_QUEUE * que; TN_TCB * task; #if TN_CHECK_PARAM if(dque == NULL || timeout == 0 || data_ptr == NULL) return TERR_WRONG_PARAM; if(dque->id_dque != TN_ID_DATAQUEUE) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); rc = dque_fifo_read(dque,data_ptr); if(rc == TERR_NO_ERR) //-- There was entry(s) in data queue { if(!is_queue_empty(&(dque->wait_send_list))) { que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); dque_fifo_write(dque,task->data_elem); //-- Put to data FIFO if(task_wait_complete(task)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } } } else //-- data FIFO is empty { if(!is_queue_empty(&(dque->wait_send_list))) { que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); *data_ptr = task->data_elem; //-- Return to caller if(task_wait_complete(task)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } rc = TERR_NO_ERR; } else //-- wait_send_list is empty { task_curr_to_wait_action(&(dque->wait_receive_list), TSK_WAIT_REASON_DQUE_WRECEIVE,timeout); tn_enable_interrupt(); tn_switch_context(); //-- When returns to this point, in the data_elem have to be valid value *data_ptr = tn_curr_run_task->data_elem; //-- Return to caller return tn_curr_run_task->task_wait_rc; } } 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; }
//----------------------------------------------------------------------------- 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; }
/** * * @param dque * * @return TN_RETVAL */ TN_RETVAL tnnc_queue_delete (TN_DQUE_S *dque) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ CDLL_QUEUE_S *que; TN_TCB_S *task; /* Not check parameter error if (dque == TN_NULL) return TERR_WRONG_PARAM; */ if (dque->id_dque != TN_ID_DATAQUEUE) return TERR_NOEXS; if (tn_is_non_task_context()) { return TERR_WCONTEXT; } while (!is_queue_empty(&(dque->wait_send_list))) { /* if (tn_chk_irq_disabled() == 0) { tn_disable_interrupt(); } */ tn_disable_interrupt(); que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); if (task_wait_complete(task, TN_FALSE)) { task->task_wait_rc = TERR_DLT; tn_enable_interrupt(); tn_switch_context(); } } while (!is_queue_empty(&(dque->wait_receive_list))) { /* if (tn_chk_irq_disabled() == 0) { tn_disable_interrupt(); } */ tn_disable_interrupt(); que = queue_remove_head(&(dque->wait_receive_list)); task = get_task_by_tsk_queue(que); if (task_wait_complete(task, TN_FALSE)) { task->task_wait_rc = TERR_DLT; tn_enable_interrupt(); tn_switch_context(); } } /* if (tn_chk_irq_disabled() == 0) { tn_disable_interrupt(); } */ tn_disable_interrupt(); dque->id_dque = TN_ID_UNKNOWN; tn_enable_interrupt(); return TERR_NO_ERR; }
//----------------------------------------------------------------------------- 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; }
/** * * @param mutex * @param timeout * * @return TN_RETVAL */ TN_RETVAL tnec_mutex_lock (TN_MUTEX_S *mutex, TN_TIMEOUT timeout) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_TCB_S *blk_task; TN_RETVAL rc; if (mutex == TN_NULL || timeout == 0) return TERR_WRONG_PARAM; if (mutex->id_mutex != TN_ID_MUTEX) return TERR_NOEXS; if (tn_is_non_task_context()) { return TERR_WCONTEXT; } tn_disable_interrupt(); rc = TERR_NO_ERR; for (;;) { if (tn_curr_run_task == mutex->holder) { rc = TERR_ILUSE; break; } if (mutex->attr == TN_MUTEX_ATTR_CEILING && tn_curr_run_task->base_priority < mutex->ceil_priority) { rc = TERR_ILUSE; break; } if (mutex->attr == TN_MUTEX_ATTR_CEILING) { if (mutex->holder == TN_NULL) { if (enable_lock_mutex(tn_curr_run_task, &blk_task)) { mutex->holder = tn_curr_run_task; tn_curr_run_task->blk_task = TN_NULL; queue_add_tail(&(tn_curr_run_task->mutex_queue), &(mutex->mutex_queue)); queue_add_tail(&tn_locked_mutexes_list, &(mutex->lock_mutex_queue)); } else { /* Невозможно заблокировать мютекс Протокол наследования: Если текущий приоритет выполняемой задачи больше приоритета задачи, которая блокирует текущую (удерживает мютекс), то блокирующая задача наследует приоритет текущей */ if (blk_task != TN_NULL) { if (tn_curr_run_task->priority < blk_task->priority) { set_current_priority(blk_task, tn_curr_run_task->priority); } } queue_add_tail(&tn_blocked_tasks_list, &(tn_curr_run_task->block_queue)); tn_curr_run_task->blk_task = blk_task; task_curr_to_wait_action(&(mutex->wait_queue), TSK_WAIT_REASON_MUTEX_C_BLK, timeout); tn_enable_interrupt(); tn_switch_context(); return tn_curr_run_task->task_wait_rc; } } else { if (tn_curr_run_task->priority < mutex->holder->priority) { set_current_priority(mutex->holder,tn_curr_run_task->priority); } task_curr_to_wait_action(&(mutex->wait_queue), TSK_WAIT_REASON_MUTEX_C, timeout); tn_enable_interrupt(); tn_switch_context(); return tn_curr_run_task->task_wait_rc; } } else if (mutex->attr == TN_MUTEX_ATTR_INHERIT) { if (mutex->holder == TN_NULL) { mutex->holder = tn_curr_run_task; queue_add_tail(&(tn_curr_run_task->mutex_queue),&(mutex->mutex_queue)); /* --- v.2.3 */ queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue)); /* --- */ rc = TERR_NO_ERR; } else { if (tn_curr_run_task->priority < mutex->holder->priority) { set_current_priority(mutex->holder, tn_curr_run_task->priority); } task_curr_to_wait_action(&(mutex->wait_queue), TSK_WAIT_REASON_MUTEX_I,timeout); tn_enable_interrupt(); tn_switch_context(); return tn_curr_run_task->task_wait_rc; } } break; } tn_enable_interrupt(); return rc; }
//---------------------------------------------------------------------------- int tn_event_wait(TN_EVENT * evf, unsigned int wait_pattern, int wait_mode, unsigned int * p_flags_pattern, unsigned long timeout) { TN_INTSAVE_DATA int rc; int fCond; #if TN_CHECK_PARAM if(evf == NULL || wait_pattern == 0 || p_flags_pattern == NULL || timeout == 0) return TERR_WRONG_PARAM; if(evf->id_event != TN_ID_EVENT) return TERR_NOEXS; #endif TN_CHECK_NON_INT_CONTEXT tn_disable_interrupt(); //-- If event attr is TN_EVENT_ATTR_SINGLE and another task already //-- in event wait queue - return ERROR without checking release condition if((evf->attr & TN_EVENT_ATTR_SINGLE) && !is_queue_empty(&(evf->wait_queue))) { rc = TERR_ILUSE; } else { //-- Check release condition if(wait_mode & TN_EVENT_WCOND_OR) //-- any setted bit is enough for release condition fCond = ((evf->pattern & wait_pattern) != 0); else //-- TN_EVENT_WCOND_AND is default mode fCond = ((evf->pattern & wait_pattern) == wait_pattern); if(fCond) { *p_flags_pattern = evf->pattern; if(evf->attr & TN_EVENT_ATTR_CLR) evf->pattern = 0; rc = TERR_NO_ERR; } else { tn_curr_run_task->ewait_mode = wait_mode; tn_curr_run_task->ewait_pattern = wait_pattern; task_curr_to_wait_action(&(evf->wait_queue), TSK_WAIT_REASON_EVENT, timeout); tn_enable_interrupt(); tn_switch_context(); if(tn_curr_run_task->task_wait_rc == TERR_NO_ERR) *p_flags_pattern = tn_curr_run_task->ewait_pattern; return tn_curr_run_task->task_wait_rc; } } tn_enable_interrupt(); return rc; }
/** * * @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; }
/** * * @param mutex * * @return TN_RETVAL */ TN_RETVAL tnec_mutex_lock_polling (TN_MUTEX_S *mutex) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_RETVAL rc; if (mutex == TN_NULL) return TERR_WRONG_PARAM; if (mutex->id_mutex != TN_ID_MUTEX) return TERR_NOEXS; if (tn_is_non_task_context()) { return TERR_WCONTEXT; } tn_disable_interrupt(); rc = TERR_NO_ERR; for (;;) { if (tn_curr_run_task == mutex->holder) { rc = TERR_ILUSE; break; } if (mutex->attr == TN_MUTEX_ATTR_CEILING && tn_curr_run_task->base_priority < mutex->ceil_priority ) { rc = TERR_ILUSE; break; } if (mutex->holder == TN_NULL) { if (mutex->attr == TN_MUTEX_ATTR_CEILING) { if (enable_lock_mutex(tn_curr_run_task, TN_NULL)) { mutex->holder = tn_curr_run_task; tn_curr_run_task->blk_task = TN_NULL; queue_add_tail(&(tn_curr_run_task->mutex_queue),&(mutex->mutex_queue)); queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue)); } else { rc = TERR_TIMEOUT; } } else if (mutex->attr == TN_MUTEX_ATTR_INHERIT) { mutex->holder = tn_curr_run_task; queue_add_tail(&(tn_curr_run_task->mutex_queue),&(mutex->mutex_queue)); /* --- v.2.3 */ queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue)); /* --- */ } } else { rc = TERR_TIMEOUT; } break; } 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; }
/** * * @param dque * @param data_ptr * @param timeout * * @return TN_RETVAL */ TN_RETVAL tnnc_queue_receive (TN_DQUE_S * dque, void **data_ptr, TN_TIMEOUT timeout) { TN_UWORD tn_save_status_reg TN_UNUSED; /* for SR save */ TN_RETVAL rc; CDLL_QUEUE_S *que; TN_TCB_S *task; /* Not check parameter error if (dque == TN_NULL || timeout == 0 || data_ptr == TN_NULL) return TERR_WRONG_PARAM; */ if (dque->id_dque != TN_ID_DATAQUEUE) return TERR_NOEXS; if (tn_is_non_task_context()) { return TERR_WCONTEXT; } tn_disable_interrupt(); rc = dque_fifo_read(dque,data_ptr); if (rc == TERR_NO_ERR) { if (!is_queue_empty(&(dque->wait_send_list))) { que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); dque_fifo_write(dque,task->data_elem); if (task_wait_complete(task, TN_FALSE)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } } } else { if (!is_queue_empty(&(dque->wait_send_list))) { que = queue_remove_head(&(dque->wait_send_list)); task = get_task_by_tsk_queue(que); *data_ptr = task->data_elem; if (task_wait_complete(task, TN_FALSE)) { tn_enable_interrupt(); tn_switch_context(); return TERR_NO_ERR; } rc = TERR_NO_ERR; } else { task_curr_to_wait_action(&(dque->wait_receive_list), TSK_WAIT_REASON_DQUE_WRECEIVE, timeout); tn_enable_interrupt(); tn_switch_context(); /* When return to this point,in data_elem have to be valid value */ *data_ptr = tn_curr_run_task->data_elem; return tn_curr_run_task->task_wait_rc; } } tn_enable_interrupt(); return rc; }