#include #include #define N_TICKS 1000 #if 1 #define CPUID _asm _emit 0x0f _asm _emit 0xa2 #define RDTSC _asm _emit 0x0f _asm _emit 0x31 #ifndef _WIN64 static int has_time_stamp_counter (void) { _asm { push ebx push ecx push edx pushfd mov eax,200000h pop ebx xor eax,ebx push eax popfd pushfd pop eax xor eax,ebx jz no_cpuid_instruction mov eax,1 CPUID shr edx,4 mov eax,1 and eax,edx no_cpuid_instruction: pop edx pop ecx pop ebx } } static void read_time_stamp_counter (LARGE_INTEGER *large_int_p) { _asm{ push ecx push edx mov ecx,large_int_p RDTSC mov dword ptr 0[ecx],eax mov dword ptr 4[ecx],edx pop edx pop ecx } } #else unsigned __int64 __rdtsc(void); #pragma intrinsic(__rdtsc) #endif # ifdef _WIN64 __int64 p_time=0; int g_time_hi=0,g_time_lo=0; extern void compute_profile_overhead (LARGE_INTEGER *large_int_p); # else int p_time_hi=0,p_time_lo=0,g_time_hi=0,g_time_lo=0; extern void compute_profile_overhead (LARGE_INTEGER *large_int_p) { _asm { jmp compute_profile_overhead_ profile_: push eax push edx RDTSC sub eax,g_time_lo sbb edx,g_time_hi add p_time_lo,eax adc p_time_hi,edx RDTSC mov g_time_hi,edx pop edx mov g_time_lo,eax pop eax ret compute_profile_overhead_: mov eax,large_int_p push ebx push ecx push edx push ebp xor ecx,ecx xor edx,edx mov ebx,100000 call profile_ mov p_time_lo,ecx mov p_time_hi,edx compute_profile_overhead_lp1: lea ebp,p_time_lo call profile_ add ecx,ecx add edx,edx sub ebx,1 jne compute_profile_overhead_lp1 mov ecx,p_time_lo mov edx,p_time_hi mov dword ptr 0[eax],ecx mov dword ptr 4[eax],edx xor ecx,ecx xor edx,edx mov ebx,100000 call profile_ mov p_time_lo,ecx mov p_time_hi,edx compute_profile_overhead_lp2: add ecx,ecx add edx,edx sub ebx,1 jne compute_profile_overhead_lp2 call profile_ mov ecx,p_time_lo mov edx,p_time_hi mov dword ptr 8[eax],ecx mov dword ptr 12[eax],edx pop ebp pop edx pop ecx pop ebx } } # endif #else extern int has_time_stamp_counter (void); extern void read_time_stamp_counter (LARGE_INTEGER *); extern void compute_profile_overhead (LARGE_INTEGER *); #endif #ifdef _WIN64 # define float_div(a,b) ((a)/(b)) #else double float_div (double a,double b) { _asm { fld a fdiv b } } #endif #define N_TIME_SAMPLES 40 #define N_PROFILE_SAMPLES 40 static void swap_bytes (unsigned char *p1,unsigned char *p2,int n) { while (n!=0){ unsigned char b; b=*p1; *p1=*p2; *p2=b; ++p1; ++p2; --n; } } #define qsort hsort static void hsort (void *a_,unsigned int high,unsigned int element_size,int compare (void*,void*)) { unsigned int low,father,son; unsigned char *a; a=(unsigned char*)a_; low=high/2; while (high>1){ father=low; for (;;){ son=2*father+1; if (son>=high) break; if (son==high-1){ if (compare (&a[element_size*father],&a[element_size*son])<0) swap_bytes (&a[element_size*son],&a[element_size*father],element_size); break; } if (compare (&a[element_size*son],&a[element_size*(son+1)])<0) ++son; if (compare (&a[element_size*father],&a[element_size*son])>=0) break; swap_bytes (&a[element_size*son],&a[element_size*father],element_size); father=son; } if (low>0){ --low; } else { --high; swap_bytes (&a[0],&a[element_size*high],element_size); } } } static int double_compare (const double *r1_p,const double *r2_p) { if (*r1_p<*r2_p) return -1; else if (*r1_p>*r2_p) return 1; else return 0; } static double compute_average_frequency (double time_results[]) { int n,begin_n,end_n; double sum; begin_n=N_TIME_SAMPLES>>2; end_n=N_TIME_SAMPLES-begin_n; sum=0.0; for (n=begin_n; nHighPart < large_int_p2->HighPart) return -1; else if (large_int_p1->HighPart > large_int_p2->HighPart) return 1; else if (large_int_p1->LowPart < large_int_p2->LowPart) return -1; else if (large_int_p1->LowPart > large_int_p2->LowPart) return 1; else return 0; } static double determine_cpu_clock_speed (double frequency) { LARGE_INTEGER begin_time0,begin_time,end_time; LARGE_INTEGER tsc_begin_time,tsc_end_time; double time_results [N_TIME_SAMPLES]; int n; for (n=0; n>2; end_n=N_PROFILE_SAMPLES-begin_n; for (n=begin_n; n>1)*100000.0); } static void set_thread_priority (HANDLE thread_handle,int old_priority,int new_priority) { if (old_priority!=THREAD_PRIORITY_ERROR_RETURN) SetThreadPriority (thread_handle,new_priority); } static void init_fpu (void) { #ifndef _WIN64 _asm { finit fldz fldz fldz fldz fldz fldz fldz } #endif } int measure_clock_speed_and_profile_overhead (double *clock_speed_p,double *profile_overhead_p) { LARGE_INTEGER performance_frequency; double frequency,average_frequency; HANDLE thread_handle; int priority; #ifndef _WIN64 if (!has_time_stamp_counter()){ *clock_speed_p=0.0; *profile_overhead_p=0.0; init_fpu(); /* for virtualpc */ return 1; } #endif thread_handle=GetCurrentThread(); priority=GetThreadPriority (thread_handle); set_thread_priority (thread_handle,priority,THREAD_PRIORITY_TIME_CRITICAL); performance_frequency.LowPart=0; performance_frequency.HighPart=0; if (!QueryPerformanceFrequency (&performance_frequency)){ set_thread_priority (thread_handle,priority,priority); *clock_speed_p=0.0; *profile_overhead_p=0.0; init_fpu(); /* for virtualpc */ return 2; } frequency = (double)performance_frequency.LowPart + (double)performance_frequency.HighPart * (65536.0*65536.0); average_frequency = determine_cpu_clock_speed (frequency); *clock_speed_p = float_div (average_frequency,1.0e6); *profile_overhead_p = determine_profile_overhead(); set_thread_priority (thread_handle,priority,priority); init_fpu(); /* for virtualpc */ return 0; }