00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
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 
00034 
00035 
00036 
00037 
00038 typedef signed long long int cycle_time;
00039 
00040 
00041 
00042 
00043 typedef double us_time;
00044 
00045 
00046 
00047 
00048 static double MHZ;
00049 
00050 #ifdef WIN32
00051 
00052 
00053 
00054 
00055 
00056 
00057 #define MHZ_SLOP 5
00058 #else
00059 
00060 
00061 
00062 
00063 
00064 #define MHZ_SLOP 2
00065 #endif
00066 
00067 
00068 
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 
00079 
00080 
00081 
00082 
00083 static inline us_time cycle_to_us (cycle_time c)
00084 {
00085   return c / (us_time)MHZ;
00086 }
00087 
00088 
00089 
00090 
00091 
00092 
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 
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 
00114 
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 
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         
00141         
00142         us_start = get_timeval_us ();
00143         cycle_start = rdtsc ();
00144         
00145         
00146 
00147 
00148 
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         
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             
00221         }
00222         else
00223         {
00224             total -= diff;
00225         }
00226         last = curr;
00227     } while( total > 0 );
00228 }