Пример #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
void os_evt_set (U16 event_flags, OS_TID task_id) {
  /* Set one or more event flags of a selectable task. */
  P_TCB p_tcb;

  p_tcb = os_active_TCB[task_id-1];
  if (p_tcb == NULL) {
    return;
  }
  tsk_lock();
  p_tcb->events |= event_flags;
  event_flags    = p_tcb->waits;
  /* If the task is not waiting for an event, it should not be put */
  /* to ready state. */
  if (p_tcb->state == WAIT_AND) {
    /* Check for AND-connected events */
    if ((p_tcb->events & event_flags) == event_flags) {
      goto wkup;
    }
  }
  if (p_tcb->state == WAIT_OR) {
    /* Check for OR-connected events */
    if (p_tcb->events & event_flags) {
      p_tcb->waits  &= p_tcb->events;
wkup: p_tcb->events &= ~event_flags;
      os_rmv_dly (p_tcb);
      p_tcb->state   = READY;
      p_tcb->ret_val = OS_R_EVT;
      os_dispatch (p_tcb);
    }
  }
  tsk_unlock();
}
Пример #3
0
OS_TID os_tsk_create0 (FUNCP task, U32 prio_stksz, void *stk, void *argv) {
  /* Start a new task declared with "task". */
  P_TCB task_context;

  tsk_lock();
  /* Priority 0 is reserved for idle task! */
  if ((prio_stksz & 0xFF) == 0) {
    prio_stksz += 1;
  }
  task_context = _alloc_box (mp_tcb);
  if (task_context == NULL) {
    tsk_unlock();
    return (0);
  }
  /* If "size != 0" use a private user provided stack. */
  task_context->stack      = stk;
  task_context->priv_stack = prio_stksz >> 8;
  /* Pass parameter 'argv' to 'os_init_context' */
  task_context->p_msg = argv;
  /* For 'size == 0' system allocates the user stack from the memory pool. */
  os_init_context (task_context, prio_stksz & 0xFF, task, __TRUE);

  /* Find a free entry in 'os_active_TCB' table. */
  os_set_TID (task_context);

  rt_notify (task_context->ptask, (__TRUE << 8) | task_context->task_id);
  os_dispatch (task_context);
  tsk_unlock();
  return ((OS_TID)task_context->task_id);
}
Пример #4
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);
}
Пример #5
0
OS_RESULT os_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) {
  /* Send message to a mailbox */
  P_MCB p_MCB = mailbox;
  P_TCB p_TCB;

  tsk_lock();
m:if (p_MCB->p_lnk != NULL && p_MCB->count == 0) {
    /* A task is waiting for message */
    p_TCB = os_get_first ((P_XCB)p_MCB);
    p_TCB->p_msg = p_msg;
    p_TCB->ret_val = OS_R_MBX;
    os_rmv_dly (p_TCB);
    os_dispatch (p_TCB);
  }
  else {
    /* Store message in mailbox queue */
    if (p_MCB->count == p_MCB->size) {
      /* No free message entry, wait for one. If message queue is full, */
      /* then no task is waiting for message. The 'p_MCB->p_lnk' list   */
      /* pointer can now be reused for send message waits task list.    */
      if (timeout == 0) {
        goto wto;
      }
      if (p_MCB->p_lnk != NULL) {
        os_put_prio ((P_XCB)p_MCB, os_runtask);
      }
      else {
        p_MCB->p_lnk = os_runtask;
        os_runtask->p_lnk  = NULL;
        os_runtask->p_rlnk = (P_TCB)p_MCB;
        /* Signal the 'isr_mbx_receive ()' that the task is waiting */
        /* to send a message */
        p_MCB->isr_st = 1;
      }
      if (os_block(timeout, WAIT_MBX) == OS_R_TMO) {
wto:    tsk_unlock();
        return (OS_R_TMO);
      }
      /* A message has been fetched, check the mailbox again. */
      goto m;
    }
    /* Yes, there is a free entry in a mailbox. */
    p_MCB->msg[p_MCB->first] = p_msg;
    _incw (&p_MCB->count);
    if (++p_MCB->first == p_MCB->size) {
      p_MCB->first = 0;
    }
  }
  tsk_unlock();
  return (OS_R_OK);
}
Пример #6
0
OS_RESULT os_mbx_wait (OS_ID mailbox, void **message, U16 timeout) {
  /* Receive a message; possibly wait for it */
  P_MCB p_MCB = mailbox;
  P_TCB p_TCB;

  tsk_lock();
  /* If a message is available in the fifo buffer */
  /* remove it from the fifo buffer and return. */
  if (p_MCB->count) {
    *message = p_MCB->msg[p_MCB->last];
    _decw (&p_MCB->count);
    if (++p_MCB->last == p_MCB->size) {
      p_MCB->last = 0;
    }
    if (p_MCB->p_lnk != NULL) {
      /* A task is waiting to send message */
      p_TCB = os_get_first ((P_XCB)p_MCB);
      os_rmv_dly (p_TCB);
      os_dispatch (p_TCB);
    }
    tsk_unlock();
    return (OS_R_OK);
  }
  /* No message available: wait for one */
  if (timeout == 0) {
    goto rto;
  }
  if (p_MCB->p_lnk != NULL) {
    os_put_prio ((P_XCB)p_MCB, os_runtask);
  }
  else {
    p_MCB->p_lnk = os_runtask;
    os_runtask->p_lnk = NULL;
    os_runtask->p_rlnk = (P_TCB)p_MCB;
  }
  if (os_block(timeout, WAIT_MBX) == OS_R_TMO) {
rto:tsk_unlock();
    *message = NULL;
    return (OS_R_TMO);
  }
  tsk_unlock();
  *message = os_runtask->p_msg;
  return (OS_R_MBX);
}
Пример #7
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);
}