Example #1
0
OS_RESULT rt_mut_release (OS_ID mutex) {
  /* Release a mutex object */
  P_MUCB p_MCB = mutex;
  P_TCB  p_TCB;

  if (p_MCB->level == 0 || p_MCB->owner != os_tsk.run) {
    /* Unbalanced mutex release or task is not the owner */
    return (OS_R_NOK);
  }
  __DMB();
  if (--p_MCB->level != 0) {
    return (OS_R_OK);
  }
  /* Restore owner task's priority. */
  os_tsk.run->prio = p_MCB->prio;
  if (p_MCB->p_lnk != NULL) {
    /* A task is waiting for mutex. */
    p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
    rt_ret_val(p_TCB, 0/*osOK*/);
#else
    rt_ret_val(p_TCB, OS_R_MUT); 
#endif
    rt_rmv_dly (p_TCB);
    /* A waiting task becomes the owner of this mutex. */
    p_MCB->level     = 1;
    p_MCB->owner     = p_TCB;
    p_MCB->prio      = p_TCB->prio;
    /* Priority inversion, check which task continues. */
    if (os_tsk.run->prio >= rt_rdy_prio()) {
      rt_dispatch (p_TCB);
    }
    else {
      /* Ready task has higher priority than running task. */
      rt_put_prio (&os_rdy, os_tsk.run);
      rt_put_prio (&os_rdy, p_TCB);
      os_tsk.run->state = READY;
      p_TCB->state      = READY;
      rt_dispatch (NULL);
    }
  }
  else {
    /* Check if own priority raised by priority inversion. */
    if (rt_rdy_prio() > os_tsk.run->prio) {
      rt_put_prio (&os_rdy, os_tsk.run);
      os_tsk.run->state = READY;
      rt_dispatch (NULL);
    }
  }
  return (OS_R_OK);
}
Example #2
0
OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) {
  /* Change execution priority of a task to "new_prio". */
  P_TCB p_task;

  if (task_id == 0) {
    /* Change execution priority of calling task. */
    os_tsk.run->prio = new_prio;
run:if (rt_rdy_prio() > new_prio) {
      rt_put_prio (&os_rdy, os_tsk.run);
      os_tsk.run->state   = READY;
      rt_dispatch (NULL);
    }
    return (OS_R_OK);
  }

  /* Find the task in the "os_active_TCB" array. */
  if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) {
    /* Task with "task_id" not found or not started. */
    return (OS_R_NOK);
  }
  p_task = os_active_TCB[task_id-1];
  p_task->prio = new_prio;
  if (p_task == os_tsk.run) {
    goto run;
  }
  rt_resort_prio (p_task);
  if (p_task->state == READY) {
    /* Task enqueued in a ready list. */
    p_task = rt_get_first (&os_rdy);
    rt_dispatch (p_task);
  }
  return (OS_R_OK);
}
Example #3
0
OS_RESULT rt_mut_release (OS_ID mutex) {
  /* Release a mutex object */
  P_MUCB p_MCB = mutex;
  P_TCB  p_TCB;
  P_MUCB p_mlnk;
  U8     prio;

  if ((p_MCB->level == 0U) || (p_MCB->owner != os_tsk.run)) {
    /* Unbalanced mutex release or task is not the owner */
    return (OS_R_NOK);
  }
  if (--p_MCB->level != 0U) {
    return (OS_R_OK);
  }

  /* Remove mutex from task mutex owner list. */
  p_mlnk = os_tsk.run->p_mlnk;
  if (p_mlnk == p_MCB) {
    os_tsk.run->p_mlnk = p_MCB->p_mlnk;
  }
  else {
    while (p_mlnk) {
      if (p_mlnk->p_mlnk == p_MCB) {
        p_mlnk->p_mlnk = p_MCB->p_mlnk;
        break;
      }
      p_mlnk = p_mlnk->p_mlnk;
    }
  }

  /* Restore owner task's priority. */
  prio = os_tsk.run->prio_base;
  p_mlnk = os_tsk.run->p_mlnk;
  while (p_mlnk) {
    if ((p_mlnk->p_lnk != NULL) && (p_mlnk->p_lnk->prio > prio)) {
      /* A task with higher priority is waiting for mutex. */
      prio = p_mlnk->p_lnk->prio;
    }
    p_mlnk = p_mlnk->p_mlnk;
  }
  os_tsk.run->prio = prio;

  if (p_MCB->p_lnk != NULL) {
    /* A task is waiting for mutex. */
    p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
    rt_ret_val(p_TCB, 0U/*osOK*/);
#else
    rt_ret_val(p_TCB, OS_R_MUT); 
#endif
    rt_rmv_dly (p_TCB);
    /* A waiting task becomes the owner of this mutex. */
    p_MCB->level  = 1U;
    p_MCB->owner  = p_TCB;
    p_MCB->p_mlnk = p_TCB->p_mlnk;
    p_TCB->p_mlnk = p_MCB; 
    /* Priority inversion, check which task continues. */
    if (os_tsk.run->prio >= rt_rdy_prio()) {
      rt_dispatch (p_TCB);
    }
    else {
      /* Ready task has higher priority than running task. */
      rt_put_prio (&os_rdy, os_tsk.run);
      rt_put_prio (&os_rdy, p_TCB);
      os_tsk.run->state = READY;
      p_TCB->state      = READY;
      rt_dispatch (NULL);
    }
  }
  else {
    /* Check if own priority lowered by priority inversion. */
    if (rt_rdy_prio() > os_tsk.run->prio) {
      rt_put_prio (&os_rdy, os_tsk.run);
      os_tsk.run->state = READY;
      rt_dispatch (NULL);
    }
  }
  return (OS_R_OK);
}
Example #4
0
OS_RESULT rt_tsk_delete (OS_TID task_id) {
    /* Terminate the task identified with "task_id". */
    P_TCB  task_context;
    P_TCB  p_TCB;
    P_MUCB p_MCB, p_MCB0;

    if ((task_id == 0U) || (task_id == os_tsk.run->task_id)) {
        /* Terminate itself. */
        os_tsk.run->state     = INACTIVE;
        os_tsk.run->tsk_stack = rt_get_PSP ();
        rt_stk_check ();
        p_MCB = os_tsk.run->p_mlnk;
        while (p_MCB) {
            /* Release mutexes owned by this task */
            if (p_MCB->p_lnk) {
                /* A task is waiting for mutex. */
                p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
                rt_ret_val (p_TCB, 0U/*osOK*/);
#else
                rt_ret_val (p_TCB, OS_R_MUT);
#endif
                rt_rmv_dly (p_TCB);
                p_TCB->state = READY;
                rt_put_prio (&os_rdy, p_TCB);
                /* A waiting task becomes the owner of this mutex. */
                p_MCB0 = p_MCB->p_mlnk;
                p_MCB->level  = 1U;
                p_MCB->owner  = p_TCB;
                p_MCB->p_mlnk = p_TCB->p_mlnk;
                p_TCB->p_mlnk = p_MCB;
                p_MCB = p_MCB0;
            }
            else {
                p_MCB0 = p_MCB->p_mlnk;
                p_MCB->level  = 0U;
                p_MCB->owner  = NULL;
                p_MCB->p_mlnk = NULL;
                p_MCB = p_MCB0;
            }
        }
        os_active_TCB[os_tsk.run->task_id-1U] = NULL;
        rt_free_box (mp_stk, os_tsk.run->stack);
        os_tsk.run->stack = NULL;
        DBG_TASK_NOTIFY(os_tsk.run, __FALSE);
        rt_free_box (mp_tcb, os_tsk.run);
        os_tsk.run = NULL;
        rt_dispatch (NULL);
        /* The program should never come to this point. */
    }
    else {
        /* Find the task in the "os_active_TCB" array. */
        if ((task_id > os_maxtaskrun) || (os_active_TCB[task_id-1U] == NULL)) {
            /* Task with "task_id" not found or not started. */
            return (OS_R_NOK);
        }
        task_context = os_active_TCB[task_id-1U];
        rt_rmv_list (task_context);
        rt_rmv_dly (task_context);
        p_MCB = task_context->p_mlnk;
        while (p_MCB) {
            /* Release mutexes owned by this task */
            if (p_MCB->p_lnk) {
                /* A task is waiting for mutex. */
                p_TCB = rt_get_first ((P_XCB)p_MCB);
#ifdef __CMSIS_RTOS
                rt_ret_val (p_TCB, 0U/*osOK*/);
#else
                rt_ret_val (p_TCB, OS_R_MUT);
#endif
                rt_rmv_dly (p_TCB);
                p_TCB->state = READY;
                rt_put_prio (&os_rdy, p_TCB);
                /* A waiting task becomes the owner of this mutex. */
                p_MCB0 = p_MCB->p_mlnk;
                p_MCB->level  = 1U;
                p_MCB->owner  = p_TCB;
                p_MCB->p_mlnk = p_TCB->p_mlnk;
                p_TCB->p_mlnk = p_MCB;
                p_MCB = p_MCB0;
            }
            else {
                p_MCB0 = p_MCB->p_mlnk;
                p_MCB->level  = 0U;
                p_MCB->owner  = NULL;
                p_MCB->p_mlnk = NULL;
                p_MCB = p_MCB0;
            }
        }
        os_active_TCB[task_id-1U] = NULL;
        rt_free_box (mp_stk, task_context->stack);
        task_context->stack = NULL;
        DBG_TASK_NOTIFY(task_context, __FALSE);
        rt_free_box (mp_tcb, task_context);
        if (rt_rdy_prio() > os_tsk.run->prio) {
            /* Ready task has higher priority than running task. */
            os_tsk.run->state = READY;
            rt_put_prio (&os_rdy, os_tsk.run);
            rt_dispatch (NULL);
        }
    }
    return (OS_R_OK);
}