前面,我们说到了优先级的修改函数,而change_interal_task_priority是完成这一功能的函数。当然,我们需要针对目前任务的状态对任务的优先级进行修改,如果任务此时正在运行或者延迟运行,那么还好办,关键是如果此时任务已经阻塞了,那么考虑的情况多了。

RAW_VOID mtx_chg_pri(RAW_TASK_OBJ *tcb, RAW_U8 oldpri)
{
 RAW_MUTEX  *mtxcb;
 RAW_TASK_OBJ *mtxtsk;

 mtxcb = (RAW_MUTEX *)(tcb->block_obj);
 
 if (mtxcb->common_block_obj.object_type == RAW_MUTEX_OBJ_TYPE) {
 
  if (mtxcb->policy == RAW_MUTEX_INHERIT_POLICY) {
   mtxtsk = mtxcb->mtxtsk;
  
   if (mtxtsk->priority > tcb->priority) {
    /* Since the highest priority of the lock wait task
       became higher, raise the lock get task priority
       higher */
    change_interal_task_priority(mtxtsk, tcb->priority);
   }

   /*the highest priority task blocked on this mutex may decrease priority so reset the mutex task priority*/
   else if(mtxtsk->priority == oldpri) {

    release_mutex(mtxtsk, 0);
   }
  
  }
 }

}

  mtx_chg_pri函数此时考虑的不光是它自己优先级的问题,它还需要考虑此时占有互斥量的这个任务优先级该怎么修改。我们进一步看看release_mutex下面做了哪些工作。

static RAW_VOID release_mutex(RAW_TASK_OBJ *tcb, RAW_MUTEX *relmtxcb)
{
 RAW_MUTEX *mtxcb, **prev;
 RAW_U8 newpri, pri;
 RAW_TASK_OBJ *first_block_task;
 LIST *block_list_head;
 
 /* (B) The base priority of task */
 newpri = tcb->bpriority;

 /* (A) The highest priority in mutex which is locked */
 pri = newpri;
 prev = &tcb->mtxlist;
 while ((mtxcb = *prev) != 0) {
  if (mtxcb == relmtxcb) {
   /* Delete from list */
   *prev = mtxcb->mtxlist;
   continue;
  }

  switch (mtxcb->policy) {
    case RAW_MUTEX_CEILING_POLICY:
   pri = mtxcb->ceiling_prio;
   break;
  
    case RAW_MUTEX_INHERIT_POLICY:
    
     block_list_head = &mtxcb->common_block_obj.block_list;
  
   if (!is_list_empty(block_list_head)) {
    first_block_task = list_entry(block_list_head->next, RAW_TASK_OBJ, task_list);
    pri = first_block_task->priority;
   }
  
   break;
  
    default:
   break;
  }
  if (newpri > pri) {
   newpri = pri;
  }

  prev = &mtxcb->mtxlist;
 }

 if ( newpri != tcb->priority ) {
  /* Change priority of lock get task */
  change_interal_task_priority(tcb, newpri);
 }
 
}

  这个函数的工作是修改那个获得互斥量的任务的优先级的,在寻找到高优先级之后,那么又需要调用change_internall_task_priority函数了。有过递归函数编写经验的朋友知道了,这其实是一个典型的递归函数。change_internall_task_priority函数调用到release_mutex,然而release_mutex又调用到change_internall_task_priority,感觉上没完没了了,其实不是这样。递归函数都是需要出口的,这个函数的出口是change_internall_task_priority,一切等到获得的那个任务不再是阻塞任务为止,整个修改的过程结束了。当然,任务优先级恢复的工作也是非常麻烦的,不管是带优先级的互斥量还是优先级继承机制的互斥量,额外的优先级修改和计算都是必须的,不知道我讲清楚了没有。rawos在互斥量的大进步是进一步说明了拥有多互斥量的任务该如何修改优先级,当然了,函数迭代的过程多了堆栈使用的空间也多了,有没有溢出的危险,这是我们需要考虑的另外一个重要因素。