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

RTServerImpl.cc

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

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