QP/C++
qk_ext.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_ext)
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_schedExt_() is extern "C", so it does not belong to the QP namespace.
00048 //
00049 extern "C" {
00050 
00051 void QK_schedExt_(uint8_t p) {
00052 
00053 #ifdef Q_USE_NAMESPACE
00054     using namespace QP;
00055 #endif
00056     uint8_t pin = QK_currPrio_;                   // save the initial priority
00057     QActive *a;
00058 #ifdef QK_TLS                                    // thread-local storage used?
00059     uint8_t pprev = pin;
00060 #endif
00061 #ifdef QK_EXT_SAVE                            // extended context-switch used?
00062     if (pin != (uint8_t)0) {          // no extended context for the idle loop
00063         a = QF::active_[pin];               // the pointer to the preempted AO
00064         QK_EXT_SAVE(a);                           // save the extended context
00065     }
00066 #endif
00067     do {
00068         a = QF::active_[p];                    // obtain the pointer to the AO
00069         QK_currPrio_ = p;            // this becomes the current task priority
00070 
00071 #ifdef QK_TLS                                    // thread-local storage used?
00072         if (p != pprev) {                          // are we changing threads?
00073             QK_TLS(a);                      // switch new thread-local storage
00074             pprev = p;
00075         }
00076 #endif
00077         QS_BEGIN_NOCRIT_(QS_QK_SCHEDULE, QS::aoObj_, a)
00078             QS_TIME_();                                           // timestamp
00079             QS_U8_(p);                    // the priority of the active object
00080             QS_U8_(pin);                             // the preempted priority
00081         QS_END_NOCRIT_()
00082 
00083         QF_INT_ENABLE();                  // unconditionally enable interrupts
00084 
00085         QEvent const *e = a->get_();         // get the next event for this AO
00086         a->dispatch(e);                               // dispatch e to this AO
00087         QF::gc(e);                  // garbage collect the event, if necessary
00088 
00089                         // determine the next highest-priority AO ready to run
00090         QF_INT_DISABLE();                                // disable interrupts
00091         p = QK_readySet_.findMax();
00092 
00093 #ifdef QK_NO_MUTEX
00094     } while (p > pin);             // is the new priority higher than initial?
00095 #else                                   // QK priority-ceiling mutexes allowed
00096     } while ((p > pin) && (p > QK_ceilingPrio_));
00097 #endif
00098 
00099     QK_currPrio_ = pin;                        // restore the initial priority
00100 
00101 #if defined(QK_TLS) || defined(QK_EXT_RESTORE)
00102     if (pin != (uint8_t)0) {          // no extended context for the idle loop
00103         a = QF::active_[pin];               // the pointer to the preempted AO
00104 #ifdef QK_TLS                                    // thread-local storage used?
00105         QK_TLS(a);                                 // restore the original TLS
00106 #endif
00107 #ifdef QK_EXT_RESTORE                         // extended context-switch used?
00108         QK_EXT_RESTORE(a);                     // restore the extended context
00109 #endif
00110     }
00111 #endif
00112 }
00113 
00114 }                                                                // extern "C"