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

RTServerImpl.cc

Go to the documentation of this file.
00001 /*
00002  * RTServerImpl.cc
00003  *
00004  * Copyright (c) 2003 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 RTServerImpl.cc
00014  *
00015  * Implementation of the RTServerImpl class.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <stdlib.h>
00021 #include <assert_pp.h>
00022 
00023 #include <iostream>
00024 
00025 #include <sys/time.h>
00026 #include <sys/resource.h>
00027 #include <unistd.h>
00028 
00029 #include "RTServerImpl.hh"
00030 
00031 /* Note: Most of this was harvested from hourglass. */
00032 
00033 /**
00034  * Type used for cycle counter values.
00035  */
00036 typedef signed long long int cycle_time;
00037 
00038 /**
00039  * Type used for time value in microseconds.
00040  */
00041 typedef double us_time;
00042 
00043 /**
00044  * The CPU frequency for this machine, in megahertz.
00045  */
00046 static double MHZ;
00047 
00048 #ifdef WIN32
00049 /**
00050  * The acceptable difference in successive guesses of the machines Mhz.
00051  * Unfortunately, win2k needs a higher value than usual.
00052  *
00053  * @sa FindMHZ
00054  */
00055 #define MHZ_SLOP 5
00056 #else
00057 /**
00058  * The acceptable difference in successive guesses of the machines Mhz.
00059  *
00060  * @sa FindMHZ
00061  */
00062 #define MHZ_SLOP 2
00063 #endif
00064 
00065 /**
00066  * @return The current value of the x86 timestamp counter.
00067  */
00068 static inline cycle_time rdtsc (void)
00069 {
00070   cycle_time d;
00071   __asm__ __volatile__ ("rdtsc" : "=A" (d) );
00072   return d;
00073 }
00074 
00075 /**
00076  * Convert a cycle count value generated by rdtsc to a microsecond value.
00077  *
00078  * @param c The cycle value to convert.
00079  * @return The 'c' value converted to microseconds.
00080  */
00081 static inline us_time cycle_to_us (cycle_time c)
00082 {
00083   return c / (us_time)MHZ;
00084 }
00085 
00086 /**
00087  * Convert a microsecond value to cycle count value.
00088  *
00089  * @param us The microsecond value to convert.
00090  * @return The 'us' value converted to a cycle count.
00091  */
00092 static inline cycle_time us_to_cycle (us_time us)
00093 {
00094   return (cycle_time)us * (cycle_time)MHZ;
00095 }
00096 
00097 /**
00098  * @return The current time of day in microseconds.
00099  */
00100 static us_time get_timeval_us(void)
00101 {
00102   struct timeval tv;
00103   us_time t;
00104   
00105   gettimeofday (&tv, NULL);
00106   t = tv.tv_usec + (1000000 * tv.tv_sec);
00107   return t;
00108 }
00109 
00110 /**
00111  * @param d A double value.
00112  * @return The absolute value of d.
00113  */
00114 static double my_fabs (double d)
00115 {
00116   if (d < 0) {
00117     return -d;
00118   } else {
00119     return d;
00120   }
00121 }
00122 
00123 /**
00124  * @return The detected Mhz for the machine where this is running.
00125  */
00126 static double FindMHZ(void)
00127 {
00128     double last_freq, freq = 0;
00129     int i;
00130     int good = 0;
00131     us_time us_start, us_stop, us_diff;
00132     cycle_time cycle_start, cycle_stop, cycle_diff;
00133 
00134     setpriority(PRIO_PROCESS, 0, 20);
00135     
00136     for( i = 0; i < 100; i++ )
00137     {
00138         // estimate MHz
00139         
00140         us_start = get_timeval_us ();
00141         cycle_start = rdtsc ();
00142         
00143         /*
00144          * ugh -- sleeping permits some laptops to power down their
00145          * processors, which screws up the measurements -- so busy-wait
00146          * instead
00147          */
00148 #if 0
00149         usleep (1000);
00150 #else
00151         {
00152             volatile int x;
00153             
00154             for (x=0; x < 5*1000*1000; x++);
00155         }
00156 #endif
00157         
00158         us_stop = get_timeval_us ();
00159         cycle_stop = rdtsc ();
00160         
00161         us_diff = us_stop - us_start;
00162         cycle_diff = cycle_stop - cycle_start;
00163         
00164         last_freq = freq;
00165         freq = cycle_diff / us_diff;
00166         
00167         // wait for three successive values within range
00168         
00169         if (my_fabs (last_freq - freq) < MHZ_SLOP) {
00170             good++;
00171             if (good == 3) {
00172                 setpriority(PRIO_PROCESS, 0, 0);
00173                 return freq;
00174             }
00175         } else {
00176             good = 0;
00177         }
00178     }
00179     
00180     cerr << "couldn't determine MHz of this processor: try reducing\n";
00181     cerr << "machine load.\n";
00182     
00183     exit (EXIT_FAILURE);
00184 }
00185 
00186 RTServerImpl::RTServerImpl(CORBA::ULong deadline_us,
00187                            const CORBA::ULong *compute_us,
00188                            unsigned int compute_us_length)
00189 {
00190     require(compute_us != NULL);
00191     
00192     this->rts_Deadline = deadline_us;
00193     this->rts_Compute.data = compute_us;
00194     this->rts_Compute.length = compute_us_length;
00195     this->rts_Compute.index = 0;
00196     if( MHZ == 0.0 )
00197     {
00198         MHZ = FindMHZ();
00199         cerr << "CPU frequency: " << MHZ << "Mhz" << endl;
00200     }
00201 }
00202 
00203 void RTServerImpl::Periodic(void)
00204     throw (CORBA::SystemException)
00205 {
00206     cycle_time last, curr, diff, total;
00207 
00208     total = us_to_cycle(this->rts_Compute.data[this->rts_Compute.index]);
00209     this->rts_Compute.index = ((this->rts_Compute.index + 1) %
00210                                this->rts_Compute.length);
00211     last = rdtsc();
00212     do {
00213         curr = rdtsc();
00214         diff = curr - last;
00215         if( diff > us_to_cycle(1.0) )
00216         {
00217             curr = rdtsc();
00218             /* gap... */
00219         }
00220         else
00221         {
00222             total -= diff;
00223         }
00224         last = curr;
00225     } while( total > 0 );
00226 }

Generated on Mon Dec 1 16:29:07 2003 for CPU Broker by doxygen 1.3.4