Esempio n. 1
0
/**
 * @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
}
Esempio n. 2
0
File: chmtx.c Progetto: Kreyl/Candle
/**
 * @brief   Unlocks all mutexes owned by the invoking thread.
 * @post    The stack of owned mutexes is emptied and all the found
 *          mutexes are unlocked.
 * @note    This function is <b>MUCH MORE</b> efficient than releasing the
 *          mutexes one by one and not just because the call overhead,
 *          this function does not have any overhead related to the priority
 *          inheritance mechanism.
 *
 * @api
 */
void chMtxUnlockAll(void) {
  thread_t *ctp = currp;

  chSysLock();
  if (ctp->p_mtxlist != NULL) {
    do {
      mutex_t *mp = ctp->p_mtxlist;
      ctp->p_mtxlist = mp->m_next;
      if (chMtxQueueNotEmptyS(mp)) {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
        mp->m_cnt = (cnt_t)1;
#endif
        thread_t *tp = queue_fifo_remove(&mp->m_queue);
        mp->m_owner = tp;
        mp->m_next = tp->p_mtxlist;
        tp->p_mtxlist = mp;
        (void) chSchReadyI(tp);
      }
      else {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
        mp->m_cnt = (cnt_t)0;
#endif
        mp->m_owner = NULL;
      }
    } while (ctp->p_mtxlist != NULL);
    ctp->p_prio = ctp->p_realprio;
    chSchRescheduleS();
  }
  chSysUnlock();
}
Esempio n. 3
0
/**
 * @brief   Unlocks all mutexes owned by the invoking thread.
 * @post    The stack of owned mutexes is emptied and all the found
 *          mutexes are unlocked.
 * @post    This function does not reschedule so a call to a rescheduling
 *          function must be performed before unlocking the kernel.
 * @note    This function is <b>MUCH MORE</b> efficient than releasing the
 *          mutexes one by one and not just because the call overhead,
 *          this function does not have any overhead related to the priority
 *          inheritance mechanism.
 *
 * @sclass
 */
void chMtxUnlockAllS(void) {
  thread_t *ctp = currp;

  while (ctp->mtxlist != NULL) {
    mutex_t *mp = ctp->mtxlist;
    ctp->mtxlist = mp->next;
    if (chMtxQueueNotEmptyS(mp)) {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
      mp->cnt = (cnt_t)1;
#endif
      thread_t *tp = queue_fifo_remove(&mp->queue);
      mp->owner = tp;
      mp->next = tp->mtxlist;
      tp->mtxlist = mp;
      (void) chSchReadyI(tp);
    }
    else {
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
      mp->cnt = (cnt_t)0;
#endif
      mp->owner = NULL;
    }
  }
  ctp->prio = ctp->realprio;
}
Esempio n. 4
0
File: chmtx.c Progetto: 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.
 *
 * @return              A pointer to the unlocked mutex.
 *
 * @api
 */
Mutex *chMtxUnlock(void) {
  Thread *ctp = currp;
  Mutex *ump, *mp;

  chSysLock();
  chDbgAssert(ctp->p_mtxlist != NULL,
              "chMtxUnlock(), #1",
              "owned mutexes list empty");
  chDbgAssert(ctp->p_mtxlist->m_owner == ctp,
              "chMtxUnlock(), #2",
              "ownership failure");
  /* Removes the top Mutex from the Thread's 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;
    }
    /* 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.*/
    tp = fifo_remove(&ump->m_queue);
    ump->m_owner = tp;
    ump->m_next = tp->p_mtxlist;
    tp->p_mtxlist = ump;
    chSchWakeupS(tp, RDY_OK);
  }
  else
    ump->m_owner = NULL;
  chSysUnlock();
  return ump;
}
Esempio n. 5
0
File: chmtx.c Progetto: Kreyl/Quetta
/**
 * @brief   Unlocks all the mutexes owned by the invoking thread.
 * @post    The stack of owned mutexes is emptied and all the found
 *          mutexes are unlocked.
 * @note    This function is <b>MUCH MORE</b> efficient than releasing the
 *          mutexes one by one and not just because the call overhead,
 *          this function does not have any overhead related to the priority
 *          inheritance mechanism.
 *
 * @api
 */
void chMtxUnlockAll(void) {
  Thread *ctp = currp;

  chSysLock();
  if (ctp->p_mtxlist != NULL) {
    do {
      Mutex *ump = ctp->p_mtxlist;
      ctp->p_mtxlist = ump->m_next;
      if (chMtxQueueNotEmptyS(ump)) {
        Thread *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;
    } while (ctp->p_mtxlist != NULL);
    ctp->p_prio = ctp->p_realprio;
    chSchRescheduleS();
  }
  chSysUnlock();
}
Esempio n. 6
0
/**
 * @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.
 *
 * @param[in] mp        pointer to the @p mutex_t structure
 *
 * @api
 */
void chMtxUnlock(mutex_t *mp) {
  thread_t *ctp = currp;
  mutex_t *lmp;

  chDbgCheck(mp != NULL);

  chSysLock();

  chDbgAssert(ctp->mtxlist != NULL, "owned mutexes list empty");
  chDbgAssert(ctp->mtxlist->owner == ctp, "ownership failure");
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
  chDbgAssert(mp->cnt >= (cnt_t)1, "counter is not positive");

  if (--mp->cnt == (cnt_t)0) {
#endif

    chDbgAssert(ctp->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->mtxlist = mp->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->realprio;
      lmp = ctp->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->queue.next->prio > newprio)) {
          newprio = lmp->queue.next->prio;
        }
        lmp = lmp->next;
      }

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

      /* Awakens the highest priority thread waiting for the unlocked mutex and
         assigns the mutex to it.*/
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
      mp->cnt = (cnt_t)1;
#endif
      tp = queue_fifo_remove(&mp->queue);
      mp->owner = tp;
      mp->next = tp->mtxlist;
      tp->mtxlist = mp;

      /* Note, not using chSchWakeupS() becuase that function expects the
         current thread to have the higher or equal priority than the ones
         in the ready list. This is not necessarily true here because we
         just changed priority.*/
      (void) chSchReadyI(tp);
      chSchRescheduleS();
    }
    else {
      mp->owner = NULL;
    }
#if CH_CFG_USE_MUTEXES_RECURSIVE == TRUE
  }
#endif

  chSysUnlock();
}