mpir/msvc/win_timing.c
2018-08-29 14:15:58 +01:00

251 lines
5.6 KiB
C

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <time.h>
#include <psapi.h>
#include <errno.h>
#include "win_timing.h"
double seconds_per_cycle = 0.0; /* seconds per processor cycle */
double seconds_per_tick; /* seconds per clock tick */
int need_cycles = 1;
char speed_time_string[] = { "Windows Performance Counter" };
int speed_precision = 100000;
double speed_cycletime;
static double start;
#if defined( _WIN64 )
# define current_processor_number GetCurrentProcessorNumber
#else
unsigned long current_processor_number(void)
{
__asm
{
mov eax,1
cpuid
shr ebx,24
mov eax, ebx
}
}
#endif
int lock_thread_to_core(void)
{ DWORD_PTR afp, afs;
if(GetProcessAffinityMask(GetCurrentProcess(), &afp, &afs))
{
afp &= (DWORD_PTR)(1 << current_processor_number());
if(SetThreadAffinityMask(GetCurrentThread(), afp))
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
int unlock_thread_from_core(void)
{ DWORD_PTR afp, afs;
if(GetProcessAffinityMask(GetCurrentProcess(), &afp, &afs))
{
if(SetThreadAffinityMask(GetCurrentThread(), afp))
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
void set_timing_cycles(void)
{
need_cycles = 1;
speed_cycletime = 1.0;
speed_precision = 100000;
}
void set_timing_seconds(void)
{
need_cycles = 0;
speed_cycletime = seconds_per_cycle;
speed_precision = 1000;
}
void init_timing(void)
{ unsigned long long cycles;
LARGE_INTEGER ll;
lock_thread_to_core();
cycles = __rdtsc();
Sleep(1000);
cycles = __rdtsc() - cycles;
unlock_thread_from_core();
seconds_per_cycle = 1.0 / (double)cycles;
QueryPerformanceFrequency(&ll);
seconds_per_tick = 1.0 / (double)ll.QuadPart;
QueryPerformanceCounter(&ll);
start = seconds_per_tick * ll.QuadPart;
set_timing_seconds();
}
void start_timing(void)
{
if(seconds_per_cycle == 0.0)
speed_time_init();
if(need_cycles)
{
lock_thread_to_core();
start = __rdtsc();
}
else
{ LARGE_INTEGER ll;
QueryPerformanceCounter(&ll);
start = seconds_per_tick * ll.QuadPart;
}
}
double end_timing(void)
{
if(need_cycles)
{ double t = (double)__rdtsc() - start;
unlock_thread_from_core();
return t;
}
else
{ LARGE_INTEGER ll;
QueryPerformanceCounter(&ll);
return seconds_per_tick * ll.QuadPart - start;
}
}
int get_processor_info(char *cpu_id, char *cpu_name, double *cycles_per_second)
{
DWORD mhz, bsize;
HKEY hKey;
if(RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
0, KEY_READ, &hKey ) != ERROR_SUCCESS)
return EXIT_FAILURE;
bsize = 4;
if(RegQueryValueEx(hKey, "~MHz", NULL, NULL, (LPBYTE) &mhz, &bsize) != ERROR_SUCCESS)
return EXIT_FAILURE;
bsize = _MAX_PATH;
if(RegQueryValueEx(hKey, "Identifier", NULL, NULL, cpu_id, &bsize) != ERROR_SUCCESS)
return EXIT_FAILURE;
bsize = _MAX_PATH;
if(RegQueryValueEx(hKey, "ProcessorNameString", NULL, NULL, cpu_name, &bsize) != ERROR_SUCCESS)
return EXIT_FAILURE;
*cycles_per_second = 1.0e6 * mhz;
return EXIT_SUCCESS;
}
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;
if(tv)
{
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
t = li.QuadPart;
t -= EPOCHFILETIME;
t /= 10;
tv->tv_sec = (long)(t / 1000000);
tv->tv_usec = (long)(t % 1000000);
}
if (tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
typedef union file_t
{ FILETIME ft;
long long lt;
} file_t;
int getrusage(int who, rusage *usage)
{
HANDLE proc_hand;
file_t c_time, x_time, s_time, u_time;
int cb = 0, err = -1;
if(who != RUSAGE_SELF)
{
errno = (who == RUSAGE_CHILDREN ? ENODATA : EINVAL);
return err;
}
proc_hand = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
if(GetProcessTimes(proc_hand, &(c_time.ft), &(x_time.ft), &(s_time.ft), &(u_time.ft)))
{
PROCESS_MEMORY_COUNTERS ctrs;
/* The units returned by GetProcessTimes are 100 nanoseconds */
u_time.lt = (u_time.lt + 5) / 10;
s_time.lt = (s_time.lt + 5) / 10;
usage->ru_utime.tv_sec = (long)(u_time.lt / 1000000ll);
usage->ru_stime.tv_sec = (long)(s_time.lt / 1000000ll);
usage->ru_utime.tv_usec = (long)(u_time.lt % 1000000ll);
usage->ru_stime.tv_usec = (long)(s_time.lt % 1000000ll);
if(GetProcessMemoryInfo(proc_hand, &ctrs, sizeof(ctrs)))
{
PERFORMANCE_INFORMATION perf_info;
GetPerformanceInfo(&perf_info, sizeof(perf_info));
usage->ru_maxrss = (DWORD) (ctrs.WorkingSetSize / perf_info.PageSize);
usage->ru_majflt = ctrs.PageFaultCount;
err = 0;
}
}
if(err)
errno = EACCES;
CloseHandle(proc_hand);
return err;
}
#if 0
int main(void)
{ char b1[_MAX_PATH], b2[_MAX_PATH];
unsigned long long cps;
if(get_processor_info(b1, b2, &cps) == EXIT_SUCCESS)
{
speed_time_init();
printf("\n%s", b1);
printf("\n%s", b2);
printf("\nSpeed: %lld", cps);
printf("\nSpeed: %.0f", 1.0 / seconds_per_cycle);
return 0;
}
else
return EXIT_FAILURE;
}
#endif