Exemplo n.º 1
0
/**
 * @brief   Change thread priority.
 * @note    This can interfere with the priority inheritance mechanism.
 */
osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio) {
  osPriority oldprio;
  thread_t * tp = (thread_t *)thread_id;

  chSysLock();

  /* Changing priority.*/
#if CH_CFG_USE_MUTEXES
  oldprio = (osPriority)tp->p_realprio;
  if ((tp->p_prio == tp->p_realprio) || ((tprio_t)newprio > tp->p_prio))
    tp->p_prio = (tprio_t)newprio;
  tp->p_realprio = (tprio_t)newprio;
#else
  oldprio = tp->p_prio;
  tp->p_prio = (tprio_t)newprio;
#endif

  /* The following states need priority queues reordering.*/
  switch (tp->p_state) {
#if CH_CFG_USE_MUTEXES |                                                    \
    CH_CFG_USE_CONDVARS |                                                   \
    (CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) |             \
    (CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY)
#if CH_CFG_USE_MUTEXES
  case CH_STATE_WTMTX:
#endif
#if CH_CFG_USE_CONDVARS
  case CH_STATE_WTCOND:
#endif
#if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY
  case CH_STATE_WTSEM:
#endif
#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY
  case CH_STATE_SNDMSGQ:
#endif
    /* Re-enqueues tp with its new priority on the queue.*/
    queue_prio_insert(queue_dequeue(tp),
                      (threads_queue_t *)tp->p_u.wtobjp);
    break;
#endif
  case CH_STATE_READY:
#if CH_DBG_ENABLE_ASSERTS
    /* Prevents an assertion in chSchReadyI().*/
    tp->p_state = CH_STATE_CURRENT;
#endif
    /* Re-enqueues tp with its new priority on the ready list.*/
    chSchReadyI(queue_dequeue(tp));
    break;
  }

  /* Rescheduling.*/
  chSchRescheduleS();

  chSysUnlock();

  return oldprio;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
Arquivo: chmtx.c Projeto: 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;
  }
}