Linux Face / QPFramework
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qf_tick.cpp Source File

qf_tick.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 07, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 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 "qf_pkg.h"
00029 
00030 // #include "qassert.h"
00031 // Q_DEFINE_THIS_MODULE(qf_tick)
00032 
00033 /// \file
00034 /// \ingroup qf
00035 /// \brief QF::tick() implementation.
00036 
00037 //............................................................................
00038 void QF::tick(void) {                                            // see NOTE01
00039     QF_INT_LOCK_KEY_
00040     QF_INT_LOCK_();
00041 
00042     QS_BEGIN_NOLOCK_(QS_QF_TICK, (void *)0, (void *)0)
00043         QS_TEC_(++QS::tickCtr_);                           // the tick counter
00044     QS_END_NOLOCK_()
00045 
00046     QTimeEvt *t = QF_timeEvtListHead_;
00047     while (t != (QTimeEvt *)0) {
00048         if (--t->m_ctr == (QTimeEvtCtr)0) {// is the time evt about to expire?
00049             if (t->m_interval != (QTimeEvtCtr)0) {//is it a periodic time evt?
00050                 t->m_ctr = t->m_interval;                // rearm the time evt
00051             }
00052             else {   // one-shot time evt, disarm by removing it from the list
00053                 if (t == QF_timeEvtListHead_) {
00054                     QF_timeEvtListHead_ = t->m_next;
00055                 }
00056                 else {
00057                     if (t->m_next != (QTimeEvt *)0) {// not the last time evt?
00058                         t->m_next->m_prev = t->m_prev;
00059                     }
00060                     t->m_prev->m_next = t->m_next;
00061                 }
00062                 t->m_prev = (QTimeEvt *)0;     // mark the time event disarmed
00063 
00064                 QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t)
00065                     QS_OBJ_(t);                      // this time event object
00066                     QS_OBJ_(t->m_act);                     // the active object
00067                 QS_END_NOLOCK_()
00068             }
00069 
00070             QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_POST, QS::teObj_, t)
00071                 QS_TIME_();                                       // timestamp
00072                 QS_OBJ_(t);                           // the time event object
00073                 QS_SIG_(t->sig);              // the signal of this time event
00074                 QS_OBJ_(t->m_act);                        // the active object
00075             QS_END_NOLOCK_()
00076 
00077             QF_INT_UNLOCK_();   // unlock interrupts before calling QF service
00078 
00079                   // postFIFO() asserts internally that the event was accepted
00080             t->m_act->postFIFO(t);
00081         }
00082         else {
00083             QF_INT_UNLOCK_();
00084             static uint8_t volatile dummy;
00085             dummy = (uint8_t)0;      // execute a few instructions, see NOTE02
00086         }
00087 
00088         QF_INT_LOCK_();           // lock interrupts again to advance the link
00089         t = t->m_next;
00090     }
00091     QF_INT_UNLOCK_();
00092 }
00093 
00094 //////////////////////////////////////////////////////////////////////////////
00095 // NOTE01:
00096 // QF::tick() must always run to completion and never preempt itself.
00097 // In particular, if QF::tick() runs in an ISR, the ISR is not allowed to
00098 // preempt itself. Also, QF::tick() should not be called from two different
00099 // ISRs, which potentially could preempt each other.
00100 //
00101 // NOTE02:
00102 // On many CPUs, the interrupt unlocking takes only effect on the next
00103 // machine instruction, which happens to be here another interrupt lock.
00104 // The assignment of a volatile variable requires a few instructions, which
00105 // the compiler cannot optimize away. This ensures that the interrupts get
00106 // actually unlocked, so that the interrupt latency stays low.
00107 //