QP/C
qk_ext.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Product: QK/C
00003 * Last Updated for Version: 4.4.00
00004 * Date of the Last Update:  Jan 04, 2012
00005 *
00006 *                    Q u a n t u m     L e a P s
00007 *                    ---------------------------
00008 *                    innovating embedded systems
00009 *
00010 * Copyright (C) 2002-2012 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
00027 *****************************************************************************/
00028 #include "qk_pkg.h"
00029 /*#include "qassert.h"*/
00030 
00031 /*Q_DEFINE_THIS_MODULE("qk_ext")*/
00032 
00039 /*..........................................................................*/
00040 /* NOTE: the QK scheduler is entered and exited with interrupts LOCKED      */
00041 void QK_schedExt_(uint8_t p) {
00042     uint8_t pin = QK_currPrio_;                /* save the initial priority */
00043 #ifdef QK_TLS                                 /* thread-local storage used? */
00044     uint8_t pprev = pin;
00045 #endif
00046     QActive *a;
00047 
00048 #ifdef QK_EXT_SAVE                         /* extended context-switch used? */
00049     if (pin != (uint8_t)0) {       /* no extended context for the idle loop */
00050         a = QF_active_[pin];             /* the pointer to the preempted AO */
00051         QK_EXT_SAVE(a);                        /* save the extended context */
00052     }
00053 #endif
00054     do {
00055         QEvent const *e;
00056         a = QF_active_[p];                  /* obtain the pointer to the AO */
00057 
00058         QK_currPrio_ = p;         /* this becomes the current task priority */
00059 
00060 #ifdef QK_TLS                                 /* thread-local storage used? */
00061         if (p != pprev) {                       /* are we changing threads? */
00062             QK_TLS(a);                   /* switch new thread-local storage */
00063             pprev = p;
00064         }
00065 #endif
00066         QS_BEGIN_NOCRIT_(QS_QK_SCHEDULE, QS_aoObj_, a)
00067             QS_TIME_();                                        /* timestamp */
00068             QS_U8_(p);                            /* the priority of the AO */
00069             QS_U8_(pin);                          /* the preempted priority */
00070         QS_END_NOCRIT_()
00071 
00072         QF_INT_ENABLE();               /* unconditionally enable interrupts */
00073 
00074         e = QActive_get_(a);              /* get the next event for this AO */
00075         QF_ACTIVE_DISPATCH_(&a->super, e);            /* dispatch to the AO */
00076         QF_gc(e);                /* garbage collect the event, if necessary */
00077 
00078         QF_INT_DISABLE();                             /* disable interrupts */
00079 
00080 #if (QF_MAX_ACTIVE <= 8)  /* determine the highest-priority AO ready to run */
00081         QPSet8_findMax(&QK_readySet_, p);
00082 #else
00083         QPSet64_findMax(&QK_readySet_, p);
00084 #endif
00085 #ifdef QK_NO_MUTEX
00086     } while (p > pin);          /* is the new priority higher than initial? */
00087 #else                                /* QK priority-ceiling mutexes allowed */
00088     } while ((p > pin) && (p > QK_ceilingPrio_));
00089 #endif
00090 
00091     QK_currPrio_ = pin;                     /* restore the initial priority */
00092 
00093 #if defined(QK_TLS) || defined(QK_EXT_RESTORE)
00094     if (pin != (uint8_t)0) {       /* no extended context for the idle loop */
00095         a = QF_active_[pin];             /* the pointer to the preempted AO */
00096 #ifdef QK_TLS                                 /* thread-local storage used? */
00097         QK_TLS(a);                              /* restore the original TLS */
00098 #endif
00099 #ifdef QK_EXT_RESTORE                      /* extended context-switch used? */
00100         QK_EXT_RESTORE(a);                  /* restore the extended context */
00101 #endif
00102     }
00103 #endif
00104 }