示例#1
0
文件: chmboxes.c 项目: rusefi/ChibiOS
/**
 * @brief   Retrieves a message from a mailbox.
 * @details The invoking thread waits until a message is posted in the mailbox
 *          or the specified time runs out.
 *
 * @param[in] mbp       the pointer to an initialized @p mailbox_t object
 * @param[out] msgp     pointer to a message variable for the received message
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval MSG_OK       if a message has been correctly fetched.
 * @retval MSG_RESET    if the mailbox has been reset.
 * @retval MSG_TIMEOUT  if the operation has timed out.
 *
 * @sclass
 */
msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) {
  msg_t rdymsg;

  chDbgCheckClassS();
  chDbgCheck((mbp != NULL) && (msgp != NULL));

  do {
    /* If the mailbox is in reset state then returns immediately.*/
    if (mbp->reset) {
      return MSG_RESET;
    }

    /* Is there a message in queue? if so then fetch.*/
    if (chMBGetUsedCountI(mbp) > (size_t)0) {
      *msgp = *mbp->rdptr++;
      if (mbp->rdptr >= mbp->top) {
        mbp->rdptr = mbp->buffer;
      }
      mbp->cnt--;

      /* If there is a writer waiting then makes it ready.*/
      chThdDequeueNextI(&mbp->qw, MSG_OK);
      chSchRescheduleS();

      return MSG_OK;
    }

    /* No message in the queue, waiting for a message to become available.*/
    rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout);
  } while (rdymsg == MSG_OK);

  return rdymsg;
}
示例#2
0
文件: chmtx.c 项目: Kreyl/Candle
/**
 * @brief   Tries to lock a mutex.
 * @details This function attempts to lock a mutex, if the mutex is already
 *          taken by another thread then the function exits without waiting.
 * @post    The mutex is locked and inserted in the per-thread stack of owned
 *          mutexes.
 * @note    This function does not have any overhead related to the
 *          priority inheritance mechanism because it does not try to
 *          enter a sleep state.
 *
 * @param[in] mp        pointer to the @p mutex_t structure
 * @return              The operation status.
 * @retval true         if the mutex has been successfully acquired
 * @retval false        if the lock attempt failed.
 *
 * @sclass
 */
bool chMtxTryLockS(mutex_t *mp) {

  chDbgCheckClassS();
  chDbgCheck(mp != NULL);

  if (mp->m_owner != NULL) {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE

    chDbgAssert(mp->m_cnt >= (cnt_t)1, "counter is not positive");

    if (mp->m_owner == currp) {
      mp->m_cnt++;
      return true;
    }
#endif
    return false;
  }
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE

  chDbgAssert(mp->m_cnt == (cnt_t)0, "counter is not zero");

  mp->m_cnt++;
#endif
  mp->m_owner = currp;
  mp->m_next = currp->p_mtxlist;
  currp->p_mtxlist = mp;
  return true;
}
示例#3
0
/**
 * @brief   Wakes up a thread.
 * @details The thread is inserted into the ready list or immediately made
 *          running depending on its relative priority compared to the current
 *          thread.
 * @pre     The thread must not be already inserted in any list through its
 *          @p p_next and @p p_prev or list corruption would occur.
 * @note    It is equivalent to a @p chSchReadyI() followed by a
 *          @p chSchRescheduleS() but much more efficient.
 * @note    The function assumes that the current thread has the highest
 *          priority.
 *
 * @param[in] ntp       the thread to be made ready
 * @param[in] msg       the wakeup message
 *
 * @sclass
 */
void chSchWakeupS(thread_t *ntp, msg_t msg) {

  chDbgCheckClassS();

  /* Storing the message to be retrieved by the target thread when it will
     restart execution.*/
  ntp->p_u.rdymsg = msg;

  /* If the waken thread has a not-greater priority than the current
     one then it is just inserted in the ready list else it made
     running immediately and the invoking thread goes in the ready
     list instead.*/
  if (ntp->p_prio <= currp->p_prio) {
    chSchReadyI(ntp);
  }
  else {
    thread_t *otp = chSchReadyI(currp);
    setcurrp(ntp);
#if defined(CH_CFG_IDLE_LEAVE_HOOK)
  if (otp->p_prio == IDLEPRIO) {
    CH_CFG_IDLE_LEAVE_HOOK();
  }
#endif
    ntp->p_state = CH_STATE_CURRENT;
    chSysSwitch(ntp, otp);
  }
}
示例#4
0
文件: chmboxes.c 项目: rusefi/ChibiOS
/**
 * @brief   Posts an high priority message into a mailbox.
 * @details The invoking thread waits until a empty slot in the mailbox becomes
 *          available or the specified time runs out.
 *
 * @param[in] mbp       the pointer to an initialized @p mailbox_t object
 * @param[in] msg       the message to be posted on the mailbox
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval MSG_OK       if a message has been correctly posted.
 * @retval MSG_RESET    if the mailbox has been reset.
 * @retval MSG_TIMEOUT  if the operation has timed out.
 *
 * @sclass
 */
msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) {
  msg_t rdymsg;

  chDbgCheckClassS();
  chDbgCheck(mbp != NULL);

  do {
    /* If the mailbox is in reset state then returns immediately.*/
    if (mbp->reset) {
      return MSG_RESET;
    }

    /* Is there a free message slot in queue? if so then post.*/
    if (chMBGetFreeCountI(mbp) > (size_t)0) {
      if (--mbp->rdptr < mbp->buffer) {
        mbp->rdptr = mbp->top - 1;
      }
      *mbp->rdptr = msg;
      mbp->cnt++;

      /* If there is a reader waiting then makes it ready.*/
      chThdDequeueNextI(&mbp->qr, MSG_OK);
      chSchRescheduleS();

      return MSG_OK;
    }

    /* No space in the queue, waiting for a slot to become available.*/
    rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout);
  } while (rdymsg == MSG_OK);

  return rdymsg;
}
示例#5
0
void chSchRescheduleS(void) {

  chDbgCheckClassS();

  if (chSchIsRescRequiredI())
    chSchDoRescheduleAhead();
}
示例#6
0
文件: chmtx.c 项目: gebart/ChibiOS
/**
 * @brief   Unlocks the specified mutex.
 * @note    Mutexes must be unlocked in reverse lock order. Violating this
 *          rules will result in a panic if assertions are enabled.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 * @post    The mutex is unlocked and removed from the per-thread stack of
 *          owned mutexes.
 * @post    This function does not reschedule so a call to a rescheduling
 *          function must be performed before unlocking the kernel.
 *
 * @param[in] mp        pointer to the @p mutex_t structure
 *
 * @sclass
 */
void chMtxUnlockS(mutex_t *mp) {
    thread_t *ctp = currp;
    mutex_t *lmp;

    chDbgCheckClassS();
    chDbgCheck(mp != NULL);

    chDbgAssert(ctp->p_mtxlist != NULL, "owned mutexes list empty");
    chDbgAssert(ctp->p_mtxlist->m_owner == ctp, "ownership failure");
#if CH_CFG_USE_MUTEXES_RECURSIVE
    chDbgAssert(mp->m_cnt >= 1, "counter is not positive");

    if (--mp->m_cnt == 0) {
#endif

        chDbgAssert(ctp->p_mtxlist == mp, "not next in list");

        /* Removes the top mutex from the thread's owned mutexes list and marks
           it as not owned. Note, it is assumed to be the same mutex passed as
           parameter of this function.*/
        ctp->p_mtxlist = mp->m_next;

        /* If a thread is waiting on the mutex then the fun part begins.*/
        if (chMtxQueueNotEmptyS(mp)) {
            thread_t *tp;

            /* Recalculates the optimal thread priority by scanning the owned
               mutexes list.*/
            tprio_t newprio = ctp->p_realprio;
            lmp = ctp->p_mtxlist;
            while (lmp != NULL) {
                /* If the highest priority thread waiting in the mutexes list has a
                   greater priority than the current thread base priority then the
                   final priority will have at least that priority.*/
                if (chMtxQueueNotEmptyS(lmp) && (lmp->m_queue.p_next->p_prio > newprio))
                    newprio = lmp->m_queue.p_next->p_prio;
                lmp = lmp->m_next;
            }

            /* Assigns to the current thread the highest priority among all the
               waiting threads.*/
            ctp->p_prio = newprio;

            /* Awakens the highest priority thread waiting for the unlocked mutex and
               assigns the mutex to it.*/
#if CH_CFG_USE_MUTEXES_RECURSIVE
            mp->m_cnt = 1;
#endif
            tp = queue_fifo_remove(&mp->m_queue);
            mp->m_owner = tp;
            mp->m_next = tp->p_mtxlist;
            tp->p_mtxlist = mp;
            chSchReadyI(tp);
        }
        else
            mp->m_owner = NULL;
#if CH_CFG_USE_MUTEXES_RECURSIVE
    }
#endif
}
示例#7
0
文件: chmtx.c 项目: Kreyl/Quetta
/**
 * @brief   Tries to lock a mutex.
 * @details This function attempts to lock a mutex, if the mutex is already
 *          taken by another thread then the function exits without waiting.
 * @post    The mutex is locked and inserted in the per-thread stack of owned
 *          mutexes.
 * @note    This function does not have any overhead related to the
 *          priority inheritance mechanism because it does not try to
 *          enter a sleep state.
 *
 * @param[in] mp        pointer to the @p Mutex structure
 * @return              The operation status.
 * @retval TRUE         if the mutex has been successfully acquired
 * @retval FALSE        if the lock attempt failed.
 *
 * @sclass
 */
bool_t chMtxTryLockS(Mutex *mp) {

  chDbgCheckClassS();
  chDbgCheck(mp != NULL, "chMtxTryLockS");

  if (mp->m_owner != NULL)
    return FALSE;
  mp->m_owner = currp;
  mp->m_next = currp->p_mtxlist;
  currp->p_mtxlist = mp;
  return TRUE;
}
void chSchGoSleepS(tstate_t newstate) {
  Thread *otp;

  chDbgCheckClassS();

  (otp = currp)->p_state = newstate;
#if CH_TIME_QUANTUM > 0
  rlist.r_preempt = CH_TIME_QUANTUM;
#endif
  setcurrp(fifo_remove(&rlist.r_queue));
  currp->p_state = THD_STATE_CURRENT;
  chSysSwitch(currp, otp);
}
示例#9
0
void chSchGoSleepS(tstate_t newstate) {
  Thread *otp;

  chDbgCheckClassS();

  (otp = currp)->p_state = newstate;
#if CH_TIME_QUANTUM > 0
  /* The thread is renouncing its remaining time slices so it will have a new
     time quantum when it will wakeup.*/
  otp->p_preempt = CH_TIME_QUANTUM;
#endif
  setcurrp(fifo_remove(&rlist.r_queue));
  currp->p_state = THD_STATE_CURRENT;
  chSysSwitch(currp, otp);
}
示例#10
0
/**
 * @brief   Puts the current thread to sleep into the specified state with
 *          timeout specification.
 * @details The thread goes into a sleeping state, if it is not awakened
 *          explicitly within the specified timeout then it is forcibly
 *          awakened with a @p RDY_TIMEOUT low level message. The possible
 *          @ref thread_states are defined into @p threads.h.
 *
 * @param[in] newstate  the new thread state
 * @param[in] time      the number of ticks before the operation timeouts, the
 *                      special values are handled as follow:
 *                      - @a TIME_INFINITE the thread enters an infinite sleep
 *                        state, this is equivalent to invoking
 *                        @p chSchGoSleepS() but, of course, less efficient.
 *                      - @a TIME_IMMEDIATE this value is not allowed.
 *                      .
 * @return              The wakeup message.
 * @retval RDY_TIMEOUT if a timeout occurs.
 *
 * @sclass
 */
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {

  chDbgCheckClassS();

  if (TIME_INFINITE != time) {
    VirtualTimer vt;

    chVTSetI(&vt, time, wakeup, currp);
    chSchGoSleepS(newstate);
    if (chVTIsArmedI(&vt))
      chVTResetI(&vt);
  }
  else
    chSchGoSleepS(newstate);
  return currp->p_u.rdymsg;
}
示例#11
0
文件: chsem.c 项目: MichDC/ChibiOS-RT
/**
 * @brief   Performs a wait operation on a semaphore.
 *
 * @param[in] sp        pointer to a @p semaphore_t structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval MSG_OK       if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval MSG_RESET    if the semaphore has been reset using @p chSemReset().
 *
 * @sclass
 */
msg_t chSemWaitS(semaphore_t *sp) {

  chDbgCheckClassS();
  chDbgCheck(sp != NULL);
  chDbgAssert(((sp->s_cnt >= 0) && queue_isempty(&sp->s_queue)) ||
              ((sp->s_cnt < 0) && queue_notempty(&sp->s_queue)),
              "inconsistent semaphore");

  if (--sp->s_cnt < 0) {
    currp->p_u.wtobjp = sp;
    sem_insert(currp, &sp->s_queue);
    chSchGoSleepS(CH_STATE_WTSEM);
    return currp->p_u.rdymsg;
  }
  return MSG_OK;
}
示例#12
0
/**
 * @brief   Posts an high priority message into a mailbox.
 * @details The invoking thread waits until a empty slot in the mailbox becomes
 *          available or the specified time runs out.
 *
 * @param[in] mbp       the pointer to an initialized @p mailbox_t object
 * @param[in] msg       the message to be posted on the mailbox
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval MSG_OK       if a message has been correctly posted.
 * @retval MSG_RESET    if the mailbox has been reset while waiting.
 * @retval MSG_TIMEOUT  if the operation has timed out.
 *
 * @sclass
 */
msg_t chMBPostAheadS(mailbox_t *mbp, msg_t msg, systime_t time) {
  msg_t rdymsg;

  chDbgCheckClassS();
  chDbgCheck(mbp != NULL);

  rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
  if (rdymsg == MSG_OK) {
    if (--mbp->mb_rdptr < mbp->mb_buffer)
      mbp->mb_rdptr = mbp->mb_top - 1;
    *mbp->mb_rdptr = msg;
    chSemSignalI(&mbp->mb_fullsem);
    chSchRescheduleS();
  }
  return rdymsg;
}
示例#13
0
/**
 * @brief   Retrieves a message from a mailbox.
 * @details The invoking thread waits until a message is posted in the mailbox
 *          or the specified time runs out.
 *
 * @param[in] mbp       the pointer to an initialized @p mailbox_t object
 * @param[out] msgp     pointer to a message variable for the received message
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval MSG_OK       if a message has been correctly fetched.
 * @retval MSG_RESET    if the mailbox has been reset while waiting.
 * @retval MSG_TIMEOUT  if the operation has timed out.
 *
 * @sclass
 */
msg_t chMBFetchS(mailbox_t *mbp, msg_t *msgp, systime_t time) {
  msg_t rdymsg;

  chDbgCheckClassS();
  chDbgCheck((mbp != NULL) && (msgp != NULL));

  rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time);
  if (rdymsg == MSG_OK) {
    *msgp = *mbp->mb_rdptr++;
    if (mbp->mb_rdptr >= mbp->mb_top)
      mbp->mb_rdptr = mbp->mb_buffer;
    chSemSignalI(&mbp->mb_emptysem);
    chSchRescheduleS();
  }
  return rdymsg;
}
示例#14
0
/**
 * @brief   Posts a message into a mailbox.
 * @details The invoking thread waits until a empty slot in the mailbox becomes
 *          available or the specified time runs out.
 *
 * @param[in] mbp       the pointer to an initialized Mailbox object
 * @param[in] msg       the message to be posted on the mailbox
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation status.
 * @retval RDY_OK       if a message has been correctly posted.
 * @retval RDY_RESET    if the mailbox has been reset while waiting.
 * @retval RDY_TIMEOUT  if the operation has timed out.
 *
 * @sclass
 */
msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) {
  msg_t rdymsg;

  chDbgCheckClassS();
  chDbgCheck(mbp != NULL, "chMBPostS");

  rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
  if (rdymsg == RDY_OK) {
    *mbp->mb_wrptr++ = msg;
    if (mbp->mb_wrptr >= mbp->mb_top)
      mbp->mb_wrptr = mbp->mb_buffer;
    chSemSignalI(&mbp->mb_fullsem);
    chSchRescheduleS();
  }
  return rdymsg;
}
示例#15
0
文件: chsem.c 项目: 0x00f/ChibiOS
/**
 * @brief   Performs a wait operation on a semaphore.
 *
 * @param[in] sp        pointer to a @p Semaphore structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval RDY_OK       if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval RDY_RESET    if the semaphore has been reset using @p chSemReset().
 *
 * @sclass
 */
msg_t chSemWaitS(Semaphore *sp) {

  chDbgCheckClassS();
  chDbgCheck(sp != NULL, "chSemWaitS");
  chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
              ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
              "chSemWaitS(), #1",
              "inconsistent semaphore");

  if (--sp->s_cnt < 0) {
    currp->p_u.wtobjp = sp;
    sem_insert(currp, &sp->s_queue);
    chSchGoSleepS(THD_STATE_WTSEM);
    return currp->p_u.rdymsg;
  }
  return RDY_OK;
}
示例#16
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 * @pre     The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
 *          in order to use this function.
 * @post    Exiting the function because a timeout does not re-acquire the
 *          mutex, the mutex ownership is lost.
 *
 * @param[in] cp        pointer to the @p condition_variable_t structure
 * @param[in] time      the number of ticks before the operation timeouts, the
 *                      special values are handled as follow:
 *                      - @a TIME_INFINITE no timeout.
 *                      - @a TIME_IMMEDIATE this value is not allowed.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval MSG_OK       if the condition variable has been signaled using
 *                      @p chCondSignal().
 * @retval MSG_RESET    if the condition variable has been signaled using
 *                      @p chCondBroadcast().
 * @retval MSG_TIMEOUT  if the condition variable has not been signaled within
 *                      the specified timeout.
 *
 * @sclass
 */
msg_t chCondWaitTimeoutS(condition_variable_t *cp, systime_t time) {
  mutex_t *mp;
  msg_t msg;

  chDbgCheckClassS();
  chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE));
  chDbgAssert(currp->p_mtxlist != NULL, "not owning a mutex");

  mp = chMtxGetNextMutexS();
  chMtxUnlockS(mp);
  currp->p_u.wtobjp = cp;
  queue_prio_insert(currp, &cp->c_queue);
  msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, time);
  if (msg != MSG_TIMEOUT)
    chMtxLockS(mp);
  return msg;
}
示例#17
0
文件: chmtx.c 项目: Kreyl/Quetta
/**
 * @brief   Unlocks the next owned mutex in reverse lock order.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 * @post    The mutex is unlocked and removed from the per-thread stack of
 *          owned mutexes.
 * @post    This function does not reschedule so a call to a rescheduling
 *          function must be performed before unlocking the kernel.
 *
 * @return              A pointer to the unlocked mutex.
 *
 * @sclass
 */
Mutex *chMtxUnlockS(void) {
  Thread *ctp = currp;
  Mutex *ump, *mp;

  chDbgCheckClassS();
  chDbgAssert(ctp->p_mtxlist != NULL,
              "chMtxUnlockS(), #1",
              "owned mutexes list empty");
  chDbgAssert(ctp->p_mtxlist->m_owner == ctp,
              "chMtxUnlockS(), #2",
              "ownership failure");

  /* Removes the top Mutex from the owned mutexes list and marks it as not
     owned.*/
  ump = ctp->p_mtxlist;
  ctp->p_mtxlist = ump->m_next;
  /* If a thread is waiting on the mutex then the fun part begins.*/
  if (chMtxQueueNotEmptyS(ump)) {
    Thread *tp;

    /* Recalculates the optimal thread priority by scanning the owned
       mutexes list.*/
    tprio_t newprio = ctp->p_realprio;
    mp = ctp->p_mtxlist;
    while (mp != NULL) {
      /* If the highest priority thread waiting in the mutexes list has a
         greater priority than the current thread base priority then the final
         priority will have at least that priority.*/
      if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
        newprio = mp->m_queue.p_next->p_prio;
      mp = mp->m_next;
    }
    ctp->p_prio = newprio;
    /* Awakens the highest priority thread waiting for the unlocked mutex and
       assigns the mutex to it.*/
    tp = fifo_remove(&ump->m_queue);
    ump->m_owner = tp;
    ump->m_next = tp->p_mtxlist;
    tp->p_mtxlist = ump;
    chSchReadyI(tp);
  }
  else
    ump->m_owner = NULL;
  return ump;
}
示例#18
0
void chSchWakeupS(Thread *ntp, msg_t msg) {

  chDbgCheckClassS();

  ntp->p_u.rdymsg = msg;
  /* If the waken thread has a not-greater priority than the current
     one then it is just inserted in the ready list else it made
     running immediately and the invoking thread goes in the ready
     list instead.*/
  if (ntp->p_prio <= currp->p_prio)
    chSchReadyI(ntp);
  else {
    Thread *otp = chSchReadyI(currp);
    setcurrp(ntp);
    ntp->p_state = THD_STATE_CURRENT;
    chSysSwitch(ntp, otp);
  }
}
示例#19
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 *
 * @param[in] cp        pointer to the @p condition_variable_t structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval MSG_OK       if the condition variable has been signaled using
 *                      @p chCondSignal().
 * @retval MSG_RESET    if the condition variable has been signaled using
 *                      @p chCondBroadcast().
 *
 * @sclass
 */
msg_t chCondWaitS(condition_variable_t *cp) {
  thread_t *ctp = currp;
  mutex_t *mp;
  msg_t msg;

  chDbgCheckClassS();
  chDbgCheck(cp != NULL);
  chDbgAssert(ctp->p_mtxlist != NULL, "not owning a mutex");

  mp = chMtxGetNextMutexS();
  chMtxUnlockS(mp);
  ctp->p_u.wtobjp = cp;
  queue_prio_insert(ctp, &cp->c_queue);
  chSchGoSleepS(CH_STATE_WTCOND);
  msg = ctp->p_u.rdymsg;
  chMtxLockS(mp);
  return msg;
}
示例#20
0
文件: chsem.c 项目: MichDC/ChibiOS-RT
/**
 * @brief   Performs a wait operation on a semaphore with timeout specification.
 *
 * @param[in] sp        pointer to a @p semaphore_t structure
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval MSG_OK       if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval MSG_RESET    if the semaphore has been reset using @p chSemReset().
 * @retval MSG_TIMEOUT  if the semaphore has not been signaled or reset within
 *                      the specified timeout.
 *
 * @sclass
 */
msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t time) {

  chDbgCheckClassS();
  chDbgCheck(sp != NULL);
  chDbgAssert(((sp->s_cnt >= 0) && queue_isempty(&sp->s_queue)) ||
              ((sp->s_cnt < 0) && queue_notempty(&sp->s_queue)),
              "inconsistent semaphore");

  if (--sp->s_cnt < 0) {
    if (TIME_IMMEDIATE == time) {
      sp->s_cnt++;
      return MSG_TIMEOUT;
    }
    currp->p_u.wtobjp = sp;
    sem_insert(currp, &sp->s_queue);
    return chSchGoSleepTimeoutS(CH_STATE_WTSEM, time);
  }
  return MSG_OK;
}
示例#21
0
文件: ch.c 项目: hsteinhaus/ChibiOS
/**
 * @brief   Performs a wait operation on a semaphore with timeout specification.
 *
 * @param[in] sp        pointer to a @p semaphore_t structure
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval NIL_MSG_OK   if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval NIL_MSG_RST  if the semaphore has been reset using @p chSemReset().
 * @retval NIL_MSG_TMO  if the semaphore has not been signaled or reset within
 *                      the specified timeout.
 *
 * @sclass
 */
msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) {

  chDbgCheckClassS();
  chDbgCheck(sp != NULL);

  /* Note, the semaphore counter is a volatile variable so accesses are
     manually optimized.*/
  cnt_t cnt = sp->cnt;
  if (cnt <= (cnt_t)0) {
    if (TIME_IMMEDIATE == timeout) {
      return MSG_TIMEOUT;
    }
    sp->cnt = cnt - (cnt_t)1;
    nil.current->u1.semp = sp;
    return chSchGoSleepTimeoutS(NIL_STATE_WTSEM, timeout);
  }
  sp->cnt = cnt - (cnt_t)1;
  return MSG_OK;
}
示例#22
0
/**
 * @brief   Puts the current thread to sleep into the specified state.
 * @details The thread goes into a sleeping state. The possible
 *          @ref thread_states are defined into @p threads.h.
 *
 * @param[in] newstate  the new thread state
 *
 * @sclass
 */
void chSchGoSleepS(tstate_t newstate) {
  thread_t *otp;

  chDbgCheckClassS();

  (otp = currp)->p_state = newstate;
#if CH_CFG_TIME_QUANTUM > 0
  /* The thread is renouncing its remaining time slices so it will have a new
     time quantum when it will wakeup.*/
  otp->p_preempt = CH_CFG_TIME_QUANTUM;
#endif
  setcurrp(queue_fifo_remove(&ch.rlist.r_queue));
#if defined(CH_CFG_IDLE_ENTER_HOOK)
  if (currp->p_prio == IDLEPRIO) {
    CH_CFG_IDLE_ENTER_HOOK();
  }
#endif
  currp->p_state = CH_STATE_CURRENT;
  chSysSwitch(currp, otp);
}
示例#23
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 *
 * @param[in] cp        pointer to the @p condition_variable_t structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval MSG_OK       if the condition variable has been signaled using
 *                      @p chCondSignal().
 * @retval MSG_RESET    if the condition variable has been signaled using
 *                      @p chCondBroadcast().
 *
 * @sclass
 */
msg_t chCondWaitS(condition_variable_t *cp) {
  thread_t *ctp = currp;
  mutex_t *mp;
  msg_t msg;

  chDbgCheckClassS();
  chDbgCheck(cp != NULL);
  chDbgAssert(ctp->p_mtxlist != NULL, "not owning a mutex");

  /* Getting "current" mutex and releasing it.*/
  mp = chMtxGetNextMutexS();
  chMtxUnlockS(mp);

  /* Start waiting on the condition variable, on exit the mutex is taken
     again.*/
  ctp->p_u.wtobjp = cp;
  queue_prio_insert(ctp, &cp->c_queue);
  chSchGoSleepS(CH_STATE_WTCOND);
  msg = ctp->p_u.rdymsg;
  chMtxLockS(mp);

  return msg;
}
示例#24
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 * @pre     The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
 *          in order to use this function.
 * @post    Exiting the function because a timeout does not re-acquire the
 *          mutex, the mutex ownership is lost.
 *
 * @param[in] cp        pointer to the @p condition_variable_t structure
 * @param[in] time      the number of ticks before the operation timeouts, the
 *                      special values are handled as follow:
 *                      - @a TIME_INFINITE no timeout.
 *                      - @a TIME_IMMEDIATE this value is not allowed.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval MSG_OK       if the condition variable has been signaled using
 *                      @p chCondSignal().
 * @retval MSG_RESET    if the condition variable has been signaled using
 *                      @p chCondBroadcast().
 * @retval MSG_TIMEOUT  if the condition variable has not been signaled within
 *                      the specified timeout.
 *
 * @sclass
 */
msg_t chCondWaitTimeoutS(condition_variable_t *cp, systime_t time) {
  mutex_t *mp;
  msg_t msg;

  chDbgCheckClassS();
  chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE));
  chDbgAssert(currp->p_mtxlist != NULL, "not owning a mutex");

  /* Getting "current" mutex and releasing it.*/
  mp = chMtxGetNextMutexS();
  chMtxUnlockS(mp);

  /* Start waiting on the condition variable, on exit the mutex is taken
     again.*/
  currp->p_u.wtobjp = cp;
  queue_prio_insert(currp, &cp->c_queue);
  msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, time);
  if (msg != MSG_TIMEOUT) {
    chMtxLockS(mp);
  }

  return msg;
}
示例#25
0
文件: chmtx.c 项目: Kreyl/Candle
/**
 * @brief   Locks the specified mutex.
 * @post    The mutex is locked and inserted in the per-thread stack of owned
 *          mutexes.
 *
 * @param[in] mp        pointer to the @p mutex_t structure
 *
 * @sclass
 */
void chMtxLockS(mutex_t *mp) {
  thread_t *ctp = currp;

  chDbgCheckClassS();
  chDbgCheck(mp != NULL);

  /* Is the mutex already locked? */
  if (mp->m_owner != NULL) {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE

    chDbgAssert(mp->m_cnt >= (cnt_t)1, "counter is not positive");

    /* If the mutex is already owned by this thread, the counter is increased
       and there is no need of more actions.*/
    if (mp->m_owner == ctp) {
      mp->m_cnt++;
    }
    else {
#endif
      /* Priority inheritance protocol; explores the thread-mutex dependencies
         boosting the priority of all the affected threads to equal the
         priority of the running thread requesting the mutex.*/
      thread_t *tp = mp->m_owner;

      /* Does the running thread have higher priority than the mutex
         owning thread? */
      while (tp->p_prio < ctp->p_prio) {
        /* Make priority of thread tp match the running thread's priority.*/
        tp->p_prio = ctp->p_prio;

        /* The following states need priority queues reordering.*/
        switch (tp->p_state) {
        case CH_STATE_WTMTX:
          /* Re-enqueues the mutex owner with its new priority.*/
          queue_prio_insert(queue_dequeue(tp), &tp->p_u.wtmtxp->m_queue);
          tp = tp->p_u.wtmtxp->m_owner;
          /*lint -e{9042} [16.1] Continues the while.*/
          continue;
#if (CH_CFG_USE_CONDVARS == TRUE) ||                                        \
    ((CH_CFG_USE_SEMAPHORES == TRUE) &&                                     \
     (CH_CFG_USE_SEMAPHORES_PRIORITY == TRUE)) ||                           \
    ((CH_CFG_USE_MESSAGES == TRUE) &&                                       \
     (CH_CFG_USE_MESSAGES_PRIORITY == TRUE))
#if CH_CFG_USE_CONDVARS == TRUE
        case CH_STATE_WTCOND:
#endif
#if (CH_CFG_USE_SEMAPHORES == TRUE) &&                                      \
    (CH_CFG_USE_SEMAPHORES_PRIORITY == TRUE)
        case CH_STATE_WTSEM:
#endif
#if (CH_CFG_USE_MESSAGES == TRUE) && (CH_CFG_USE_MESSAGES_PRIORITY == TRUE)
        case CH_STATE_SNDMSGQ:
#endif
          /* Re-enqueues tp with its new priority on the queue.*/
          queue_prio_insert(queue_dequeue(tp), &tp->p_u.wtmtxp->m_queue);
          break;
#endif
        case CH_STATE_READY:
#if CH_DBG_ENABLE_ASSERTS == TRUE
          /* Prevents an assertion in chSchReadyI().*/
          tp->p_state = CH_STATE_CURRENT;
#endif
          /* Re-enqueues tp with its new priority on the ready list.*/
          (void) chSchReadyI(queue_dequeue(tp));
          break;
        default:
          /* Nothing to do for other states.*/
          break;
        }
        break;
      }

      /* Sleep on the mutex.*/
      queue_prio_insert(ctp, &mp->m_queue);
      ctp->p_u.wtmtxp = mp;
      chSchGoSleepS(CH_STATE_WTMTX);

      /* It is assumed that the thread performing the unlock operation assigns
         the mutex to this thread.*/
      chDbgAssert(mp->m_owner == ctp, "not owner");
      chDbgAssert(ctp->p_mtxlist == mp, "not owned");
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
      chDbgAssert(mp->m_cnt == (cnt_t)1, "counter is not one");
    }
#endif
  }
  else {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
    chDbgAssert(mp->m_cnt == (cnt_t)0, "counter is not zero");

    mp->m_cnt++;
#endif
    /* It was not owned, inserted in the owned mutexes list.*/
    mp->m_owner = ctp;
    mp->m_next = ctp->p_mtxlist;
    ctp->p_mtxlist = mp;
  }
}
示例#26
0
文件: chmtx.c 项目: Kreyl/Quetta
/**
 * @brief   Locks the specified mutex.
 * @post    The mutex is locked and inserted in the per-thread stack of owned
 *          mutexes.
 *
 * @param[in] mp        pointer to the @p Mutex structure
 *
 * @sclass
 */
void chMtxLockS(Mutex *mp) {
  Thread *ctp = currp;

  chDbgCheckClassS();
  chDbgCheck(mp != NULL, "chMtxLockS");

  /* Is the mutex already locked? */
  if (mp->m_owner != NULL) {
    /* Priority inheritance protocol; explores the thread-mutex dependencies
       boosting the priority of all the affected threads to equal the priority
       of the running thread requesting the mutex.*/
    Thread *tp = mp->m_owner;
    /* Does the running thread have higher priority than the mutex
       owning thread? */
    while (tp->p_prio < ctp->p_prio) {
      /* Make priority of thread tp match the running thread's priority.*/
      tp->p_prio = ctp->p_prio;
      /* The following states need priority queues reordering.*/
      switch (tp->p_state) {
      case THD_STATE_WTMTX:
        /* Re-enqueues the mutex owner with its 0; // new priority.*/
        prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp);
        tp = ((Mutex *)tp->p_u.wtobjp)->m_owner;
        continue;
#if CH_USE_CONDVARS |                                                       \
    (CH_USE_SEMAPHORES && CH_USE_SEMAPHORES_PRIORITY) |                     \
    (CH_USE_MESSAGES && CH_USE_MESSAGES_PRIORITY)
#if CH_USE_CONDVARS
      case THD_STATE_WTCOND:
#endif
#if CH_USE_SEMAPHORES && CH_USE_SEMAPHORES_PRIORITY
      case THD_STATE_WTSEM:
#endif
#if CH_USE_MESSAGES && CH_USE_MESSAGES_PRIORITY
      case THD_STATE_SNDMSGQ:
#endif
        /* Re-enqueues tp with its 0; // new priority on the queue.*/
        prio_insert(dequeue(tp), (ThreadsQueue *)tp->p_u.wtobjp);
        break;
#endif
      case THD_STATE_READY:
#if CH_DBG_ENABLE_ASSERTS
        /* Prevents an assertion in chSchReadyI().*/
        tp->p_state = THD_STATE_CURRENT;
#endif
        /* Re-enqueues tp with its 0; // new priority on the ready list.*/
        chSchReadyI(dequeue(tp));
        break;
      }
      break;
    }
    /* Sleep on the mutex.*/
    prio_insert(ctp, &mp->m_queue);
    ctp->p_u.wtobjp = mp;
    chSchGoSleepS(THD_STATE_WTMTX);
    /* It is assumed that the thread performing the unlock operation assigns
       the mutex to this thread.*/
    chDbgAssert(mp->m_owner == ctp, "chMtxLockS(), #1", "not owner");
    chDbgAssert(ctp->p_mtxlist == mp, "chMtxLockS(), #2", "not owned");
  }
  else {
    /* It was not owned, inserted in the owned mutexes list.*/
    mp->m_owner = ctp;
    mp->m_next = ctp->p_mtxlist;
    ctp->p_mtxlist = mp;
  }
}
示例#27
0
文件: ch.c 项目: hsteinhaus/ChibiOS
/**
 * @brief   Puts the current thread to sleep into the specified state with
 *          timeout specification.
 * @details The thread goes into a sleeping state, if it is not awakened
 *          explicitly within the specified system time then it is forcibly
 *          awakened with a @p NIL_MSG_TMO low level message.
 *
 * @param[in] newstate  the new thread state or a semaphore pointer
 * @param[in] timeout   the number of ticks before the operation timeouts.
 *                      the following special values are allowed:
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The wakeup message.
 * @retval NIL_MSG_TMO  if a timeout occurred.
 *
 * @sclass
 */
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) {
  thread_t *ntp, *otp = nil.current;

  chDbgCheckClassS();

  chDbgAssert(otp != &nil.threads[CH_CFG_NUM_THREADS],
               "idle cannot sleep");

  /* Storing the wait object for the current thread.*/
  otp->state = newstate;

#if CH_CFG_ST_TIMEDELTA > 0
  if (timeout != TIME_INFINITE) {
    systime_t abstime;

    /* TIMEDELTA makes sure to have enough time to reprogram the timer
       before the free-running timer counter reaches the selected timeout.*/
    if (timeout < (systime_t)CH_CFG_ST_TIMEDELTA) {
      timeout = (systime_t)CH_CFG_ST_TIMEDELTA;
    }

    /* Absolute time of the timeout event.*/
    abstime = chVTGetSystemTimeX() + timeout;

    if (nil.lasttime == nil.nexttime) {
      /* Special case, first thread asking for a timeout.*/
      port_timer_start_alarm(abstime);
      nil.nexttime = abstime;
    }
    else {
      /* Special case, there are already other threads with a timeout
         activated, evaluating the order.*/
      if (chVTIsTimeWithinX(abstime, nil.lasttime, nil.nexttime)) {
        port_timer_set_alarm(abstime);
        nil.nexttime = abstime;
      }
    }

    /* Timeout settings.*/
    otp->timeout = abstime - nil.lasttime;
  }
#else

  /* Timeout settings.*/
  otp->timeout = timeout;
#endif

  /* Scanning the whole threads array.*/
  ntp = nil.threads;
  while (true) {
    /* Is this thread ready to execute?*/
    if (NIL_THD_IS_READY(ntp)) {
      nil.current = nil.next = ntp;
      if (ntp == &nil.threads[CH_CFG_NUM_THREADS]) {
        CH_CFG_IDLE_ENTER_HOOK();
      }
      port_switch(ntp, otp);
      return nil.current->u1.msg;
    }

    /* Points to the next thread in lowering priority order.*/
    ntp++;
    chDbgAssert(ntp <= &nil.threads[CH_CFG_NUM_THREADS],
                "pointer out of range");
  }
}