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 }