--
-- Copyright (c) 2020-2023, Adel Noureddine, Université de Pau et des Pays de l'Adour.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the
-- GNU General Public License v3.0 only (GPL-3.0-only)
-- which accompanies this distribution, and is available at:
-- https://www.gnu.org/licenses/gpl-3.0.en.html
--
-- Author : Adel Noureddine
--
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.String_Split; use GNAT;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with GNAT.OS_Lib; use GNAT.OS_Lib;
package body CPU_STAT_PID is
procedure Calculate_PID_Time (PID_Data : in out CPU_STAT_PID_Data; Is_Before : in Boolean) is
F : File_Type; -- File handle
File_Name : constant String := "/proc/" & Trim(Integer'Image(PID_Data.PID_Number), Ada.Strings.Left) & "/stat"; -- File name /proc/pid/stat
Subs : String_Split.Slice_Set; -- Used to slice the read data from stat file
Seps : constant String := " "; -- Seperator (space) for slicing string
Utime : Long_Integer; -- User time
Stime : Long_Integer; -- System time
begin
Open (F, In_File, File_Name);
String_Split.Create (S => Subs, -- Store sliced data in Subs
From => Get_Line (F), -- Read data to slice. We only need the first line of the stat file
Separators => Seps, -- Separator (here space)
Mode => String_Split.Multiple);
Close (F);
-- Reading cpu time from /proc/pid/stat
-- We only need utime and stime (user and system time)
-- utime is at index 13, stime at index 14 (assuming index starts at 0)
-- utime %lu : Amount of time that this process has been scheduled in user mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)). This includes guest time, guest_time (time spent running a virtual CPU, see below), so that applications that are not aware of the guest time field do not lose that time from their calculations.
-- stime %lu : Amount of time that this process has been scheduled in kernel mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK)).
-- Example of line: 25152 (java) S 12564 1685 1685 0 -1 1077960704 155132 412 478 2 11617 1816 0 0 20 0 61 0 2001362 3813126144 99139 18446744073709551615 4194304 4196724 140736365379696 140736365362368 140056419567211 0 0 4096 16796879 18446744073709551615 0 0 17 2 0 0 3 0 0 6294960 6295616 13131776 140736365387745 140736365388341 140736365388341 140736365391821 0
-- fscanf(fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu %lu", &cpu_process_data->utime, &cpu_process_data->stime);
Utime := Long_Integer'Value (String_Split.Slice (Subs, 14)); -- Index 13 in file. Slice function starts index at 1, so it is 14
Stime := Long_Integer'Value (String_Split.Slice (Subs, 15)); -- Index 14 in file. Slice function starts index at 1, so it is 15
if (Is_Before) then
PID_Data.Before_Time := Utime + Stime; -- Total time
else
PID_Data.After_Time := Utime + Stime; -- Total time
PID_Data.Monitored_Time := PID_Data.After_Time - PID_Data.Before_Time;
end if;
exception
when others =>
Put_Line ("Error reading " & File_Name & " file");
OS_Exit (0);
end;
end CPU_STAT_PID;