QP/C++
qk_sched.cpp
Go to the documentation of this file.
00001 
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.3.00
00004 // Date of the Last Update:  Nov 02, 2011
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qk_pkg.h"
00029 //#include "qassert.h"
00030 
00034 
00035 #ifdef Q_USE_NAMESPACE
00036 namespace QP {
00037 #endif
00038 
00039 //Q_DEFINE_THIS_MODULE(qk_sched)
00040 
00041 #ifdef Q_USE_NAMESPACE
00042 }                                                              // namespace QP
00043 #endif
00044 
00045 //............................................................................
00046 // NOTE: the QK scheduler is entered and exited with interrupts DISABLED.
00047 // QK_sched_() is extern "C", so it does not belong to the QP namespace.
00048 //
00049 extern "C" {
00050 
00051 void QK_sched_(uint8_t p) {
00052 
00053 #ifdef Q_USE_NAMESPACE
00054     using namespace QP;
00055 #endif
00056 
00057     uint8_t pin = QK_currPrio_;                   // save the initial priority
00058     QActive *a;
00059 #ifdef QK_TLS                                    // thread-local storage used?
00060     uint8_t pprev = pin;
00061 #endif
00062     do {
00063         a = QF::active_[p];                    // obtain the pointer to the AO
00064         QK_currPrio_ = p;            // this becomes the current task priority
00065 
00066 #ifdef QK_TLS                                    // thread-local storage used?
00067         if (p != pprev) {                          // are we changing threads?
00068             QK_TLS(a);                      // switch new thread-local storage
00069             pprev = p;
00070         }
00071 #endif
00072         QS_BEGIN_NOCRIT_(QS_QK_SCHEDULE, QS::aoObj_, a)
00073             QS_TIME_();                                           // timestamp
00074             QS_U8_(p);                    // the priority of the active object
00075             QS_U8_(pin);                             // the preempted priority
00076         QS_END_NOCRIT_()
00077 
00078         QF_INT_ENABLE();                  // unconditionally enable interrupts
00079 
00080         QEvent const *e = a->get_();         // get the next event for this AO
00081         a->dispatch(e);                               // dispatch e to this AO
00082         QF::gc(e);                  // garbage collect the event, if necessary
00083 
00084                         // determine the next highest-priority AO ready to run
00085         QF_INT_DISABLE();                                // disable interrupts
00086         p = QK_readySet_.findMax();
00087 
00088 #ifdef QK_NO_MUTEX
00089     } while (p > pin);             // is the new priority higher than initial?
00090 #else                                   // QK priority-ceiling mutexes allowed
00091     } while ((p > pin) && (p > QK_ceilingPrio_));
00092 #endif
00093 
00094     QK_currPrio_ = pin;                        // restore the initial priority
00095 
00096 #ifdef QK_TLS                                    // thread-local storage used?
00097     if (pin != (uint8_t)0) {          // no extended context for the idle loop
00098         a = QF::active_[pin];               // the pointer to the preempted AO
00099         QK_TLS(a);                                 // restore the original TLS
00100     }
00101 #endif
00102 }
00103 
00104 }                                                                // extern "C"