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

RealTimePhilosophersStatic.cc

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

// 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 <uIOStream.h>
#include <uIOManip.h>
#include <uDeadlineMonotonicStatic.h>
#include <uStaticPriorityQ.h>
#include <uStaticPIQ.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


uMutex<uStaticPriorityQ, uStaticPriorityQ> class RestRoom {
  public:
    void Toilet( int id, uDuration C1 ) {
      uTime starttime, delay, currtime, endtime;

      starttime = uThisProcessor().uGetClock().uGetTime();
      uCout << uAcquire << setw(3) << starttime - ::Start << "\t" << id << " goes to TOILET (priority " <<
          uThisTask().uGetActivePriorityValue() << "," << uThisTask().uGetActiveQueueValue() << ")" << 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() + C1;
      {
          AcrossCxtSw acrossCxtSw( delay );
          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 << " leaves TOILET " <<
          setw(3) << endtime - starttime << " seconds later (priority " << uThisTask().uGetActivePriorityValue() << "," << uThisTask().uGetActiveQueueValue() <<
          ")" << endl << uRelease;
    } // Toilet::Toilet

    uNoMutex void Wash( int id, uDuration C2 ) {
      uTime starttime, delay, currtime, endtime;

      starttime = uThisProcessor().uGetClock().uGetTime();
      uCout << uAcquire << setw(3) << starttime - ::Start << "\t" << id << " goes to WASH (priority " <<
          uThisTask().uGetActivePriorityValue() << "," << uThisTask().uGetActiveQueueValue() << ")" << 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() + C2;
      {
          AcrossCxtSw acrossCxtSw( delay );
          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 << " finished with WASH " <<
          setw(3) << endtime - starttime << " seconds later (priority " << uThisTask().uGetActivePriorityValue() << "," << uThisTask().uGetActiveQueueValue() << 
          ")" << endl << uRelease;
    } // Toilet::Wash
}; // RestRoom

RestRoom restroom;

uMutex<uStaticPriorityQ, uStaticPriorityQ> uPeriodicTask<uStaticPIQ> Philosopher {
    uDuration C1, C2;
    int id;

    void main() {
      restroom.Toilet( id, C1 );
      restroom.Wash( id, C2 );
    } // Philosopher::main
  public:
    Philosopher( int id, uDuration period, uDuration toilet, uDuration wash, uCluster &clust ) :
          uPeriodicBaseTask( period, uTime(0,0), uThisProcessor().uGetClock().uGetTime()+90, period, clust ),
//        uPeriodicBaseTask( period, uTime(0,0), uTime(0,0), period, clust),
          C1( toilet ), C2( wash ), id( id ) {
    } // Philosopher::Philosopher
}; // Philosopher

void uMain::main() {
    uDeadlineMonotonicStatic rq ;                // create real-time scheduler
    uRealTimeCluster RTClust( rq );             // create real-time cluster with scheduler
    uProcessor *p;
    {
      Philosopher t1( 1, 20, 2, 2, RTClust );
      Philosopher t2( 2, 30, 4, 3, RTClust );
      Philosopher t3( 3, 40, 6, 4, RTClust );
      Philosopher t4( 4, 50, 8, 5, RTClust );

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

      ::Start = uThisProcessor().uGetClock().uGetTime();
      p = new uProcessor( RTClust );                  // now create the processor to do the work
    }
    delete p;
    uCout << uAcquire << "successful completion" << endl << uRelease;
} // uMain::main

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

Generated by  Doxygen 1.6.0   Back to index