mirror of https://github.com/red-prig/fpPS4.git
334 lines
6.2 KiB
Plaintext
334 lines
6.2 KiB
Plaintext
unit kern_time;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
windows,
|
|
ntapi,
|
|
time;
|
|
|
|
procedure timevalfix(t1:ptimeval);
|
|
procedure timevaladd(t1,t2:ptimeval);
|
|
procedure timevalsub(t1,t2:ptimeval);
|
|
|
|
function cputick2usec(time:QWORD):QWORD; inline;
|
|
function get_unit_uptime:Int64;
|
|
procedure getmicrouptime(tvp:ptimeval);
|
|
procedure getnanotime(tp:Ptimespec);
|
|
|
|
function kern_clock_gettime_unit(clock_id:Integer;time:PInt64):Integer;
|
|
function kern_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer;
|
|
function kern_clock_getres(clock_id:Integer;tp:Ptimespec):Integer;
|
|
|
|
function sys_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer;
|
|
function sys_clock_getres(clock_id:Integer;tp:Ptimespec):Integer;
|
|
|
|
Procedure timeinit; //SYSINIT
|
|
|
|
implementation
|
|
|
|
uses
|
|
errno,
|
|
systm;
|
|
|
|
Const
|
|
UNIT_PER_SEC =10000000;
|
|
DELTA_EPOCH_IN_UNIT =116444736000000000;
|
|
POW10_7 =10000000;
|
|
POW10_9 =1000000000;
|
|
|
|
procedure timevalfix(t1:ptimeval);
|
|
begin
|
|
if (t1^.tv_usec < 0) then
|
|
begin
|
|
Dec(t1^.tv_sec);
|
|
Inc(t1^.tv_usec,1000000);
|
|
end;
|
|
if (t1^.tv_usec >= 1000000) then
|
|
begin
|
|
Inc(t1^.tv_sec);
|
|
Dec(t1^.tv_usec,1000000);
|
|
end;
|
|
end;
|
|
|
|
procedure timevaladd(t1,t2:ptimeval);
|
|
begin
|
|
Inc(t1^.tv_sec ,t2^.tv_sec);
|
|
Inc(t1^.tv_usec,t2^.tv_usec);
|
|
timevalfix(t1);
|
|
end;
|
|
|
|
procedure timevalsub(t1,t2:ptimeval);
|
|
begin
|
|
Dec(t1^.tv_sec ,t2^.tv_sec);
|
|
Dec(t1^.tv_usec,t2^.tv_usec);
|
|
timevalfix(t1);
|
|
end;
|
|
|
|
function cputick2usec(time:QWORD):QWORD; inline;
|
|
begin
|
|
Result:=time div 10;
|
|
end;
|
|
|
|
function mul_div_u64(m,d,v:QWORD):QWORD; sysv_abi_default; assembler; nostackframe;
|
|
asm
|
|
movq v,%rax
|
|
mulq m
|
|
divq d
|
|
end;
|
|
|
|
function get_unit_uptime:Int64;
|
|
var
|
|
pc:QWORD;
|
|
pf:QWORD;
|
|
begin
|
|
pc:=0;
|
|
pf:=1;
|
|
NtQueryPerformanceCounter(@pc,@pf);
|
|
|
|
if (pf=UNIT_PER_SEC) then
|
|
begin
|
|
Result:=pc;
|
|
end else
|
|
begin
|
|
Result:=mul_div_u64(UNIT_PER_SEC,pf,pc);
|
|
end;
|
|
end;
|
|
|
|
procedure getmicrouptime(tvp:ptimeval);
|
|
var
|
|
time:Int64;
|
|
begin
|
|
time:=get_unit_uptime;
|
|
tvp^.tv_sec :=(time div POW10_7);
|
|
tvp^.tv_usec:=(time mod POW10_7) div 10;
|
|
end;
|
|
|
|
type
|
|
tunittime=procedure(time:PInt64); stdcall;
|
|
|
|
var
|
|
_unittime:tunittime;
|
|
|
|
procedure unittime(time:PInt64);
|
|
var
|
|
h:HMODULE;
|
|
begin
|
|
if (_unittime=nil) then
|
|
begin
|
|
h:=GetModuleHandle('kernel32.dll');
|
|
Pointer(_unittime):=GetProcAddress(h,'GetSystemTimePreciseAsFileTime');
|
|
if (_unittime=nil) then
|
|
begin
|
|
Pointer(_unittime):=GetProcAddress(h,'GetSystemTimeAsFileTime');
|
|
end;
|
|
end;
|
|
_unittime(time);
|
|
end;
|
|
|
|
procedure calcru(user,syst:PInt64);
|
|
var
|
|
k:KERNEL_USER_TIMES;
|
|
begin
|
|
k:=Default(KERNEL_USER_TIMES);
|
|
NtQueryInformationProcess(NtCurrentProcess,
|
|
ProcessTimes,
|
|
@k,
|
|
SizeOf(KERNEL_USER_TIMES),
|
|
nil);
|
|
user^:=k.UserTime.QuadPart;
|
|
syst^:=k.KernelTime.QuadPart;
|
|
end;
|
|
|
|
procedure get_process_cputime(time:PInt64);
|
|
var
|
|
k:KERNEL_USER_TIMES;
|
|
begin
|
|
k:=Default(KERNEL_USER_TIMES);
|
|
NtQueryInformationProcess(NtCurrentProcess,
|
|
ProcessTimes,
|
|
@k,
|
|
SizeOf(KERNEL_USER_TIMES),
|
|
nil);
|
|
|
|
unittime(@k.ExitTime.QuadPart);
|
|
time^:=k.ExitTime.QuadPart-k.CreateTime.QuadPart;
|
|
end;
|
|
|
|
procedure get_thread_cputime(time:PInt64);
|
|
var
|
|
k:KERNEL_USER_TIMES;
|
|
begin
|
|
k:=Default(KERNEL_USER_TIMES);
|
|
NtQueryInformationThread(NtCurrentThread,
|
|
ThreadTimes,
|
|
@k,
|
|
SizeOf(KERNEL_USER_TIMES),
|
|
nil);
|
|
unittime(@k.ExitTime.QuadPart);
|
|
time^:=k.ExitTime.QuadPart-k.CreateTime.QuadPart;
|
|
end;
|
|
|
|
procedure getnanotime(tp:Ptimespec);
|
|
var
|
|
time:Int64;
|
|
begin
|
|
unittime(@time);
|
|
time:=time-DELTA_EPOCH_IN_UNIT;
|
|
tp^.tv_sec :=(time div POW10_7);
|
|
tp^.tv_nsec:=(time mod POW10_7)*100;
|
|
end;
|
|
|
|
function kern_clock_gettime_unit(clock_id:Integer;time:PInt64):Integer;
|
|
var
|
|
user,syst:Int64;
|
|
begin
|
|
Result:=0;
|
|
|
|
case clock_id of
|
|
CLOCK_REALTIME,
|
|
CLOCK_REALTIME_PRECISE,
|
|
CLOCK_REALTIME_FAST:
|
|
begin
|
|
unittime(@user);
|
|
user:=user-DELTA_EPOCH_IN_UNIT;
|
|
time^:=user;
|
|
end;
|
|
|
|
CLOCK_VIRTUAL:
|
|
begin
|
|
calcru(@user,@syst);
|
|
time^:=user;
|
|
end;
|
|
|
|
CLOCK_PROF:
|
|
begin
|
|
calcru(@user,@syst);
|
|
time^:=user+syst;
|
|
end;
|
|
|
|
CLOCK_MONOTONIC,
|
|
CLOCK_MONOTONIC_PRECISE,
|
|
CLOCK_MONOTONIC_FAST,
|
|
CLOCK_UPTIME,
|
|
CLOCK_UPTIME_PRECISE,
|
|
CLOCK_UPTIME_FAST,
|
|
CLOCK_EXT_NETWORK,
|
|
CLOCK_EXT_DEBUG_NETWORK,
|
|
CLOCK_EXT_AD_NETWORK,
|
|
CLOCK_EXT_RAW_NETWORK:
|
|
begin
|
|
time^:=get_unit_uptime;
|
|
end;
|
|
|
|
CLOCK_SECOND:
|
|
begin
|
|
unittime(@user);
|
|
user:=user-DELTA_EPOCH_IN_UNIT;
|
|
user:=user-(user mod POW10_7);
|
|
time^:=user;
|
|
end;
|
|
|
|
CLOCK_PROCTIME:
|
|
begin
|
|
get_process_cputime(time);
|
|
end;
|
|
|
|
CLOCK_THREAD_CPUTIME_ID:
|
|
begin
|
|
get_thread_cputime(time);
|
|
end
|
|
|
|
else
|
|
Result:=EINVAL;
|
|
end;
|
|
end;
|
|
|
|
function kern_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer;
|
|
var
|
|
time:Int64;
|
|
begin
|
|
time:=0;
|
|
Result:=kern_clock_gettime_unit(clock_id,@time);
|
|
if (Result=0) then
|
|
begin
|
|
tp^.tv_sec :=(time div POW10_7);
|
|
tp^.tv_nsec:=(time mod POW10_7)*100;
|
|
end;
|
|
end;
|
|
|
|
function kern_clock_getres(clock_id:Integer;tp:Ptimespec):Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
case clock_id of
|
|
CLOCK_REALTIME,
|
|
CLOCK_VIRTUAL,
|
|
CLOCK_PROF,
|
|
CLOCK_MONOTONIC,
|
|
CLOCK_UPTIME,
|
|
CLOCK_UPTIME_PRECISE,
|
|
CLOCK_UPTIME_FAST,
|
|
CLOCK_REALTIME_PRECISE,
|
|
CLOCK_REALTIME_FAST,
|
|
CLOCK_MONOTONIC_PRECISE,
|
|
CLOCK_MONOTONIC_FAST,
|
|
CLOCK_THREAD_CPUTIME_ID,
|
|
CLOCK_PROCTIME,
|
|
CLOCK_EXT_NETWORK,
|
|
CLOCK_EXT_DEBUG_NETWORK,
|
|
CLOCK_EXT_AD_NETWORK,
|
|
CLOCK_EXT_RAW_NETWORK:
|
|
begin
|
|
tp^.tv_sec :=0;
|
|
tp^.tv_nsec:=100;
|
|
end;
|
|
|
|
CLOCK_SECOND:
|
|
begin
|
|
tp^.tv_sec :=1;
|
|
tp^.tv_nsec:=0;
|
|
end;
|
|
|
|
else
|
|
Result:=EINVAL;
|
|
end;
|
|
end;
|
|
|
|
function sys_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer;
|
|
var
|
|
ats:timespec;
|
|
begin
|
|
Result:=kern_clock_gettime(clock_id,@ats);
|
|
if (Result=0) then
|
|
begin
|
|
Result:=copyout(@ats,tp,sizeof(ats));
|
|
end;
|
|
end;
|
|
|
|
function sys_clock_getres(clock_id:Integer;tp:Ptimespec):Integer;
|
|
var
|
|
ats:timespec;
|
|
begin
|
|
Result:=kern_clock_getres(clock_id,@ats);
|
|
if (Result=0) then
|
|
begin
|
|
Result:=copyout(@ats,tp,sizeof(ats));
|
|
end;
|
|
end;
|
|
|
|
Procedure timeinit;
|
|
var
|
|
min,max,cur:ULONG;
|
|
begin
|
|
NtQueryTimerResolution(@min,@max,@cur);
|
|
NtSetTimerResolution(max,True,@cur);
|
|
end;
|
|
|
|
end.
|
|
|
|
|