home *** CD-ROM | disk | FTP | other *** search
/ PC User 1997 April / PCU_APR_97.ISO / utils / cpu / cpuinfo / source / cpuinf32 / speed.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-13  |  20.5 KB  |  742 lines

  1. /***************************************************************
  2. * C file:  Speed.c... for cpuinf32 DLL
  3. *
  4. *       This program has been developed by Intel Corporation.  
  5. *        You have Intel's permission to incorporate this code 
  6. *       into your product, royalty free.  Intel has various 
  7. *        intellectual property rights which it may assert under
  8. *       certain circumstances, such as if another manufacturer's
  9. *       processor mis-identifies itself as being "GenuineIntel"
  10. *        when the CPUID instruction is executed.
  11. *
  12. *       Intel specifically disclaims all warranties, express or
  13. *       implied, and all liability, including consequential and
  14. *        other indirect damages, for the use of this code, 
  15. *        including liability for infringement of any proprietary
  16. *        rights, and including the warranties of merchantability
  17. *        and fitness for a particular purpose.  Intel does not 
  18. *        assume any responsibility for any errors which may 
  19. *        appear in this code nor any responsibility to update it.
  20. *
  21. *  * Other brands and names are the property of their respective
  22. *    owners.
  23. *
  24. *  Copyright (c) 1995, Intel Corporation.  All rights reserved.
  25. ***************************************************************/
  26.  
  27. #include <windows.h>
  28. #include <stdio.h>
  29. #include <math.h>
  30. #include <limits.h>
  31.  
  32. #include "speed.h"
  33. #include "cpuid.h"
  34.  
  35. #define ROUND_THRESHOLD        6
  36.  
  37. // Tabs set at 4
  38. static struct FREQ_INFO GetCmosCpuSpeed();
  39. static struct FREQ_INFO GetRDTSCCpuSpeed();
  40. static struct FREQ_INFO GetBSFCpuSpeed(ulong cycles);
  41. static unsigned long diffTime64(unsigned long t1Hi, unsigned long t1Low, 
  42.                          unsigned long t2Hi, unsigned long t2Low, 
  43.                            unsigned long *tHi, unsigned long *tLow );
  44.  
  45. // Number of cycles needed to execute a single BSF instruction.
  46. //    Note that processors below i386(tm) are not supported.
  47. static ulong processor_cycles[] = {
  48.     00,  00,  00, 115, 47, 43, 
  49.     38,  38,  38, 38,  38, 38, 
  50. };
  51.  
  52.  
  53.  
  54. /***************************************************************
  55. * BOOL WINAPI DllMain()
  56. *
  57. * Inputs:    hDLL       - handle of DLL
  58. *           dwReason   - indicates why DLL called
  59. *           lpReserved - reserved
  60. *
  61. * Return Value: TRUE (always) 
  62. ***************************************************************/
  63.  
  64. BOOL WINAPI DllMain (HINSTANCE hDLL, 
  65.                      DWORD dwReason, 
  66.                      LPVOID lpReserved)
  67. {
  68.  
  69. return TRUE;
  70.  
  71. } // DllMain()
  72.  
  73. /***************************************************************
  74. * CpunormSpeed() -- Return the raw clock rate of the host CPU.
  75. *
  76. * Inputs:
  77. *    clocks:        0: Use default value for number of cycles
  78. *                   per BSF instruction.
  79. *               -1: Use CMos timer to get cpu speed.
  80. *               Positive Integer: Use clocks value for number
  81. *                   of cycles per BSF instruction.
  82. *
  83. * Returns:
  84. *        If error then return all zeroes in FREQ_INFO structure
  85. *        Else return FREQ_INFO structure containing calculated 
  86. *       clock frequency, normalized clock frequency, number of 
  87. *       clock cycles during test sampling, and the number of 
  88. *       microseconds elapsed during the sampling.
  89. ***************************************************************/
  90.  
  91. unsigned long cpunormspeed(int clocks)
  92. {
  93.     struct FREQ_INFO cpu_speed;
  94.     HKEY hKey;
  95.     LPBYTE ProcSpeed;
  96.     DWORD buflen, ret;
  97.  
  98.     if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey)) 
  99.     {
  100.         ProcSpeed = 0;
  101.         buflen = sizeof( ProcSpeed );
  102.         ret = RegQueryValueEx(hKey, "~MHz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen);
  103.         // If we don't succeed, try some other spellings.
  104.         if (ret != ERROR_SUCCESS) 
  105.             ret = RegQueryValueEx(hKey, "~Mhz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen);
  106.         if (ret != ERROR_SUCCESS) 
  107.             ret = RegQueryValueEx(hKey, "~mhz", NULL, NULL, (LPBYTE) &ProcSpeed, &buflen);
  108.         RegCloseKey(hKey);
  109.         if (ret == ERROR_SUCCESS) 
  110.             return (unsigned long)ProcSpeed;
  111.     }
  112.     cpu_speed = cpuspeed(clocks);
  113.     return cpu_speed.norm_freq;
  114. }
  115.  
  116. /***************************************************************
  117. * ProcessorCount() -- Return the number of CPU's on this machine.
  118. *
  119. * Inputs:
  120. *
  121. * Returns:
  122. *        count of the number of processors on this machine.
  123. ***************************************************************/
  124.  
  125. unsigned long ProcessorCount()
  126. {
  127.     DWORD ProcessAffinityMask, SystemAffinityMask, count;
  128.  
  129.     GetProcessAffinityMask(GetCurrentProcess(),    &ProcessAffinityMask, &SystemAffinityMask);    
  130.  
  131.     // count bits in the mask
  132.     for (count = 0; SystemAffinityMask != 0; count++)
  133.         SystemAffinityMask &= (SystemAffinityMask-1);
  134.  
  135.     return count;
  136. }
  137.  
  138. /***************************************************************
  139. * CpurawSpeed() -- Return the raw clock rate of the host CPU.
  140. *
  141. * Inputs:
  142. *    clocks:        0: Use default value for number of cycles
  143. *                   per BSF instruction.
  144. *               -1: Use CMos timer to get cpu speed (DOES NOT WORK FOR WINNT).
  145. *               Positive Integer: Use clocks value for number
  146. *                   of cycles per BSF instruction.
  147. *
  148. * Returns:
  149. *        If error then return all zeroes in FREQ_INFO structure
  150. *        Else return FREQ_INFO structure containing calculated 
  151. *       clock frequency, normalized clock frequency, number of 
  152. *       clock cycles during test sampling, and the number of 
  153. *       microseconds elapsed during the sampling.
  154. ***************************************************************/
  155.  
  156. unsigned long cpurawspeed(int clocks)
  157. {
  158.     struct FREQ_INFO cpu_speed;
  159.  
  160.     cpu_speed = cpuspeed(clocks);
  161.     return cpu_speed.raw_freq;
  162. }
  163.  
  164.  
  165. /***************************************************************
  166. * CpuSpeed() -- Return the raw clock rate of the host CPU.
  167. *
  168. * Inputs:
  169. *    clocks:        0: Use default value for number of cycles
  170. *                   per BSF instruction.
  171. *               -1: Use CMos timer to get cpu speed.
  172. *               Positive Integer: Use clocks value for number
  173. *                   of cycles per BSF instruction.
  174. *
  175. * Returns:
  176. *        If error then return all zeroes in FREQ_INFO structure
  177. *        Else return FREQ_INFO structure containing calculated 
  178. *       clock frequency, normalized clock frequency, number of 
  179. *       clock cycles during test sampling, and the number of 
  180. *       microseconds elapsed during the sampling.
  181. ***************************************************************/
  182.  
  183. struct FREQ_INFO cpuspeed(int clocks) 
  184. {
  185.     ulong  cycles;                    // Clock cycles elapsed 
  186.                                     //   during test
  187.     
  188.     ushort processor = wincpuid();    // Family of processor
  189.  
  190.     DWORD features = wincpufeatures();    // Features of Processor
  191.  
  192.     int manual=0;            // Specifies whether the user 
  193.                             //   manually entered the number of
  194.                             //   cycles for the BSF instruction.
  195.  
  196.     struct FREQ_INFO cpu_speed;        // Return structure for
  197.                                     //   cpuspeed
  198.  
  199.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  200.     
  201.     if ( processor & CLONE_MASK )
  202.         return cpu_speed;
  203.  
  204.     // Check for manual BSF instruction clock count
  205.     if (clocks <= 0) {
  206.         cycles = ITERATIONS * processor_cycles[processor];
  207.     }
  208.     else if (0 < clocks && clocks <= MAXCLOCKS)  {
  209.         cycles = ITERATIONS * clocks;
  210.         manual = 1;            // Toggle manual control flag.
  211.                             //   Note that this mode will not
  212.                             //      work properly with processors
  213.                             //   which can process multiple
  214.                             //   BSF instructions at a time.
  215.                             //   For example, manual mode
  216.                             //   will not work on a 
  217.                             //   PentiumPro(R)
  218.     }
  219.  
  220.     if ( ( features&0x00000010 ) && !(manual) ) {                        
  221.                         // On processors supporting the Read 
  222.                         //   Time Stamp opcode, compare elapsed
  223.                         //   time on the High-Resolution Counter
  224.                         //   with elapsed cycles on the Time 
  225.                         //   Stamp Register.
  226.         if ( clocks == 0 )
  227.             return GetRDTSCCpuSpeed();
  228.         else
  229.             return GetCmosCpuSpeed();
  230.     }
  231.     else if ( processor >= 3 ) {
  232.         return GetBSFCpuSpeed(cycles);
  233.     }
  234.  
  235.     return cpu_speed;
  236.  
  237. } // cpuspeed()
  238.  
  239.  
  240. static struct FREQ_INFO GetBSFCpuSpeed(ulong cycles)
  241. {
  242.     // If processor does not support time 
  243.     //   stamp reading, but is at least a 
  244.     //   386 or above, utilize method of 
  245.     //   timing a loop of BSF instructions 
  246.     //   which take a known number of cycles
  247.     //   to run on i386(tm), i486(tm), and
  248.     //   Pentium(R) processors.
  249.     LARGE_INTEGER t0,t1;            // Variables for High-
  250.                                     //   Resolution Performance
  251.                                     //   Counter reads
  252.  
  253.     ulong freq  =0;            // Most current frequ. calculation
  254.  
  255.     ulong  ticks;                    // Microseconds elapsed 
  256.                                     //   during test
  257.     
  258.     LARGE_INTEGER count_freq;        // High Resolution 
  259.                                     //   Performance Counter 
  260.                                     //   frequency
  261.  
  262.     int i;                        // Temporary Variable
  263.  
  264.     ulong current = 0;          // Variable to store time
  265.                                     //   elapsed during loop of
  266.                                     //   of BSF instructions
  267.  
  268.     ulong lowest  = ULONG_MAX;    // Since algorithm finds 
  269.                                     //   the lowest value out of
  270.                                     //   a set of samplings, 
  271.                                     //   this variable is set 
  272.                                     //   intially to the max 
  273.                                     //   unsigned long value). 
  274.                                     //   This guarantees that 
  275.                                     //   the initialized value 
  276.                                     //   is not later used as 
  277.                                     //   the least time through 
  278.                                     //   the loop.
  279.  
  280.     struct FREQ_INFO cpu_speed;
  281.  
  282.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  283.  
  284.     if ( !QueryPerformanceFrequency ( &count_freq ) )
  285.         return cpu_speed;
  286.  
  287.     for ( i = 0; i < SAMPLINGS; i++ ) { // Sample Ten times. Can
  288.                                      //   be increased or 
  289.                                      //   decreased depending
  290.                                      //   on accuracy vs. time
  291.                                      //   requirements
  292.  
  293.         QueryPerformanceCounter(&t0);    // Get start time
  294.  
  295.             _asm 
  296.             {
  297.                 
  298.                     mov eax, 80000000h    
  299.                     mov bx, ITERATIONS        
  300.                                 // Number of consecutive BSF 
  301.                                 //   instructions to execute. 
  302.                                 //   Set identical to 
  303.                                 //   nIterations constant in
  304.                                 //   speed.h
  305.                
  306.                 loop1:    bsf ecx,eax
  307.        
  308.                            dec    bx
  309.                         jnz    loop1
  310.             }
  311.                              
  312.         QueryPerformanceCounter(&t1);    // Get end time
  313.         current = (ulong) t1.LowPart - (ulong) t0.LowPart;    
  314.                                 // Number of external ticks is
  315.                                 //   difference between two
  316.                                 //   hi-res counter reads.
  317.  
  318.         if ( current < lowest )        // Take lowest elapsed
  319.             lowest = current;        //   time to account
  320.     }                                //   for some samplings
  321.                                         //   being interrupted
  322.                                         //   by other operations 
  323.          
  324.     ticks = lowest;
  325.  
  326.     // Note that some seemingly arbitrary mulitplies and
  327.     //   divides are done below. This is to maintain a 
  328.     //   high level of precision without truncating the 
  329.     //   most significant data. According to what value 
  330.     //   ITERATIIONS is set to, these multiplies and
  331.     //   divides might need to be shifted for optimal
  332.     //   precision.
  333.  
  334.     ticks = ticks * 100000;    
  335.                         // Convert ticks to hundred
  336.                         //   thousandths of a tick
  337.             
  338.     ticks = ticks / ( count_freq.LowPart/10 );        
  339.                         // Hundred Thousandths of a 
  340.                         //   Ticks / ( 10 ticks/second )
  341.                         //   = microseconds (us)
  342.         
  343.     if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )    
  344.         ticks++;                // Round up if necessary
  345.             
  346.     freq = cycles/ticks;        // Cycles / us  = MHz
  347.  
  348.     cpu_speed.raw_freq  = freq;
  349.     if ( cycles%ticks > ticks/2 )
  350.            freq++;                    // Round up if necessary    
  351.  
  352.     cpu_speed.in_cycles = cycles;    // Return variable structure
  353.     cpu_speed.ex_ticks  = ticks;    //   determined by one of 
  354.     cpu_speed.norm_freq = freq;
  355.  
  356.     return cpu_speed;
  357. }    
  358.  
  359. static struct FREQ_INFO GetRDTSCCpuSpeed()
  360. {
  361.     struct FREQ_INFO cpu_speed;
  362.     LARGE_INTEGER t0,t1;            // Variables for High-
  363.                                     //   Resolution Performance
  364.                                     //   Counter reads
  365.  
  366.     ulong freq  =0;            // Most current frequ. calculation
  367.     ulong freq2 =0;            // 2nd most current frequ. calc.
  368.     ulong freq3 =0;            // 3rd most current frequ. calc.
  369.     
  370.     ulong total;            // Sum of previous three frequency
  371.                             //   calculations
  372.  
  373.     int tries=0;            // Number of times a calculation has
  374.                             //   been made on this call to 
  375.                             //   cpuspeed
  376.  
  377.     ulong  total_cycles=0, cycles;    // Clock cycles elapsed 
  378.                                     //   during test
  379.     
  380.     ulong  stamp0, stamp1;            // Time Stamp Variable 
  381.                                     //   for beginning and end 
  382.                                     //   of test
  383.  
  384.     ulong  total_ticks=0, ticks;    // Microseconds elapsed 
  385.                                     //   during test
  386.     
  387.     LARGE_INTEGER count_freq;        // High Resolution 
  388.                                     //   Performance Counter 
  389.                                     //   frequency
  390.  
  391. #ifdef WIN32
  392.     int iPriority;
  393.     HANDLE hThread = GetCurrentThread();
  394. #endif // WIN32;
  395.  
  396.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  397.  
  398.     if ( !QueryPerformanceFrequency ( &count_freq ) )
  399.         return cpu_speed;
  400.  
  401.     // On processors supporting the Read 
  402.     //   Time Stamp opcode, compare elapsed
  403.     //   time on the High-Resolution Counter
  404.     //   with elapsed cycles on the Time 
  405.     //   Stamp Register.
  406.     
  407.     do {            // This do loop runs up to 20 times or
  408.                        //   until the average of the previous 
  409.                        //   three calculated frequencies is 
  410.                        //   within 1 MHz of each of the 
  411.                        //   individual calculated frequencies. 
  412.                     //   This resampling increases the 
  413.                     //   accuracy of the results since
  414.                     //   outside factors could affect this
  415.                     //   calculation
  416.             
  417.         tries++;        // Increment number of times sampled
  418.                         //   on this call to cpuspeed
  419.             
  420.         freq3 = freq2;    // Shift frequencies back to make
  421.         freq2 = freq;    //   room for new frequency 
  422.                         //   measurement
  423.  
  424.         QueryPerformanceCounter(&t0);    
  425.                         // Get high-resolution performance 
  426.                         //   counter time
  427.             
  428.         t1.LowPart = t0.LowPart;        // Set Initial time
  429.         t1.HighPart = t0.HighPart;
  430.  
  431. #ifdef WIN32
  432.         iPriority = GetThreadPriority(hThread);
  433.         if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
  434.         {
  435.             SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
  436.         }
  437. #endif // WIN32
  438.  
  439.            while ( (ulong)t1.LowPart - (ulong)t0.LowPart<50) {      
  440.                            // Loop until 50 ticks have 
  441.                            //   passed    since last read of hi-
  442.                         //     res counter. This accounts for
  443.                         //   overhead later.
  444.  
  445.             QueryPerformanceCounter(&t1);
  446.  
  447.             RDTSC;                        // Read Time Stamp
  448.             _asm {
  449.                 MOV stamp0, EAX
  450.             }
  451.         }
  452.             
  453.             
  454.         t0.LowPart = t1.LowPart;        // Reset Initial 
  455.         t0.HighPart = t1.HighPart;        //   Time
  456.  
  457.            while ((ulong)t1.LowPart-(ulong)t0.LowPart<1000 ) {
  458.                            // Loop until 1000 ticks have 
  459.                            //   passed    since last read of hi-
  460.                            //   res counter. This allows for
  461.                         //   elapsed time for sampling.
  462.                
  463.                 
  464.                QueryPerformanceCounter(&t1);
  465.                
  466.  
  467.             RDTSC;                        // Read Time Stamp
  468.             __asm {
  469.                 MOV stamp1, EAX
  470.             }
  471.         }
  472.  
  473.             
  474.  
  475. #ifdef WIN32
  476.         // Reset priority
  477.         if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
  478.         {
  479.             SetThreadPriority(hThread, iPriority);
  480.         }
  481. #endif // WIN32
  482.  
  483.            cycles = stamp1 - stamp0;    // Number of internal 
  484.                                     //   clock cycles is 
  485.                                     //   difference between 
  486.                                     //   two time stamp 
  487.                                     //   readings.
  488.  
  489.         ticks = (ulong) t1.LowPart - (ulong) t0.LowPart;    
  490.                                 // Number of external ticks is
  491.                                 //   difference between two
  492.                                 //   hi-res counter reads.
  493.     
  494.  
  495.         // Note that some seemingly arbitrary mulitplies and
  496.         //   divides are done below. This is to maintain a 
  497.         //   high level of precision without truncating the 
  498.         //   most significant data. According to what value 
  499.         //   ITERATIIONS is set to, these multiplies and
  500.         //   divides might need to be shifted for optimal
  501.         //   precision.
  502.  
  503.         ticks = ticks * 100000;    
  504.                             // Convert ticks to hundred
  505.                             //   thousandths of a tick
  506.             
  507.         ticks = ticks / ( count_freq.LowPart/10 );        
  508.                             // Hundred Thousandths of a 
  509.                             //   Ticks / ( 10 ticks/second )
  510.                             //   = microseconds (us)
  511.  
  512.         total_ticks += ticks;
  513.         total_cycles += cycles;
  514.  
  515.         if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
  516.             ticks++;            // Round up if necessary
  517.             
  518.         freq = cycles/ticks;    // Cycles / us  = MHz
  519.                                                 
  520.          if ( cycles%ticks > ticks/2 )
  521.                freq++;                // Round up if necessary
  522.               
  523.         total = ( freq + freq2 + freq3 );
  524.                             // Total last three frequency 
  525.                             //   calculations
  526.  
  527.     } while ( (tries < 3 ) ||         
  528.               (tries < 20)&&
  529.               ((abs(3 * freq -total) > 3*TOLERANCE )||
  530.                (abs(3 * freq2-total) > 3*TOLERANCE )||
  531.                (abs(3 * freq3-total) > 3*TOLERANCE )));    
  532.                     // Compare last three calculations to 
  533.                       //   average of last three calculations.        
  534.  
  535.     // Try one more significant digit.
  536.     freq3 = ( total_cycles * 10 ) / total_ticks;
  537.     freq2 = ( total_cycles * 100 ) / total_ticks;
  538.  
  539.  
  540.     if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
  541.         freq3++;
  542.  
  543.     cpu_speed.raw_freq = total_cycles / total_ticks;
  544.     cpu_speed.norm_freq = cpu_speed.raw_freq;
  545.  
  546.     freq = cpu_speed.raw_freq * 10;
  547.     if( (freq3 - freq) >= ROUND_THRESHOLD )
  548.         cpu_speed.norm_freq++;
  549.  
  550.     cpu_speed.ex_ticks = total_ticks;
  551.     cpu_speed.in_cycles = total_cycles;
  552.  
  553.     return cpu_speed;
  554. }
  555.  
  556. int GetCmosTick(void)
  557. {
  558.     int tick = 0;
  559.  
  560.     // __asm    mov ah, 02h
  561.     // __asm    int 1Ah
  562.     // __asm    mov al, dh
  563.     // __asm    and ax, 000Fh  
  564.  
  565.     __asm  xor ax, ax
  566.     __asm  out 070h, al
  567.  
  568.     __asm  xor ax, ax
  569.     __asm  in  al, 071h
  570.  
  571.     // _outp( 0x70, offset );
  572.     // base = _inp( 0x71 ); 
  573.  
  574. // value returned in ax by function
  575.  
  576.     __asm     mov word ptr tick, ax
  577.  
  578.     return tick;
  579. }
  580.  
  581. //***************************************************************
  582. //
  583. // Function: cpuTimeStamp
  584. //
  585. //        Returns the pentium cpu time stamp in 2 32 bit unsigned longs
  586. //
  587. //    Notes: maintains a flag to make sure the cpu supports the RDTSC instruction.  There is
  588. //        the overhead of checking the cpu the first time afterwhich the time consumed in 
  589. //        checking the flag is very minimal.  You could adjust the count but then you would
  590. //        have to do 64bit math.  ugh.
  591. //
  592. //***************************************************************
  593. unsigned long cpuTimeStamp(unsigned long *hi, unsigned long *low)
  594. {
  595.     unsigned long ulHi = 0L;
  596.     unsigned long ulLow = 0L;
  597.     __asm {
  598.         ;RDTSC
  599.         _emit 0Fh
  600.         _emit 31h
  601.         mov ulLow, eax
  602.         mov ulHi, edx
  603.     }        
  604.  
  605.     *hi = ulHi;
  606.     *low = ulLow;
  607.  
  608.     return ulLow;        
  609. }    
  610.  
  611.  
  612. //#define ABS_TICK(a,b)  (b<a)?b+60-a:b-a
  613. // since I am only interested in single ticks
  614. #define ABS_TICK(a,b)  (b<a)?b+10-a:b-a
  615.  
  616. static struct FREQ_INFO GetCmosCpuSpeed()
  617. {
  618.     unsigned long     t1Low, t1High, t2Low, t2High, tResLow, tResHigh;
  619.     int    timeStart, timeStop, lapseTime;
  620.     unsigned long   temp;
  621.     unsigned long   temp1;
  622.     struct FREQ_INFO cpu_speed;
  623.     unsigned long   cpuSpeed = 0l;
  624. #ifdef WIN32
  625.     HANDLE    hThread = GetCurrentThread();
  626.     int        iPriority;
  627. #endif // WIN32
  628.     
  629.  
  630.     memset(&cpu_speed, 0x00, sizeof(cpu_speed));
  631.  
  632.     // This loop waits for the next tick
  633.     // so that we begin speed test on a tick edge
  634. #ifdef WIN32
  635.         iPriority = GetThreadPriority(hThread);
  636.         if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
  637.         {
  638.             SetThreadPriority(hThread, iPriority+1);
  639.         }
  640. #endif // WIN32
  641.  
  642.     timeStart = GetCmosTick();
  643.     for(;;)
  644.     {
  645.         timeStop = GetCmosTick();
  646.         if (  ABS_TICK(timeStart,timeStop) > 0 )
  647.         {
  648.             cpuTimeStamp(&t1High, &t1Low);
  649.             break;    
  650.         }    
  651.     }
  652.  
  653.     timeStart = timeStop;
  654.  
  655.     for(;;)
  656.     {
  657.         timeStop = GetCmosTick();
  658.         if (  ABS_TICK(timeStart,timeStop) > 0 )
  659.         {
  660.             cpuTimeStamp(&t2High, &t2Low);
  661.             break;    
  662.         }    
  663.     }
  664.  
  665. #ifdef WIN32
  666.         // Set thread priority back.
  667.         if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
  668.         {
  669.             SetThreadPriority(hThread, iPriority);
  670.         }
  671. #endif // WIN32
  672.  
  673.     diffTime64(t1High, t1Low, t2High, t2Low, &tResHigh, &tResLow );
  674.     lapseTime = ABS_TICK(timeStart,timeStop);
  675.  
  676.     cpuSpeed = tResLow; ///lapseTime; 
  677.     cpu_speed.in_cycles = tResLow;        // Cycles count since we in this routine
  678.  
  679.     //round to nearest digit
  680.     temp =  cpuSpeed/1000000;     
  681.     temp1 = cpuSpeed/100000;  
  682.     temp = temp * 10;  // realign with last digit = zero
  683.  
  684.     cpuSpeed = cpuSpeed/1000000; // cpuSpeed/1000000;
  685.     cpu_speed.raw_freq = cpuSpeed;    
  686.  
  687.     if( (temp1 - temp) >= ROUND_THRESHOLD )
  688.         cpuSpeed++;
  689.     
  690.     cpu_speed.norm_freq = cpuSpeed;    
  691.     cpu_speed.ex_ticks = (timeStop - timeStart) * 1000000;
  692.  
  693.     return cpu_speed;            
  694. }
  695.  
  696. //***************************************************************
  697. //
  698. // Function: diffTime64
  699. //
  700. //        Calculates the difference of a 64 bit time as represented by
  701. //        two 32 bit unsigned longs
  702. //
  703. //***************************************************************
  704. unsigned long diffTime64(unsigned long t1Hi, unsigned long t1Low, 
  705.                          unsigned long t2Hi, unsigned long t2Low, 
  706.                            unsigned long *tHi, unsigned long *tLow )
  707. {
  708.     unsigned long xl, xh;
  709.  
  710. /*
  711.     *tHi = t2Hi - t1Hi;
  712.  
  713.     if( t1Low > t2Low )
  714.     {
  715.         *tLow = t1Low - t2Low;
  716.         *tLow = ULONG_MAX - *tLow;         
  717.         *tHi -= 1;
  718.  
  719.     } else {
  720.         *tLow = t2Low - t1Low;
  721.     }
  722. */
  723.  
  724.     __asm {
  725.         mov eax, t2Low
  726.         mov ebx, t1Low
  727.         sub eax, ebx
  728.         mov xl, eax
  729.         mov eax, t2Hi
  730.         mov ebx, t1Hi
  731.         sbb eax, ebx
  732.         mov xh, eax
  733.     }
  734.  
  735.     *tLow = xl;
  736.     *tHi  = xh;
  737.  
  738.     return *tLow;
  739.  
  740. }    
  741.  
  742.