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

RealTimeSchedule.cc

Go to the documentation of this file.
00001 /*
00002  * RealTimeSchedule.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 RealTimeSchedule.cc
00014  *
00015  * Implementation of the RealTimeSchedule class.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <assert_pp.h>
00021 
00022 #include <iostream>
00023 
00024 #include <time_util.h>
00025 
00026 #include "RealTimeSchedule.hh"
00027 
00028 #if !defined(min)
00029 /**
00030  * @param x First comparable value.
00031  * @param y Second comparable value.
00032  * @return The minimum of x and y.
00033  */
00034 #define min(x, y) ((x) < (y) ? (x) : (y))
00035 
00036 /**
00037  * @param x First comparable value.
00038  * @param y Second comparable value.
00039  * @return The maximum of x and y.
00040  */
00041 #define max(x, y) ((x) > (y) ? (x) : (y))
00042 #endif
00043 
00044 RealTimeSchedule::RealTimeSchedule(CORBA::ULong start,
00045                                    CORBA::ULong period,
00046                                    CORBA::ULong deadline,
00047                                    rts_reserve_mode_t reserve_mode,
00048                                    pid_t pid) :
00049     rts_Start(start),
00050     rts_Period(period),
00051     rts_Deadline(deadline),
00052     rts_ReserveMode(reserve_mode),
00053     rts_PID(pid)
00054 {
00055     require(deadline <= period);
00056 }
00057 
00058 void RealTimeSchedule::setParameters(const Broker::ScheduleParameters &sp)
00059     throw (Broker::DuplicateScheduleParameter,
00060            Broker::InvalidScheduleParameter,
00061            Broker::MissingScheduleParameter)
00062 {
00063     unsigned long long start = 0, period = ~0, deadline = ~0;
00064     unsigned int lpc;
00065     const char *str;
00066     pid_t pid = -1;
00067 
00068     for( lpc = 0; lpc < sp.length(); lpc++ )
00069     {
00070         if( strcasecmp(sp[lpc].name.in(), "reserve-mode") == 0 )
00071         {
00072             const char *str;
00073 
00074             if( sp[lpc].value >>= str )
00075             {
00076                 if( strcasecmp(str, "soft") == 0 )
00077                 {
00078                     this->rts_ReserveMode = RTS_RSV_SOFT;
00079                 }
00080                 else if( strcasecmp(str, "hard") == 0 )
00081                 {
00082                     this->rts_ReserveMode = RTS_RSV_HARD;
00083                 }
00084                 else
00085                 {
00086                     throw Broker::InvalidScheduleParameter(
00087                         "'reserve-mode' not 'hard' or 'soft'", sp[lpc]);
00088                 }
00089             }
00090             else
00091             {
00092                 throw Broker::InvalidScheduleParameter(
00093                         "'reserve-mode' not a string", sp[lpc]);
00094             }
00095         }
00096         else if( strcasecmp(sp[lpc].name.in(), "start") == 0 )
00097         {
00098             if( ((sp[lpc].value >>= str) && string_to_microsec(&start, str)) )
00099             {
00100             }
00101             else
00102             {
00103                 throw Broker::InvalidScheduleParameter("'start' is not a time",
00104                                                        sp[lpc]);
00105             }
00106         }
00107         else if( strcasecmp(sp[lpc].name.in(), "pid") == 0 )
00108         {
00109             CORBA::Long c_pid;
00110             const char *str;
00111 
00112             if( pid != -1 )
00113             {
00114                 throw Broker::DuplicateScheduleParameter("pid");
00115             }
00116             else if( sp[lpc].value >>= c_pid )
00117             {
00118                 pid = c_pid;
00119             }
00120             else if( (sp[lpc].value >>= str) &&
00121                      (sscanf(str, "%d", &pid) == 1) )
00122             {
00123             }
00124             else
00125             {
00126                 throw Broker::InvalidScheduleParameter("'pid' not a long",
00127                                                        sp[lpc]);
00128             }
00129             if( pid < 0 )
00130             {
00131                 pid = -1;
00132                 throw Broker::InvalidScheduleParameter("'pid' not a long",
00133                                                        sp[lpc]);
00134             }
00135         }
00136         else if( strcasecmp(sp[lpc].name.in(), "period") == 0 )
00137         {
00138             CORBA::ULong period_ul;
00139             
00140             if( period != ~0ULL )
00141             {
00142                 throw Broker::DuplicateScheduleParameter("period");
00143             }
00144             else if( sp[lpc].value >>= period_ul )
00145             {
00146                 period = period_ul;
00147             }
00148             else if( (sp[lpc].value >>= str) &&
00149                      string_to_microsec(&period, str) )
00150             {
00151             }
00152             else
00153             {
00154                 throw Broker::InvalidScheduleParameter(
00155                         "'period' is not a time",
00156                         sp[lpc]);
00157             }
00158         }
00159         else if( strcasecmp(sp[lpc].name.in(), "deadline") == 0 )
00160         {
00161             CORBA::ULong deadline_ul;
00162             
00163             if( deadline != ~0ULL )
00164             {
00165                 throw Broker::DuplicateScheduleParameter("deadline");
00166             }
00167             else if( sp[lpc].value >>= deadline_ul )
00168             {
00169                 deadline = deadline_ul;
00170             }
00171             else if( (sp[lpc].value >>= str) &&
00172                      string_to_microsec(&deadline, str) )
00173             {
00174             }
00175             else
00176             {
00177                 throw Broker::InvalidScheduleParameter(
00178                         "'deadline' is not a time",
00179                         sp[lpc]);
00180             }
00181         }
00182     }
00183     
00184     /* Make sure we have everything we need */
00185     if( period == ~0ULL )
00186     {
00187         throw Broker::MissingScheduleParameter("period");
00188     }
00189     if( pid == -1 )
00190     {
00191         throw Broker::MissingScheduleParameter("pid");
00192     }
00193     
00194     /* ... and derive the rest. */
00195     if( deadline == ~0ULL )
00196     {
00197         deadline = period;
00198     }
00199 
00200     this->rts_Start = start;
00201     this->rts_Deadline = deadline;
00202     this->rts_Period = period;
00203     this->rts_PID = pid;
00204 }
00205 
00206 RealTimeSchedule::~RealTimeSchedule()
00207 {
00208 }
00209 
00210 CORBA::ULong RealTimeSchedule::intersect(CORBA::ULong start, CORBA::ULong stop)
00211 {
00212     int starting_period_index, ending_period_index;
00213     CORBA::ULong retval = 0;
00214 
00215     require(start <= stop);
00216 
00217     /*
00218      * The strategy here is to compute the set of periods in this schedule that
00219      * overlap with the given time frame.  Then we simply add the all the ones
00220      * in the middle and the starting and ending periods which may be partially
00221      * covered by the time frame.
00222      */
00223 
00224     /* Compute the index of the first period. */
00225     starting_period_index = ((int)start - (int)this->rts_Start) /
00226         (int)this->rts_Period;
00227     /* The last intersected period is */
00228     if( stop < this->rts_Start )
00229     {
00230         /* ... before this schedule starts, do nothing. */
00231         ending_period_index = -1;
00232     }
00233     else
00234     {
00235         /*
00236          * in the middle.  (Since there is no stop time in the schedule, there
00237          * is always a middle)
00238          */
00239         ending_period_index = (stop - this->rts_Start - 1) / this->rts_Period;
00240     }
00241     /* The start of the intersection is */
00242     if( starting_period_index < 0 )
00243     {
00244         /*
00245          * ... before this schedules start time.  Therefore, the starting
00246          * period is completely covered.  We set the value to -1 here so that
00247          * the computation of periods in the middle will work properly.
00248          */
00249         starting_period_index = -1;
00250     }
00251     else
00252     {
00253         unsigned long long start_us, end_us;
00254 
00255         /*
00256          * ... possibly in the middle of a period.  Therefore, we need to
00257          * compute the absolute start of the intersecting period and
00258          */
00259         start_us = this->rts_Start +
00260             (this->rts_Period * starting_period_index);
00261         /* ... the absolute end of the intersecting period. */
00262         end_us = this->rts_Start +
00263             (this->rts_Period * starting_period_index) +
00264             this->rts_Deadline;
00265         /* Then add the part of the period that actually intersects. */
00266         retval += (CORBA::ULong)(min(stop, end_us) - max(start, start_us));
00267     }
00268     /* If the intersection covers several periods then */
00269     if( (starting_period_index + 1) <= (ending_period_index - 1) )
00270     {
00271         /* ... add those to the return value. */
00272         retval += (ending_period_index - starting_period_index - 1) *
00273             this->rts_Deadline;
00274     }
00275     /* Add to the return value if the intersection ends */
00276     if( ending_period_index < 0 )
00277     {
00278         /* ... before this schedule starts. */
00279     }
00280     else if( starting_period_index != ending_period_index )
00281     {
00282         unsigned long long start_us;
00283 
00284         /* ... at a period not covered by the previous cases (start/middle). */
00285         start_us = this->rts_Start + (this->rts_Period * ending_period_index);
00286         retval += (CORBA::ULong)(min(stop, start_us + this->rts_Deadline) -
00287                                  start_us);
00288     }
00289     return( retval );
00290 }

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