//---------------------------------------------------------------------------- int task_wait_complete(TN_TCB * task) //-- v. 2.6 { #ifdef USE_MUTEXES int fmutex; int curr_priority; TN_MUTEX * mutex; TN_TCB * mt_holder_task; CDLL_QUEUE * t_que; #endif int rc = FALSE; if(task == NULL) return 0; #ifdef USE_MUTEXES t_que = NULL; if(task->task_wait_reason == TSK_WAIT_REASON_MUTEX_I || task->task_wait_reason == TSK_WAIT_REASON_MUTEX_C) { fmutex = TRUE; t_que = task->pwait_queue; } else fmutex = FALSE; #endif task->pwait_queue = NULL; task->task_wait_rc = TERR_NO_ERR; if(task->tick_count != TN_WAIT_INFINITE) queue_remove_entry(&(task->timer_queue)); task->tick_count = TN_WAIT_INFINITE; if(!(task->task_state & TSK_STATE_SUSPEND)) { task_to_runnable(task); rc = TRUE; } else //-- remove WAIT state task->task_state = TSK_STATE_SUSPEND; #ifdef USE_MUTEXES if(fmutex) { mutex = get_mutex_by_wait_queque(t_que); mt_holder_task = mutex->holder; if(mt_holder_task != NULL) { //-- if task was blocked by another task and its pri was changed //-- - recalc current priority if(mt_holder_task->priority != mt_holder_task->base_priority && mt_holder_task->priority == task->priority) { curr_priority = find_max_blocked_priority(mutex, mt_holder_task->base_priority); set_current_priority(mt_holder_task, curr_priority); rc = TRUE; } } } #endif task->task_wait_reason = 0; //-- Clear wait reason return rc; }
/** * * @param mutex * * @return TN_BOOL */ TN_BOOL do_unlock_mutex (TN_MUTEX_S *mutex) { CDLL_QUEUE_S *curr_que; TN_MUTEX_S *tmp_mutex; TN_TCB_S *task; TN_TCB_S *hi_pri_task = TN_NULL; TN_TCB_S *blk_task; TN_TCB_S *tmp_task; TN_UWORD priority; TN_UWORD pr; TN_BOOL need_switch_context = TN_FALSE; queue_remove_entry(&(mutex->mutex_queue)); queue_remove_entry(&(mutex->lock_mutex_queue)); if (is_queue_empty(&(tn_curr_run_task->mutex_queue))) { need_switch_context = set_current_priority(tn_curr_run_task, tn_curr_run_task->base_priority); } else { if (mutex->attr == TN_MUTEX_ATTR_INHERIT || mutex->attr == TN_MUTEX_ATTR_CEILING ) { pr = tn_curr_run_task->base_priority; curr_que = tn_curr_run_task->mutex_queue.next; for (;;) { tmp_mutex = get_mutex_by_mutex_queue(curr_que); pr = find_max_blocked_priority(tmp_mutex,pr); if (curr_que->next == &(tn_curr_run_task->mutex_queue)) break; else { curr_que = curr_que->next; } } if (pr != tn_curr_run_task->priority) { need_switch_context = set_current_priority(tn_curr_run_task,pr); } } } if (is_queue_empty(&(mutex->wait_queue))) { mutex->holder = TN_NULL; hi_pri_task = tn_curr_run_task; } else { if (mutex->attr == TN_MUTEX_ATTR_CEILING) { priority = TN_NUM_PRIORITY - 1; curr_que = mutex->wait_queue.next; for (;;) { task = get_task_by_tsk_queue(curr_que); if (task->priority < priority) { hi_pri_task = task; priority = task->priority; } if (curr_que->next == &(mutex->wait_queue)) break; else curr_que = curr_que->next; } if (enable_lock_mutex(hi_pri_task,&blk_task)) { queue_remove_entry(&(hi_pri_task->task_queue)); remove_task_from_blocked_list(hi_pri_task); if (task_wait_complete(hi_pri_task, TN_FALSE)) need_switch_context = TN_TRUE; mutex->holder = hi_pri_task; hi_pri_task->blk_task = TN_NULL; queue_add_tail(&(hi_pri_task->mutex_queue),&(mutex->mutex_queue)); queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue)); } else { if (!queue_contains_entry(&tn_blocked_tasks_list, &(hi_pri_task->block_queue))) { queue_add_tail(&tn_blocked_tasks_list,&(hi_pri_task->block_queue)); hi_pri_task->task_wait_reason = TSK_WAIT_REASON_MUTEX_C_BLK; hi_pri_task->blk_task = blk_task; } } } else if (mutex->attr == TN_MUTEX_ATTR_INHERIT) { curr_que = queue_remove_head(&(mutex->wait_queue)); task = get_task_by_tsk_queue(curr_que); if (task_wait_complete(task, TN_FALSE)) need_switch_context = TN_TRUE; mutex->holder = task; queue_add_tail(&(task->mutex_queue),&(mutex->mutex_queue)); /*--- v.2.3 */ queue_add_tail(&tn_locked_mutexes_list,&(mutex->lock_mutex_queue)); /*--- */ } } if (mutex->holder == TN_NULL && mutex->attr == TN_MUTEX_ATTR_CEILING) { if (!is_queue_empty(&tn_blocked_tasks_list)) { curr_que = tn_blocked_tasks_list.next; for (;;) { tmp_task = get_task_by_block_queue(curr_que); if (tmp_task != hi_pri_task) { if (try_lock_mutex(tmp_task)) { need_switch_context = TN_TRUE; } } if (curr_que->next == &tn_blocked_tasks_list) break; else curr_que = curr_que->next; } } } return need_switch_context; }