Пример #1
0
OS_RESULT os_mut_release (OS_ID mutex) {
  /* Release a mutex object */
  P_MUCB p_MCB = mutex;
  P_TCB p_TCB;

  tsk_lock();
  if (p_MCB->level == 0 || p_MCB->owner != os_runtask) {
    /* Unbalanced mutex release or task is not the owner */
    tsk_unlock ();
    return (OS_R_NOK);
  }
  if (--p_MCB->level != 0) {
    goto ok;
  }
  /* Restore owner task's priority. */
  os_runtask->prio = p_MCB->prio;
  if (p_MCB->p_lnk != NULL) {
    /* A task is waiting for this mutex. */
    p_TCB = os_get_first ((P_XCB)p_MCB);
    p_TCB->ret_val = OS_R_MUT;
    os_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_runtask->prio >= os_rdy_prio()) {
      os_dispatch (p_TCB);
    }
    else {
      /* Ready task has higher priority than running task. */
      os_put_prio (&os_rdy, os_runtask);
      os_put_prio (&os_rdy, p_TCB);
      os_runtask->state = READY;
      p_TCB->state      = READY;
      os_dispatch (NULL);
    }
  }
  else {
    /* Check if own priority raised by priority inversion. */
    if (os_rdy_prio() > os_runtask->prio) {
      os_put_prio (&os_rdy, os_runtask);
      os_runtask->state = READY;
      os_dispatch (NULL);
    }
  }
ok:tsk_unlock();
  return (OS_R_OK);
}
Пример #2
0
OS_RESULT os_tsk_prio (OS_TID task_id, U8 new_prio) {
  /* Change execution priority of a task to "new_prio". */
  P_TCB p_task;

  tsk_lock();
  if (task_id == 0) {
    /* Change execution priority of calling task. */
    os_runtask->prio      = new_prio;
    os_runtask->prio_base = new_prio;
run:if (os_rdy_prio() > new_prio) {
      os_put_prio (&os_rdy, os_runtask);
      os_runtask->state = READY;
      os_dispatch (NULL);
    }
    tsk_unlock();
    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. */
    tsk_unlock ();
    return (OS_R_NOK);
  }
  p_task = os_active_TCB[task_id-1];
  p_task->prio      = new_prio;
  p_task->prio_base = new_prio;
  if (p_task == os_runtask) {
    goto run;
  }
  os_resort_prio (p_task);
  if (p_task->state == READY) {
    /* Task enqueued in a ready list. */
    p_task = os_get_first (&os_rdy);
    os_dispatch (p_task);
  }
  tsk_unlock ();
  return (OS_R_OK);
}
Пример #3
0
OS_RESULT os_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;

  tsk_lock();
  if (task_id == 0 || task_id == os_runtask->task_id) {
    /* Terminate itself. */
    os_runtask->state = INACTIVE;
    os_stk_check (0);
    p_MCB = os_runtask->p_mlnk;
    while (p_MCB) {
      /* Release mutexes owned by this task */
      if (p_MCB->p_lnk) {
        /* A task is waiting for mutex. */
        p_TCB = os_get_first ((P_XCB)p_MCB);
        p_TCB->ret_val = OS_R_MUT;
        os_rmv_dly (p_TCB);
        p_TCB->state = READY;
        os_put_prio (&os_rdy, p_TCB);
        /* A waiting task becomes the owner of this mutex. */
        p_MCB0 = p_MCB;
        p_MCB->level  = 1;
        p_MCB->owner  = p_TCB;
        p_MCB->p_mlnk = p_TCB->p_mlnk;
        p_TCB->p_mlnk = p_MCB; 
        p_MCB = p_MCB0->p_mlnk;
      }
      else {
        p_MCB = p_MCB->p_mlnk;
      }
    }
    os_active_TCB[os_runtask->task_id-1] = NULL;
    _free_box (mp_stk, os_runtask->stack);
    os_runtask->stack = NULL;
    rt_notify (os_runtask->ptask, (__FALSE << 8) | os_runtask->task_id);
    _free_box (mp_tcb, os_runtask);
    os_runtask = NULL;
    os_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-1] == NULL) {
      /* Task with "task_id" not found or not started. */
      tsk_unlock ();
      return (OS_R_NOK);
    }
    task_context = os_active_TCB[task_id-1];
    os_rmv_list (task_context);
    os_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 = os_get_first ((P_XCB)p_MCB);
        p_TCB->ret_val = OS_R_MUT;
        os_rmv_dly (p_TCB);
        p_TCB->state = READY;
        os_put_prio (&os_rdy, p_TCB);
        /* A waiting task becomes the owner of this mutex. */
        p_MCB0 = p_MCB;
        p_MCB->level  = 1;
        p_MCB->owner  = p_TCB;
        p_MCB->p_mlnk = p_TCB->p_mlnk;
        p_TCB->p_mlnk = p_MCB; 
        p_MCB = p_MCB0->p_mlnk;
      }
      else {
        p_MCB = p_MCB->p_mlnk;
      }
    }
    os_active_TCB[task_id-1] = NULL;
    _free_box (mp_stk, task_context->stack);
    task_context->stack = NULL;
    rt_notify (task_context->ptask, (__FALSE << 8) | task_context->task_id);
    _free_box (mp_tcb, task_context);
    tsk_unlock ();
    if (os_rdy_prio() > os_runtask->prio) {
      /* Ready task has higher priority than running task. */
      os_runtask->state = READY;
      os_put_prio (&os_rdy, os_runtask);
      os_dispatch (NULL);
    }
  }
  return (OS_R_OK);
}