Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

BasicDelegate.cc

Go to the documentation of this file.
00001 /*
00002  * BasicDelegate.cc
00003  *
00004  * Copyright (c) 2003, 2004 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file BasicDelegate.cc
00014  *
00015  * Implementation of the BasicDelegate class.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <math.h>
00021 #include <iostream>
00022 
00023 #include <assert_pp.h>
00024 
00025 #include <rk_stub.h>
00026 
00027 #include "BasicDelegate.hh"
00028 
00029 using namespace std;
00030 
00031 BasicDelegate::BasicDelegate(const char *name,
00032                              unsigned long period,
00033                              unsigned long deadline) :
00034     bd_Period(period), bd_Deadline(deadline)
00035 {
00036     require(name != NULL);
00037     require(deadline <= period);
00038 
00039     this->bd_AdviseDrop = 0;
00040     /* Create the fake process. */
00041     this->bd_PID = rk_stub_mk_pid(name,
00042                                   this,
00043                                   cxx_delegate_precall,
00044                                   cxx_delegate_postcall);
00045     
00046     /* Build up the parameter lists. */
00047     this->bd_CPUSchedule.length(3);
00048     this->bd_CPUSchedule[0].name = "period";
00049     this->bd_CPUSchedule[0].value <<= (CORBA::ULong)period;
00050     this->bd_CPUSchedule[1].name = "deadline";
00051     this->bd_CPUSchedule[1].value <<= (CORBA::ULong)deadline;
00052     this->bd_CPUSchedule[2].name = "pid";
00053     this->bd_CPUSchedule[2].value <<= this->bd_PID;
00054     this->bd_TaskDescription.length(1);
00055     this->bd_TaskDescription[0].name = "name";
00056     this->bd_TaskDescription[0].value <<= name;
00057 }
00058 
00059 BasicDelegate::~BasicDelegate()
00060 {
00061 }
00062 
00063 rk_stub_precall_retval_t BasicDelegate::precall(void)
00064 {
00065     rk_stub_precall_retval_t retval;
00066 
00067     require(this->bd_AdviseDrop >= 0);
00068 
00069     /* Check if we need to do a drop. */
00070     if( this->bd_AdviseDrop > 0 )
00071     {
00072         this->bd_AdviseDrop -= 1;
00073         retval = RKSP_DROP;
00074     }
00075     else
00076     {
00077         rk_stub_getrusage(this->bd_PID, &this->bd_RUStart);
00078         rk_clock_gettime(CLOCK_REALTIME, &this->bd_Start);
00079         retval = RKSP_OK;
00080     }
00081 
00082     return( retval );
00083 }
00084 
00085 void BasicDelegate::postcall(void)
00086 {
00087     long long start_us, end_us, diff_us;
00088     struct rusage ru_end;
00089     struct timespec end;
00090     float periods;
00091     
00092     require(!CORBA::is_nil(this->bd_Advocate.in()));
00093     
00094     rk_stub_getrusage(this->bd_PID, &ru_end);
00095     rk_clock_gettime(CLOCK_REALTIME, &end);
00096 
00097     /* Figure out how long it took, in microseconds, to process the data. */
00098     start_us = timespec_to_microsec(&this->bd_Start);
00099     end_us = timespec_to_microsec(&end);
00100     diff_us = end_us - start_us;
00101 
00102     cout << "start: " << start_us
00103          << "; end: " << end_us
00104          << "; diff: " << diff_us
00105          << endl;
00106 
00107     /*
00108      * Now convert the microseconds value to a float value that
00109      * Broker::RealTimeAdvocate::ReportCPU will understand.
00110      *
00111      * First, compute how much time it took between the start of the period
00112      * and the deadline.
00113      */
00114     periods = (float)(diff_us % this->bd_Deadline) / (float)this->bd_Deadline;
00115     cout << "periods: " << periods << endl;
00116     if( periods == 0.0 )
00117     {
00118         /*
00119          * Add one if the method finished exactly on time.  (Probably only
00120          * happens in the simulator...)
00121          */
00122         periods += 1.0;
00123     }
00124     /* ... and then add in any full periods that were used. */
00125     periods +=
00126         (float)(diff_us - (periods * this->bd_Deadline)) /
00127         (float)this->bd_Period;
00128     cout << "nperiods: " << periods << endl;
00129     if( periods > 1.0 )
00130     {
00131         /* We overran the deadline, drop the data periods that were overrun. */
00132         this->bd_AdviseDrop = ((int)floorf(periods + 0.99)) - 1;
00133     }
00134 
00135     start_us = this->bd_RUStart.ru_utime.tv_usec;
00136     start_us += this->bd_RUStart.ru_utime.tv_sec * 1000000;
00137     end_us = ru_end.ru_utime.tv_usec;
00138     end_us += ru_end.ru_utime.tv_sec * 1000000;
00139     diff_us = end_us - start_us;
00140     try
00141     {
00142         Broker::CPUReserve cr;
00143 
00144         /* Send our report to the advocate. */
00145         cr.Period = this->bd_Period;
00146         cr.Compute = diff_us;
00147         this->bd_Advocate->ReportCPU(cr, cr, this->bd_KeyedReportParameters);
00148     }
00149     catch(Broker::InvalidStatus &is)
00150     {
00151         cout << "Exception: " << is << endl;
00152         exit(1);
00153     }
00154     catch(CORBA::SystemException &se)
00155     {
00156         cout << "CORBA Exception: " << se << endl;
00157         exit(1);
00158     }
00159     catch(...)
00160     {
00161         cout << "Unhandled exception" << endl;
00162     }
00163 }

Generated on Fri Oct 22 07:50:24 2004 for CPU Broker by  doxygen 1.3.9.1