unit md_resource;

{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}

interface

uses
 sys_resource;

function kern_getrusage(who:Integer;rup:p_rusage):Integer;

implementation

uses
 ntapi,
 errno,
 time,
 md_time,
 kern_thr,
 kern_proc,
 vmparam,
 vm_map;

function pgtok(x:QWORD):QWORD; inline;
begin
 Result:=x*(PAGE_SIZE div 1024)
end;

function kern_getrusage(who:Integer;rup:p_rusage):Integer;
var
 td:p_kthread;

 user,syst:Int64;

 data:array[0..SizeOf(VM_COUNTERS)-1+7] of Byte;

 P_IO:PIO_COUNTERS;
 P_VM:PVM_COUNTERS;

 R:DWORD;

 vms:p_vmspace;
begin
 Result:=0;

 rup^:=Default(t_rusage);

 user:=0;
 syst:=0;

 Case who of
  RUSAGE_SELF:
    begin
     rup^.ru_nsignals:=p_proc.p_nsignals;
     rup^.ru_nvcsw   :=p_proc.p_nvcsw;
     rup^.ru_nivcsw  :=p_proc.p_nivcsw;

     vms:=p_proc.p_vmspace;

     rup^.ru_ixrss   :=pgtok(vms^.vm_tsize);
     rup^.ru_idrss   :=pgtok(vms^.vm_dsize);
     rup^.ru_isrss   :=pgtok(vms^.vm_ssize);

     P_IO:=Align(@data,8);
     P_IO^:=Default(IO_COUNTERS);
     R:=NtQueryInformationProcess(NtCurrentProcess,ProcessIoCounters,P_IO,SizeOf(IO_COUNTERS),nil);

     if (R=0) then
     begin
      rup^.ru_inblock:=P_IO^.ReadOperationCount;
      rup^.ru_oublock:=P_IO^.WriteOperationCount;
     end;

     P_VM:=Align(@data,8);
     P_VM^:=Default(VM_COUNTERS);
     R:=NtQueryInformationProcess(NtCurrentProcess,ProcessVmCounters,P_VM,SizeOf(VM_COUNTERS),nil);

     if (R=0) then
     begin
      rup^.ru_maxrss:=P_VM^.PeakWorkingSetSize div 1024;
      rup^.ru_majflt:=P_VM^.PageFaultCount;
     end;

     calcru_proc(@user,@syst);
    end;
  RUSAGE_THREAD:
    begin
     td:=curkthread;
     if (td=nil) then Exit(-1);

     rup^.ru_nsignals:=td^.td_ru.ru_nsignals;
     rup^.ru_nvcsw   :=td^.td_ru.ru_nvcsw;
     rup^.ru_nivcsw  :=td^.td_ru.ru_nivcsw;

     rup^.ru_inblock :=td^.td_ru.ru_inblock;
     rup^.ru_oublock :=td^.td_ru.ru_oublock;

     calcru_thread(@user,@syst);
    end;
   RUSAGE_CHILDREN:
    begin
     Exit(0);
    end
  else;
    Exit(EINVAL);
 end;

 UNIT_TO_TIMEVAL(@rup^.ru_utime,user);
 UNIT_TO_TIMEVAL(@rup^.ru_stime,syst);

 //ru_minflt
 //ru_nswap
 //ru_msgsnd
 //ru_msgrcv
end;

end.

