/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; } }