Exemplo n.º 1
0
/* NOTE: the QK scheduler is entered and exited with interrupts DISABLED    */
void QK_sched_(uint8_t p) {
    uint8_t pin = QK_currPrio_;                /* save the initial priority */
    QActive *a;
#ifdef QK_TLS                                 /* thread-local storage used? */
    uint8_t pprev = pin;
#endif
    do {
        QEvt const *e;
        a = QF_active_[p];                  /* obtain the pointer to the AO */

        QK_currPrio_ = p;         /* this becomes the current task priority */

#ifdef QK_TLS                                 /* thread-local storage used? */
        if (p != pprev) {                       /* are we changing threads? */
            QK_TLS(a);                   /* switch new thread-local storage */
            pprev = p;
        }
#endif
        QS_BEGIN_NOCRIT_(QS_QK_SCHEDULE, QS_priv_.aoObjFilter, a)
            QS_TIME_();                                        /* timestamp */
            QS_U8_(p);                            /* the priority of the AO */
            QS_U8_(pin);                          /* the preempted priority */
        QS_END_NOCRIT_()

        QF_INT_ENABLE();               /* unconditionally enable interrupts */

        e = QActive_get_(a);              /* get the next event for this AO */
        QMSM_DISPATCH(&a->super, e);                  /* dispatch to the AO */
        QF_gc(e);                /* garbage collect the event, if necessary */

        QF_INT_DISABLE();                             /* disable interrupts */

#if (QF_MAX_ACTIVE <= 8)                /* new highest-prio AO ready to run */
        QPSet8_findMax(&QK_readySet_, p);
#else
        QPSet64_findMax(&QK_readySet_, p);
#endif

        if (p <= pin) {          /* below the current preemption threshold? */
            p = (uint8_t)0;
        }
#ifndef QK_NO_MUTEX
        else if (p <= QK_ceilingPrio_) {        /* below the mutex ceiling? */
            p = (uint8_t)0;
        }
        else {
            /* empty */
        }
#endif
    } while (p != (uint8_t)0);

    QK_currPrio_ = pin;                     /* restore the initial priority */

#ifdef QK_TLS                                 /* thread-local storage used? */
    if (pin != (uint8_t)0) {       /* no extended context for the idle loop */
        a = QF_active_[pin];             /* the pointer to the preempted AO */
        QK_TLS(a);                              /* restore the original TLS */
    }
#endif
}
Exemplo n.º 2
0
/**
* \description
* The "extended" QK scheduler performs all the steps of the regular scheduler
* QK_sched_() and additionally switches the Thread-Local Storage (TLS) and
* handles the extended context-switch.
*
* \arguments
* \arg[in] \c p  priority of the next AO to schedule
*
* \note The "extended" QK scheduler needs to be called only to handle
* "asynchronous" preemption, under the assumption that neither the ISRs
* nor the QK idle loop use TLS or the co-processors requiring
* extended context switch (see [PSiCC2] Section 10.4.3).
*
* \note QK_schedExt_() must be always called with interrupts DISABLED.
*
* \note The extended scheduler might enable interrupts internally,
* but always returns with interrupts DISABLED.
*/
void QK_schedExt_(uint_fast8_t p) {
    uint_fast8_t pin = QK_currPrio_; /* save the initial priority */

    /* thread-local storage used? */
#ifdef QK_TLS
    uint_fast8_t pprev = pin;
#endif
    QActive *a;

    /* extended context-switch used? */
#ifdef QK_EXT_SAVE
    /* aren't we preempting the idle loop? (idle loop has prio==0)  */
    if (pin != (uint_fast8_t)0) {
        a = QF_active_[pin]; /* the pointer to the preempted AO */
        QK_EXT_SAVE(a);      /* save the extended context */
    }
#endif

    /* loop until have ready-to-run AOs of higher priority than the initial */
    do {
        QEvt const *e;
        a = QF_active_[p]; /* obtain the pointer to the AO */

        QK_currPrio_ = p;  /* this becomes the current task priority */

    /* thread-local storage used? */
#ifdef QK_TLS
        /* are we changing threads? */
        if (p != pprev) {
            QK_TLS(a); /* switch new thread-local storage */
            pprev = p;
        }
#endif
        QS_BEGIN_NOCRIT_(QS_QK_SCHEDULE, QS_priv_.aoObjFilter, a)
            QS_TIME_();           /* timestamp */
            QS_U8_((uint8_t)p);   /* the priority of the AO */
            QS_U8_((uint8_t)pin); /* the preempted priority */
        QS_END_NOCRIT_()

        QF_INT_ENABLE(); /* unconditionally enable interrupts */

        /* perform the run-to-completion (RTS) step...
        * 1. retrieve the event from the AO's event queue, which by this
        *    time must be non-empty and QActive_get_() asserts it.
        * 2. dispatch the event to the AO's state machine.
        * 3. determine if event is garbage and collect it if so
        */
        e = QActive_get_(a);
        QMSM_DISPATCH(&a->super, e);
        QF_gc(e);

        QF_INT_DISABLE(); /* disable interrupts */

        /* find new highest-priority AO ready to run... */
#if (QF_MAX_ACTIVE <= 8)
        QPSet8_findMax(&QK_readySet_, p);
#else
        QPSet64_findMax(&QK_readySet_, p);
#endif
        /* is the new priority below the current preemption threshold? */
        if (p <= pin) {
            p = (uint_fast8_t)0;
        }
#ifndef QK_NO_MUTEX
        /* is the new priority below the mutex ceiling? */
        else if (p <= QK_ceilingPrio_) {
            p = (uint_fast8_t)0;
        }
        else {
            /* empty */
        }
#endif
    } while (p != (uint_fast8_t)0);

    QK_currPrio_ = pin; /* restore the initial priority */

#if defined(QK_TLS) || defined(QK_EXT_RESTORE)
    /* aren't we preempting the idle loop? (idle loop has prio==0) */
    if (pin != (uint_fast8_t)0) {
        a = QF_active_[pin]; /* the pointer to the preempted AO */

        /* thread-local storage used? */
#ifdef QK_TLS
        QK_TLS(a); /* restore the original TLS */
#endif

        /* extended context-switch used? */
#ifdef QK_EXT_RESTORE
        QK_EXT_RESTORE(a); /* restore the extended context */
#endif
    }
#endif
}
Exemplo n.º 3
0
void QK_schedule_(void) {
#else
void QK_schedule_(QF_INT_KEY_TYPE intLockKey_) {
#endif
    uint8_t p;
                      /* the QK scheduler must be called at task level only */
    Q_REQUIRE(QK_intNest_ == (uint8_t)0);

#if (QF_MAX_ACTIVE <= 8)
    if (QPSet8_notEmpty(&QK_readySet_)) {
        /* determine the priority of the highest-priority task ready to run */
        QPSet8_findMax(&QK_readySet_, p);
#else
    if (QPSet64_notEmpty(&QK_readySet_)) {
        /* determine the priority of the highest-priority task ready to run */
        QPSet64_findMax(&QK_readySet_, p);
#endif

#ifdef QK_NO_MUTEX
        if (p > QK_currPrio_) {                 /* do we have a preemption? */
#else                                /* QK priority-ceiling mutexes allowed */
        if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
#endif
            uint8_t pin = QK_currPrio_;        /* save the initial priority */
            QActive *a;
#ifdef QK_TLS                                 /* thread-local storage used? */
            uint8_t pprev = pin;
#endif
            do {
                QEvent const *e;
                a = QF_active_[p];          /* obtain the pointer to the AO */

                QK_currPrio_ = p; /* this becomes the current task priority */

#ifdef QK_TLS                                 /* thread-local storage used? */
                if (p != pprev) {               /* are we changing threads? */
                    QK_TLS(a);           /* switch new thread-local storage */
                    pprev = p;
                }
#endif
                QS_BEGIN_NOLOCK_(QS_QK_SCHEDULE, QS_aoObj_, a)
                    QS_TIME_();                                /* timestamp */
                    QS_U8_(p);                    /* the priority of the AO */
                    QS_U8_(pin);                  /* the preempted priority */
                QS_END_NOLOCK_()

                QK_INT_UNLOCK_();                  /* unlock the interrupts */

                e = QActive_get_(a);      /* get the next event for this AO */
                QF_ACTIVE_DISPATCH_(&a->super, e);    /* dispatch to the AO */
                QF_gc(e);        /* garbage collect the event, if necessary */

                QK_INT_LOCK_();
                          /* determine the highest-priority AO ready to run */
#if (QF_MAX_ACTIVE <= 8)
                if (QPSet8_notEmpty(&QK_readySet_)) {
                    QPSet8_findMax(&QK_readySet_, p);
#else
                if (QPSet64_notEmpty(&QK_readySet_)) {
                    QPSet64_findMax(&QK_readySet_, p);
#endif
                }
                else {
                    p = (uint8_t)0;
                }
#ifdef QK_NO_MUTEX
            } while (p > pin);  /* is the new priority higher than initial? */
#else                                /* QK priority-ceiling mutexes allowed */
            } while ((p > pin) && (p > QK_ceilingPrio_));
#endif
            QK_currPrio_ = pin;             /* restore the initial priority */

#ifdef QK_TLS                                 /* thread-local storage used? */
            if (pin != (uint8_t)0) {/*no extended context for the idle loop */
                a = QF_active_[pin];     /* the pointer to the preempted AO */
                QK_TLS(a);                      /* restore the original TLS */
            }
#endif
        }
    }
}
Exemplo n.º 4
0
void QK_scheduleExt_(void) {
#else
void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey_) {
#endif
                         // the QK scheduler must be called at task level only
    Q_REQUIRE(QK_intNest_ == (uint8_t)0);

           // determine the priority of the highest-priority task ready to run
    uint8_t p = QK_readySet_.findMax();

#ifdef QK_NO_MUTEX
    if (p > QK_currPrio_) {                        // do we have a preemption?
#else                                   // QK priority-ceiling mutexes allowed
    if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
#endif
        uint8_t pin = QK_currPrio_;               // save the initial priority
        QActive *a;
#ifdef QK_TLS                                    // thread-local storage used?
        uint8_t pprev = pin;
#endif
#ifdef QK_EXT_SAVE                            // extended context-switch used?
        if (pin != (uint8_t)0) {      // no extended context for the idle loop
            a = QF::active_[pin];           // the pointer to the preempted AO
            QK_EXT_SAVE(a);                       // save the extended context
        }
#endif
        do {
            QEvent const *e;
            a = QF::active_[p];                // obtain the pointer to the AO
            QK_currPrio_ = p;        // this becomes the current task priority

#ifdef QK_TLS                                    // thread-local storage used?
            if (p != pprev) {                      // are we changing threads?
                QK_TLS(a);                  // switch new thread-local storage
                pprev = p;
            }
#endif
            QS_BEGIN_NOLOCK_(QS_QK_SCHEDULE, QS::aoObj_, a)
                QS_TIME_();                                       // timestamp
                QS_U8_(p);                // the priority of the active object
                QS_U8_(pin);                         // the preempted priority
            QS_END_NOLOCK_()

            QK_INT_UNLOCK_();                         // unlock the interrupts

            e = a->get_();        // get the next event for this active object
            a->dispatch(e);                 // dispatch e to the active object
            QF::gc(e);              // garbage collect the event, if necessary

            QK_INT_LOCK_();
                             // determine the highest-priority AO ready to run
            p = QK_readySet_.findMax();

#ifdef QK_NO_MUTEX
        } while (p > pin);         // is the new priority higher than initial?
#else                                   // QK priority-ceiling mutexes allowed
        } while ((p > pin) && (p > QK_ceilingPrio_));
#endif
        QK_currPrio_ = pin;                    // restore the initial priority

#if defined(QK_TLS) || defined(QK_EXT_RESTORE)
        if (pin != (uint8_t)0) {      // no extended context for the idle loop
            a = QF::active_[pin];           // the pointer to the preempted AO
    #ifdef QK_TLS                                // thread-local storage used?
            QK_TLS(a);                             // restore the original TLS
    #endif
    #ifdef QK_EXT_RESTORE                     // extended context-switch used?
            QK_EXT_RESTORE(a);                 // restore the extended context
    #endif
        }
#endif
    }
}