Logo Search packages:      
Sourcecode: u++ version File versions

PeriodicTaskTestStatic.cc

//                              -*- Mode: C++ -*- 
// 
// uC++ Version 5.0.1, Copyright (C) Philipp E. Lim and Ashif S. Harji 1996
// 
// PeriodicTaskTest.cc -- 
// 
// Author           : Philipp E. Lim and Ashif S. Harji
// Created On       : Tue Jul 23 14:48:37 1996
// Last Modified By : Peter A. Buhr
// Last Modified On : Fri Aug 13 08:54:21 2004
// Update Count     : 139
// 

// When run multiprocessor, migration to the system cluster to perform I/O
// causes rescheduling of the tasks on the real-time cluster. An unfortunate
// side-effect of having the standard files on the system cluster.


#include <uC++.h>
#include <uRealTime.h>
#include <uDeadlineMonotonicStatic.h>
#include <uStaticPriorityQ.h>
#include <uStaticPIQ.h>
#include <uIOStream.h>
#include <uIOManip.h>


const int Delay = 100000;
uTime Start;                                    // global start time for all tasks


class AcrossCxtSw : public uContext {
    uTime &clock, beginCxtSw;
  public:
    AcrossCxtSw( uTime &clock ) : clock( clock ) {
    } // AcrossCxtSw::AcrossCxtSw

    void uSave(){
      beginCxtSw = uThisProcessor().uGetClock().uGetTime();
    } // AcrossCxtSw::uSave

    void uRestore(){
      clock += uThisProcessor().uGetClock().uGetTime() - beginCxtSw;
    } // AcrossCxtSw::uRestore
}; // AcrossCxtSw


// This real-time task is periodic with a specific duration and computation
// time (C). However, due to pre-emption from tasks with higher priority and
// time slicing, a direct calculation to simulate computation time does not
// work because time spent executing other tasks is not excluded from the
// calculation of C.  In order to compensate for this, a function is called
// during each context switch to calculate the amount of time spend outside the
// task.  By adding this time to the task's calculated stop time after each
// context switch, an accurate simulation of the computation time, C, is
// possible.

uMutex<uStaticPriorityQ, uStaticPriorityQ> uPeriodicTask<uStaticPIQ> TestTask {
    uDuration C;
    int id;

    void main() {
      uTime starttime, delay, currtime, endtime;

      starttime = uThisProcessor().uGetClock().uGetTime();
      uCout << uAcquire << setw(3) << starttime - ::Start << "\t" << id << " Beginning." << endl << uRelease;

      // The loop below must deal with asynchronous advancing of variable
      // "delay" during context switches. A problem occurs when "delay" is
      // loaded into a register for the comparison, a context switch occurs,
      // and "delay" is advanced, but the old value of "delay" is used in a
      // comparison with the current time. This situation causes a premature
      // exit from the loop because the old delay value is less than the
      // current time.  To solve the problem, the current time value is saved
      // *before* the comparison.  Thus, whether the delay value is the old
      // or new (i.e., becomes larger) value, the comparision does not cause
      // a premature exit.

      delay = uThisProcessor().uGetClock().uGetTime() + C;
      {
          AcrossCxtSw acrossCxtSw( delay );           // cause delay to advance across a context switch interval
          do {
            for ( int i = 0; i < Delay; i += 1 );     // don't spend too much time in non-interruptible clock routine
            currtime = uThisProcessor().uGetClock().uGetTime();
          } while ( delay > currtime );
      }
      endtime = uThisProcessor().uGetClock().uGetTime();
      uCout << uAcquire << setw(3) << endtime - ::Start << "\t" << id << " Ending " <<
          setw(3) << endtime - starttime << " seconds later" << endl << uRelease;
    } // TestTask::main
  public:
    TestTask( int id, uDuration period, uDuration deadline, uCluster &clust ) :
          uPeriodicBaseTask( period, uTime(0), uThisProcessor().uGetClock().uGetTime()+90, deadline, clust ),
          C( deadline ), id( id ) {
    } // TestTask::TestTask
}; // TestTask

void uMain::main() {
    uDeadlineMonotonicStatic rq;                 // create real-time scheduler
    uRealTimeCluster RTClust( rq );             // create real-time cluster with scheduler
    uProcessor *p;
    {
      TestTask t1( 1, 15, 5, RTClust );
      TestTask t2( 2, 30, 9, RTClust );
      TestTask t3( 3, 60, 19, RTClust );

      uCout << uAcquire << "Time  \t\tTaskID" << endl << uRelease;

      ::Start = uThisProcessor().uGetClock().uGetTime();
      p = new uProcessor( RTClust );                  // now create the processor to do the work
    } // wait for t1, t2, t3 to finish
    delete p;
    uCout << "successful completion" << endl;
} // uMain::main


// Local Variables: //
// compile-command: "u++ PeriodicTaskTestStatic.cc" //
// End: //

Generated by  Doxygen 1.6.0   Back to index