View source with formatted comments or as raw
    1/*  Part of SWISH
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2015, VU University Amsterdam
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(procps,
   36	  [ procps_stat/1,		% -Stat
   37	    procps_stat/2,		% +Pid, -Stat
   38	    procps_thread_stat/2,	% ?Thread, -Stat
   39	    procps_status/1,		% -Status
   40	    procps_status/2		% +Pid, -Status
   41	  ]).   42:- if(exists_source(library(unix))).   43:- use_module(library(unix)).   44:- endif.   45
   46		 /*******************************
   47		 *	  /proc/[pid]/stat	*
   48		 *******************************/
   49
   50procps_stat(Stat) :-
   51	current_prolog_flag(pid, Pid),
   52	procps_stat(Pid, Stat).
   53procps_stat(Pid, Stat) :-
   54	atomic_list_concat(['/proc/', Pid, '/stat'], StatFile),
   55	stat_file_dict(StatFile, Stat).
   56
   57procps_thread_stat(Thread, Stat) :-
   58	current_prolog_flag(pid, Pid),
   59	thread_property(Thread, system_thread_id(TID)),
   60	atomic_list_concat(['/proc/', Pid, '/task/', TID, '/stat'], StatFile),
   61	stat_file_dict(StatFile, Stat).
   62
   63stat_file_dict(StatFile, Stat) :-
   64	setup_call_cleanup(
   65	    open(StatFile, read, In),
   66	    read_string(In, _, String),
   67	    close(In)),
   68	split_string(String, " ", " \n", Parts),
   69	parts_pairs(Parts, 1, Pairs),
   70	dict_pairs(Stat, stat, Pairs).
   71
   72parts_pairs([], _, []).
   73parts_pairs([H0|T0], I0, [H|T]) :-
   74	part_pair(H0, I0, H),
   75	I is I0+1,
   76	parts_pairs(T0, I, T).
   77
   78part_pair(String, I, Key-Value) :-
   79	stat_field(Key, I), !,
   80	stat_field_value(Key, String, Value).
   81part_pair(String, I, I-String).
   82
   83stat_field_value(comm, String, Command) :- !,
   84	sub_string(String, 1, _, 1, Command).
   85stat_field_value(state, String, Atom) :- !,
   86	atom_string(Atom, String).
   87stat_field_value(Field, String, Seconds) :-
   88	time_field(Field), !,
   89	number_string(ClockTicks, String),
   90	clockticks(TicksPerSec),
   91	Seconds is ClockTicks/TicksPerSec.
   92stat_field_value(Field, String, Bytes) :-
   93	page_field(Field), !,
   94	number_string(Pages, String),
   95	pagesize(BytesPerPage),
   96	Bytes is Pages*BytesPerPage.
   97stat_field_value(_, String, Number) :-
   98	number_string(Number, String).
   99
  100:- if(current_predicate(sysconf/1)).  101% the weird way to call sysconf confuses ClioPatria's cpack code
  102% analysis enough to accept this ...
  103term_expansion(clockticks(sysconf), Expansion) :-
  104	(   member(Sysconf, [sysconf(clk_tck(TicksPerSec))]),
  105	    call(Sysconf)
  106	->  Expansion = clockticks(TicksPerSec)
  107	;   Expansion = clockticks(100)
  108	).
  109term_expansion(pagesize(sysconf), Expansion) :-
  110	(   member(Sysconf, [sysconf(pagesize(Bytes))]),
  111	    call(Sysconf)
  112	->  Expansion = pagesize(Bytes)
  113	;   Expansion = pagesize(4096)
  114	).
  115clockticks(sysconf).
  116pagesize(sysconf).
  117:- else.  118clockticks(100).
  119pagesize(4096).
  120:- endif.  121
  122time_field(utime).
  123time_field(stime).
  124time_field(cutime).
  125time_field(cstime).
  126time_field(starttime).
  127
  128page_field(rss).
  129
  130stat_field(pid,			  1).
  131stat_field(comm,		  2).
  132stat_field(state,		  3).
  133stat_field(ppid,		  4).
  134stat_field(pgrp,		  5).
  135stat_field(session,		  6).
  136stat_field(tty_nr,		  7).
  137stat_field(tpgid,		  8).
  138stat_field(flags,		  9).
  139stat_field(minflt,		  10).
  140stat_field(cminflt,		  11).
  141stat_field(majflt,		  12).
  142stat_field(cmajflt,		  13).
  143stat_field(utime,		  14).
  144stat_field(stime,		  15).
  145stat_field(cutime,		  16).
  146stat_field(cstime,		  17).
  147stat_field(priority,		  18).
  148stat_field(nice,		  19).
  149stat_field(num_threads,		  20).
  150stat_field(itrealvalue,		  21).
  151stat_field(starttime,		  22).
  152stat_field(vsize,		  23).
  153stat_field(rss,			  24).
  154stat_field(rsslim,		  25).
  155stat_field(startcode,		  26).
  156stat_field(endcode,		  27).
  157stat_field(startstack,		  28).
  158stat_field(kstkesp,		  29).
  159stat_field(kstkeip,		  30).
  160stat_field(signal,		  31).
  161stat_field(blocked,		  32).
  162stat_field(sigignore,		  33).
  163stat_field(sigcatch,		  34).
  164stat_field(wchan,		  35).
  165stat_field(nswap,		  36).
  166stat_field(cnswap,		  37).
  167stat_field(exit_signal,		  38).
  168stat_field(processor,		  39).
  169stat_field(rt_priority,		  40).
  170stat_field(policy,		  41).
  171stat_field(delayacct_blkio_ticks, 42).
  172stat_field(guest_time,		  43).
  173stat_field(cguest_time,		  44).
  174
  175
  176		 /*******************************
  177		 *	/proc/[pid]/status	*
  178		 *******************************/
  179
  180procps_status(Stat) :-
  181	current_prolog_flag(pid, Pid),
  182	procps_status(Pid, Stat).
  183procps_status(Pid, Stat) :-
  184	atomic_list_concat(['/proc/', Pid, '/status'], StatFile),
  185	status_file_dict(StatFile, Stat).
  186
  187status_file_dict(StatFile, Status) :-
  188	setup_call_cleanup(
  189	    open(StatFile, read, In),
  190	    read_string(In, _, String),
  191	    close(In)),
  192	split_string(String, "\n", " \n", Lines),
  193	status_line_pairs(Lines, Pairs),
  194	dict_pairs(Status, status, Pairs).
  195
  196status_line_pairs([], []).
  197status_line_pairs([H0|T0], [Name-Value|T]) :-
  198	split_string(H0, ":", " \t", [NameS, ValueS]),
  199	string_lower(NameS, NameLS),
  200	atom_string(Name, NameLS),
  201	status_value(Name, ValueS, Value), !,
  202	status_line_pairs(T0, T).
  203status_line_pairs([_|T0], T) :-
  204	status_line_pairs(T0, T).
  205
  206status_value(state, ValueS, State) :- !,
  207	split_string(ValueS, " ", " ", [Vs|_]),
  208	atom_string(State, Vs).
  209status_value(Name, ValueS, Bytes) :-
  210	sub_atom(Name, 0, _, _, vm), !,
  211	split_string(ValueS, " ", " ", [Vs,"kB"]),
  212	number_string(Kb, Vs),
  213	Bytes is Kb*1024