On Wed, Jul 04, 2012 at 08:14:26AM -0500, Jonathan Nieder wrote:
> Alessandro Ghedini wrote:
> 
> > ulatencyd embeds a not so up-to-date version of libprocps because it uses 
> > some
> > of its internal symbols, and
> 
> Thanks.  Which internal symbols?  Maybe they could be exposed, or
> maybe some other part of the API provides the same functionality.

Actually, after a little inspection, it's not really about internal symbols but
more about actual changes to the sources. It seems to me that most changes
concern support for cgroups, but I may very well be wrong.

See attached diff against upstream procps version 3.2.8, which is the version
that, AFAICT, ulatencyd embeds.

Cheers

-- 
perl -E '$_=q;$/= @{[@_]};and s;\S+;<inidehG ordnasselA>;eg;say~~reverse'
diff -bruN procps-3.2.8.orig/proc/alloc.c /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/alloc.c
--- procps-3.2.8.orig/proc/alloc.c	2012-07-04 16:36:07.572291071 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/alloc.c	2012-07-04 16:37:32.104710221 +0200
@@ -6,6 +6,7 @@
 // See file COPYING for information on distribution conditions.
 
 #include <stdlib.h>
+#include <string.h>
 #include <stdio.h>
 #include "alloc.h"
 
@@ -26,6 +27,7 @@
     if (size == 0)
         ++size;
     p = malloc(size);
+    memset(p, 0, size);
     if (!p) {
 	fprintf(stderr, "xmalloc: malloc(%d) failed", size);
 	perror(NULL);
diff -bruN procps-3.2.8.orig/proc/readproc.c /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/readproc.c
--- procps-3.2.8.orig/proc/readproc.c	2012-07-04 16:36:07.572291071 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/readproc.c	2012-07-04 16:37:32.104710221 +0200
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <string.h>
+#include <limits.h>
 #include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
@@ -85,63 +86,68 @@
     long Threads = 0;
     long Tgid = 0;
     long Pid = 0;
+    int hash = 0;
+    int isupgid = 0;
 
   static const unsigned char asso[] =
     {
-      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-      61, 61, 61, 61, 61, 61, 61, 61, 15, 61,
-      61, 61, 61, 61, 61, 61, 30,  3,  5,  5,
-      61,  5, 61,  8, 61, 61,  3, 61, 10, 61,
-       6, 61, 13,  0, 30, 25,  0, 61, 61, 61,
-      61, 61, 61, 61, 61, 61, 61,  3, 61, 13,
-       0,  0, 61, 30, 61, 25, 61, 61, 61,  0,
-      61, 61, 61, 61,  5, 61,  0, 61, 61, 61,
-       0, 61, 61, 61, 61, 61, 61, 61
+      66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+      66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+      66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+      66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+      66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+      66, 66, 66, 66, 66, 66, 66, 66,  0, 66,
+      66, 66, 66, 66, 66, 66,  3, 30, 20, 30,
+      66, 25, 66, 20, 66, 66, 30, 66, 25, 66,
+       0, 66,  8, 10,  3, 18,  5, 66, 66, 66,
+      66, 66, 66, 66, 66, 66, 66,  3, 66, 10,
+       0,  0, 66, 25, 66,  5, 66, 66, 66, 25,
+      66,  5, 66, 66,  0, 66,  0,  0, 66, 66,
+      25, 66, 66, 66, 66, 66, 66, 66
     };
 
     static const status_table_struct table[] = {
-      F(VmStk)
+      F(Pid)
       NUL NUL
-      F(State)
+      F(Threads)
+      NUL
+      F(PPid)
+      NUL NUL
+      F(Tgid)
       NUL
-      F(VmExe)
       F(ShdPnd)
+      NUL NUL
+      F(State)
       NUL
-      F(VmData)
+      F(VmStk)
+      NUL NUL
+      F(Uid)
       NUL
-      F(Name)
+      F(VmSize)
       NUL NUL
       F(VmRSS)
-      NUL NUL
-      F(VmLck)
-      NUL NUL NUL
+      NUL
       F(Gid)
-      F(Pid)
-      NUL NUL NUL
-      F(VmSize)
       NUL NUL
-      F(VmLib)
-      NUL NUL
-      F(PPid)
-      NUL
-      F(SigCgt)
+      F(VmData)
       NUL
-      F(Threads)
+      F(Groups)
+      NUL NUL NUL NUL
       F(SigPnd)
+      NUL NUL
+      F(SigBlk)
       NUL
+      F(VmLib)
+      NUL NUL NUL NUL
+      F(VmLck)
+      NUL NUL NUL NUL
+      F(Name)
+      NUL NUL NUL NUL
       F(SigIgn)
-      NUL
-      F(Uid)
-      NUL NUL NUL NUL NUL NUL NUL NUL NUL
-      NUL NUL NUL NUL NUL
-      F(Tgid)
       NUL NUL NUL NUL
-      F(SigBlk)
-      NUL NUL NUL
+      F(VmExe)
+      NUL NUL NUL NUL
+      F(SigCgt)
     };
 
 #undef F
@@ -157,6 +163,9 @@
     P->vm_exe  = 0;
     P->vm_lib  = 0;
     P->nlwp    = 0;
+    P->nsupgid = 0;
+    P->supgid = NULL;
+    P->supgrp = NULL;
     P->signal[0] = '\0';  // so we can detect it as missing for very old kernels
 
     goto base;
@@ -173,7 +182,9 @@
         // examine a field name (hash and compare)
     base:
         if(unlikely(!*S)) break;
-        entry = table[63 & (asso[S[3]] + asso[S[2]] + asso[S[0]])];
+        hash = asso[S[3]] + asso[S[2]] + asso[S[0]];
+        if (hash > 65) continue;
+        entry = table[hash];
         colon = strchr(S, ':');
         if(unlikely(!colon)) break;
         if(unlikely(colon[1]!='\t')) break;
@@ -271,6 +282,21 @@
         P->sgid = strtol(S,&S,10);
         P->fgid = strtol(S,&S,10);
         continue;
+    case_Groups:
+        isupgid = 0;
+        if (*S != '\n'){ // Is there any supplementary group ?
+          P->supgid = (int *) xmalloc(0x0004 * sizeof(int));
+          int vctsize = 0x0004;
+          while (S[1] != '\n' && isupgid<INT_MAX){ // There is one blank before '\n'
+            if (isupgid == vctsize){
+              vctsize *= 2;
+              P->supgid = (int *)xrealloc(P->supgid,vctsize * sizeof(int));
+            }
+            P->supgid[isupgid++] = strtol(S,&S,10);
+            P->nsupgid++;
+          }
+        }
+        continue;
     case_VmData:
         P->vm_data = strtol(S,&S,10);
         continue;
@@ -407,7 +433,7 @@
 /*    fprintf(stderr, "statm2proc converted %d fields.\n",num); */
 }
 
-static int file2str(const char *directory, const char *what, char *ret, int cap) {
+int file2str(const char *directory, const char *what, char *ret, int cap) {
     static char filename[80];
     int fd, num_read;
 
@@ -421,7 +447,7 @@
     return num_read;
 }
 
-static char** file2strvec(const char* directory, const char* what) {
+char** file2strvec_ext(const char* directory, const char* what, char terminator) {
     char buf[2048];	/* read buf bytes at a time */
     char *p, *rbuf = 0, *endbuf, **q, **ret;
     int fd, tot = 0, n, c, end_of_file = 0;
@@ -442,7 +468,7 @@
 		free(rbuf);
 	    return NULL;	/* read error */
 	}
-	if (end_of_file && buf[n-1])		/* last read char not null */
+        if (end_of_file && buf[n-1] != terminator)		/* last read char not null */
 	    buf[n++] = '\0';			/* so append null-terminator */
 	rbuf = xrealloc(rbuf, tot + n);		/* allocate more memory */
 	memcpy(rbuf + tot, buf, n);		/* copy buffer into it */
@@ -457,9 +483,12 @@
     }
     endbuf = rbuf + tot;			/* count space for pointers */
     align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1));
-    for (c = 0, p = rbuf; p < endbuf; p++)
+    for (c = 0, p = rbuf; p < endbuf; p++) {
+        if (*p == terminator)
+          *p = 0;
     	if (!*p)
 	    c += sizeof(char*);
+    }
     c += sizeof(char*);				/* one extra for NULL term */
 
     rbuf = xrealloc(rbuf, tot + c + align);	/* make room for ptrs AT END */
@@ -475,6 +504,10 @@
     return ret;
 }
 
+char** file2strvec(const char* directory, const char* what) {
+  return file2strvec_ext(directory, what, '\0');
+}
+
 // warning: interface may change
 int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
     char name[32];
@@ -589,6 +622,13 @@
         }
     }
 
+    if (flags & PROC_FILLSUPGRP && p->nsupgid > 0){
+        allocsupgrp(p);
+        int i;
+        for (i=0; i < p->nsupgid; i++)
+            memcpy(p->supgrp[i], group_from_gid(p->supgid[i]), P_G_SZ);
+    }
+
     if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG))	/* read+parse /proc/#/cmdline */
 	p->cmdline = file2strvec(path, "cmdline");
     else
@@ -599,6 +639,17 @@
     else
         p->environ = NULL;
     
+    if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP)) {
+	p->cgroup = file2strvec_ext(path, "cgroup", '\n'); 	/* read /proc/#/cgroup */
+    	if(p->cgroup && *p->cgroup) {
+		int i = strlen(*p->cgroup);
+		if( (*p->cgroup)[i-1]=='\n' )
+			(*p->cgroup)[i-1] = ' '; //little hack to remove trailing \n
+	}
+    }
+    else
+	p->cgroup = NULL;
+    
     return p;
 next_proc:
     return NULL;
@@ -672,6 +723,13 @@
         }
     }
 
+    if (flags & PROC_TASKSUPGRP && t->nsupgid > 0){
+        allocsupgrp(t);
+        int i;
+        for (i=0; i < t->nsupgid; i++)
+            memcpy(t->supgrp[i], group_from_gid(t->supgid[i]), P_G_SZ);
+    }
+
 #if 0
     if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG))	/* read+parse /proc/#/cmdline */
 	t->cmdline = file2strvec(path, "cmdline");
@@ -686,7 +744,7 @@
     t->cmdline = p->cmdline;  // better not free these until done with all threads!
     t->environ = p->environ;
 #endif
-
+    t->cgroup = p->cgroup;
     t->ppid = p->ppid;  // ought to put the per-task ppid somewhere
 
     return t;
@@ -777,6 +835,7 @@
 
   saved_p = p;
   if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
+  else memset(p, 0, sizeof *p);
 
   for(;;){
     // fills in the path, plus p->tid and p->tgid
@@ -805,6 +864,7 @@
 
   saved_t = t;
   if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */
+  else memset(t, 0, sizeof *t);
 
   // 1. got to fake a thread for old kernels
   // 2. for single-threaded processes, this is faster (but must patch up stuff that differs!)
@@ -886,6 +946,29 @@
     }
 }
 
+// allocate memory for supgrp
+void allocsupgrp(proc_t *p) {
+    if (!p || p->nsupgid == 0) return;
+    p->supgrp = (char**)xmalloc(p->nsupgid * sizeof(char*));
+    int i;
+    for (i=0; i<p->nsupgid; i++)
+      p->supgrp[i] = (char*)xmalloc(P_G_SZ * sizeof(char));
+}
+
+// free memory allocated for supgrp
+void freesupgrp(proc_t *p) {
+    int i;
+    if(!p->supgid)
+      return;
+    for (i=0; i<p->nsupgid; i++)
+      if (p->supgrp && p->supgrp[i])
+        free(p->supgrp[i]);
+    free(p->supgid);
+    free(p->supgrp);
+    p->supgid = NULL;
+    p->supgrp = NULL;
+}
+
 // deallocate the space allocated by readproc if the passed rbuf was NULL
 void freeproc(proc_t* p) {
     if (!p)	/* in case p is NULL */
@@ -896,9 +979,38 @@
 	free((void*)*p->cmdline);
     if (p->environ)
 	free((void*)*p->environ);
+  if (p->cgroup)
+	  free((void*)*p->cgroup);
+  if (p->supgid)
+  	free(p->supgid);
+
+  //printf("frp: %p\n", p);
     free(p);
 }
 
+// deallocate the space allocated by readproc if the passed rbuf was NULL
+void freeproc_light(proc_t* p) {
+    if (!p)	/* in case p is NULL */
+	return;
+    /* ptrs are after strings to avoid copying memory when building them. */
+    /* so free is called on the address of the address of strvec[0]. */
+  if (p->cmdline)
+    free((void*)*p->cmdline);
+  if (p->environ)
+    free((void*)*p->environ);
+  if (p->cgroup)
+    free((void*)*p->cgroup);
+
+  if (p->supgid)
+  	free(p->supgid);
+  p->cmdline = NULL;
+  p->environ = NULL;
+  p->cgroup = NULL;
+  p->supgid = NULL;
+  
+  //printf("frp: %p\n", p);
+}
+
 
 //////////////////////////////////////////////////////////////////////////////////
 void look_up_our_self(proc_t *p) {
@@ -942,6 +1054,8 @@
     else
 	PT = openproc(flags);
     va_end(ap);
+    if (!PT)
+      return 0;
     do {					/* read table: */
 	tab = xrealloc(tab, (n+1)*sizeof(proc_t*));/* realloc as we go, using */
 	tab[n] = readproc_direct(PT, NULL);     /* final null to terminate */
@@ -1034,7 +1148,7 @@
  * and filled out proc_t structure.
  */
 proc_t * get_proc_stats(pid_t pid, proc_t *p) {
-	static char path[PATH_MAX], sbuf[1024];
+	static char path[32], sbuf[1024];
 	struct stat statbuf;
 
 	sprintf(path, "/proc/%d", pid);
diff -bruN procps-3.2.8.orig/proc/readproc.h /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/readproc.h
--- procps-3.2.8.orig/proc/readproc.h	2012-07-04 16:36:07.568290991 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/readproc.h	2012-07-04 16:37:32.108710229 +0200
@@ -38,107 +38,111 @@
 typedef struct proc_t {
 // 1st 16 bytes
     int
-        tid,		// (special)       task id, the POSIX thread ID (see also: tgid)
-    	ppid;		// stat,status     pid of parent process
+        tid,		//!< (special)       task id, the POSIX thread ID (see also: tgid)
+    	ppid;		//!< stat,status     pid of parent process
     unsigned
-        pcpu;           // stat (special)  %CPU usage (is not filled in by readproc!!!)
+        pcpu;           //!< stat (special)  %CPU usage (is not filled in by readproc!!!)
     char
-    	state,		// stat,status     single-char code for process state (S=sleeping)
-    	pad_1,		// n/a             padding
-    	pad_2,		// n/a             padding
-    	pad_3;		// n/a             padding
-// 2nd 16 bytes
+    	state,		//!< stat,status     single-char code for process state (S=sleeping)
+    	pad_1,		//!< n/a             padding
+    	pad_2,		//!< n/a             padding
+    	pad_3;		//!< n/a             padding
+//!< 2nd 16 bytes
     unsigned long long
-	utime,		// stat            user-mode CPU time accumulated by process
-	stime,		// stat            kernel-mode CPU time accumulated by process
-// and so on...
-	cutime,		// stat            cumulative utime of process and reaped children
-	cstime,		// stat            cumulative stime of process and reaped children
-	start_time;	// stat            start time of process -- seconds since 1-1-70
+	utime,		//!< stat            user-mode CPU time accumulated by process
+	stime,		//!< stat            kernel-mode CPU time accumulated by process
+//!< and so on...
+	cutime,		//!< stat            cumulative utime of process and reaped children
+	cstime,		//!< stat            cumulative stime of process and reaped children
+	start_time;	//!< stat            start time of process -- seconds since 1-1-70
 #ifdef SIGNAL_STRING
     char
-	// Linux 2.1.7x and up have 64 signals. Allow 64, plus '\0' and padding.
-	signal[18],	// status          mask of pending signals, per-task for readtask() but per-proc for readproc()
-	blocked[18],	// status          mask of blocked signals
-	sigignore[18],	// status          mask of ignored signals
-	sigcatch[18],	// status          mask of caught  signals
-	_sigpnd[18];	// status          mask of PER TASK pending signals
+	//!< Linux 2.1.7x and up have 64 signals. Allow 64, plus '\0' and padding.
+	signal[18],	//!< status          mask of pending signals, per-task for readtask() but per-proc for readproc()
+	blocked[18],	//!< status          mask of blocked signals
+	sigignore[18],	//!< status          mask of ignored signals
+	sigcatch[18],	//!< status          mask of caught  signals
+	_sigpnd[18];	//!< status          mask of PER TASK pending signals
 #else
     long long
-	// Linux 2.1.7x and up have 64 signals.
-	signal,		// status          mask of pending signals, per-task for readtask() but per-proc for readproc()
-	blocked,	// status          mask of blocked signals
-	sigignore,	// status          mask of ignored signals
-	sigcatch,	// status          mask of caught  signals
-	_sigpnd;	// status          mask of PER TASK pending signals
+	//!< Linux 2.1.7x and up have 64 signals.
+	signal,		//!< status          mask of pending signals, per-task for readtask() but per-proc for readproc()
+	blocked,	//!< status          mask of blocked signals
+	sigignore,	//!< status          mask of ignored signals
+	sigcatch,	//!< status          mask of caught  signals
+	_sigpnd;	//!< status          mask of PER TASK pending signals
 #endif
     unsigned KLONG
-	start_code,	// stat            address of beginning of code segment
-	end_code,	// stat            address of end of code segment
-	start_stack,	// stat            address of the bottom of stack for the process
-	kstk_esp,	// stat            kernel stack pointer
-	kstk_eip,	// stat            kernel instruction pointer
-	wchan;		// stat (special)  address of kernel wait channel proc is sleeping in
+	start_code,	//!< stat            address of beginning of code segment
+	end_code,	//!< stat            address of end of code segment
+	start_stack,	//!< stat            address of the bottom of stack for the process
+	kstk_esp,	//!< stat            kernel stack pointer
+	kstk_eip,	//!< stat            kernel instruction pointer
+	wchan;		//!< stat (special)  address of kernel wait channel proc is sleeping in
     long
-	priority,	// stat            kernel scheduling priority
-	nice,		// stat            standard unix nice level of process
-	rss,		// stat            resident set size from /proc/#/stat (pages)
-	alarm,		// stat            ?
-    // the next 7 members come from /proc/#/statm
-	size,		// statm           total # of pages of memory
-	resident,	// statm           number of resident set (non-swapped) pages (4k)
-	share,		// statm           number of pages of shared (mmap'd) memory
-	trs,		// statm           text resident set size
-	lrs,		// statm           shared-lib resident set size
-	drs,		// statm           data resident set size
-	dt;		// statm           dirty pages
+	priority,	//!< stat            kernel scheduling priority
+	nice,		//!< stat            standard unix nice level of process
+	rss,		//!< stat            resident set size from /proc/#/stat (pages)
+	alarm,		//!< stat            ?
+    //!< the next 7 members come from /proc/#/statm
+	size,		//!< statm           total # of pages of memory
+	resident,	//!< statm           number of resident set (non-swapped) pages (4k)
+	share,		//!< statm           number of pages of shared (mmap'd) memory
+	trs,		//!< statm           text resident set size
+	lrs,		//!< statm           shared-lib resident set size
+	drs,		//!< statm           data resident set size
+	dt;		//!< statm           dirty pages
     unsigned long
-	vm_size,        // status          same as vsize in kb
-	vm_lock,        // status          locked pages in kb
-	vm_rss,         // status          same as rss in kb
-	vm_data,        // status          data size
-	vm_stack,       // status          stack size
-	vm_exe,         // status          executable size
-	vm_lib,         // status          library size (all pages, not just used ones)
-	rtprio,		// stat            real-time priority
-	sched,		// stat            scheduling class
-	vsize,		// stat            number of pages of virtual memory ...
-	rss_rlim,	// stat            resident set size limit?
-	flags,		// stat            kernel flags for the process
-	min_flt,	// stat            number of minor page faults since process start
-	maj_flt,	// stat            number of major page faults since process start
-	cmin_flt,	// stat            cumulative min_flt of process and child processes
-	cmaj_flt;	// stat            cumulative maj_flt of process and child processes
+	vm_size,        //!< status          same as vsize in kb
+	vm_lock,        //!< status          locked pages in kb
+	vm_rss,         //!< status          same as rss in kb
+	vm_data,        //!< status          data size
+	vm_stack,       //!< status          stack size
+	vm_exe,         //!< status          executable size
+	vm_lib,         //!< status          library size (all pages, not just used ones)
+	rtprio,		//!< stat            real-time priority
+	sched,		//!< stat            scheduling class
+	vsize,		//!< stat            number of pages of virtual memory ...
+	rss_rlim,	//!< stat            resident set size limit?
+	flags,		//!< stat            kernel flags for the process
+	min_flt,	//!< stat            number of minor page faults since process start
+	maj_flt,	//!< stat            number of major page faults since process start
+	cmin_flt,	//!< stat            cumulative min_flt of process and child processes
+	cmaj_flt;	//!< stat            cumulative maj_flt of process and child processes
     char
-	**environ,	// (special)       environment string vector (/proc/#/environ)
-	**cmdline;	// (special)       command line string vector (/proc/#/cmdline)
+	**environ,	//!< (special)       environment string vector (/proc/#/environ)
+	**cmdline;	//!< (special)       command line string vector (/proc/#/cmdline)
     char
-	// Be compatible: Digital allows 16 and NT allows 14 ???
-    	euser[P_G_SZ],	// stat(),status   effective user name
-    	ruser[P_G_SZ],	// status          real user name
-    	suser[P_G_SZ],	// status          saved user name
-    	fuser[P_G_SZ],	// status          filesystem user name
-    	rgroup[P_G_SZ],	// status          real group name
-    	egroup[P_G_SZ],	// status          effective group name
-    	sgroup[P_G_SZ],	// status          saved group name
-    	fgroup[P_G_SZ],	// status          filesystem group name
-    	cmd[16];	// stat,status     basename of executable file in call to exec(2)
+	//!< Be compatible: Digital allows 16 and NT allows 14 ???
+    	euser[P_G_SZ],	//!< stat(),status   effective user name
+    	ruser[P_G_SZ],	//!< status          real user name
+    	suser[P_G_SZ],	//!< status          saved user name
+    	fuser[P_G_SZ],	//!< status          filesystem user name
+    	rgroup[P_G_SZ],	//!< status          real group name
+    	egroup[P_G_SZ],	//!< status          effective group name
+    	sgroup[P_G_SZ],	//!< status          saved group name
+    	fgroup[P_G_SZ],	//!< status          filesystem group name
+    	**supgrp, //!< status        supplementary groups
+    	cmd[32];	//!< stat,status     basename of executable file in call to exec(2)
     struct proc_t
-	*ring,		// n/a             thread group ring
-	*next;		// n/a             various library uses
+	*ring,		//!< n/a             thread group ring
+	*next;		//!< n/a             various library uses
     int
-	pgrp,		// stat            process group id
-	session,	// stat            session id
-	nlwp,		// stat,status     number of threads, or 0 if no clue
-	tgid,		// (special)       task group ID, the POSIX PID (see also: tid)
-	tty,		// stat            full device number of controlling terminal
-        euid, egid,     // stat(),status   effective
-        ruid, rgid,     // status          real
-        suid, sgid,     // status          saved
-        fuid, fgid,     // status          fs (used for file access only)
-	tpgid,		// stat            terminal process group id
-	exit_signal,	// stat            might not be SIGCHLD
-	processor;      // stat            current (or most recent?) CPU
+	pgrp,		//!< stat            process group id
+	session,	//!< stat            session id
+	nlwp,		//!< stat,status     number of threads, or 0 if no clue
+	tgid,		//!< (special)       task group ID, the POSIX PID (see also: tid)
+	tty,		//!< stat            full device number of controlling terminal
+        euid, egid,     //!< stat(),status   effective
+        ruid, rgid,     //!< status          real
+        suid, sgid,     //!< status          saved
+        fuid, fgid,     //!< status          fs (used for file access only)
+	tpgid,		//!< stat            terminal process group id
+	nsupgid,	//!< status        number of supplementary groups
+	*supgid,	//!< status        supplementary gid's
+	exit_signal,	//!< stat            might not be SIGCHLD
+	processor;      //!< stat            current (or most recent?) CPU
+    	char **cgroup;  //!< cgroup	   current cgroup, looks like a classic filepath
 } proc_t;
 
 // PROCTAB: data structure holding the persistent information readproc needs
@@ -197,6 +201,12 @@
 // clean-up open files, etc from the openproc()
 extern void closeproc(PROCTAB* PT);
 
+// allocate memory for supgrp
+extern void allocsupgrp(proc_t *p);
+
+// free memory allocated for supgrp
+extern void freesupgrp(proc_t *p);
+
 // retrieve the next process matching the criteria set by the openproc()
 extern proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p);
 extern proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict t);
@@ -209,6 +219,7 @@
 // deallocate space allocated by readproc
 
 extern void freeproc(proc_t* p);
+extern void freeproc_light(proc_t* p);
 
 //fill out a proc_t for a single task
 extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
@@ -236,8 +247,11 @@
 #define PROC_FILLSTAT        0x0040 // read stat -- currently unconditional
 #define PROC_FILLWCHAN       0x0080 // look up WCHAN name
 #define PROC_FILLARG         0x0100 // alloc and fill in `cmdline'
+#define PROC_FILLCGROUP      0x0200 // alloc and fill in `cgroup`
+#define PROC_FILLSUPGRP      0x0400 // resolve supplementary group id number -> group name
+#define PROC_TASKSUPGRP      0x0800 // resolve supplementary group id number -> group name
 
-#define PROC_LOOSE_TASKS     0x0200 // threat threads as if they were processes
+#define PROC_LOOSE_TASKS     0x2000 // threat threads as if they were processes
 
 // Obsolete, consider only processes with one of the passed:
 #define PROC_PID             0x1000  // process id numbers ( 0   terminated)
@@ -249,5 +263,9 @@
 #define PROC_SPARE_3     0x04000000
 #define PROC_SPARE_4     0x08000000
 
+
+char** file2strvec(const char* directory, const char* what);
+char** file2strvec_ext(const char* directory, const char* what, char terminator);
+
 EXTERN_C_END
 #endif
diff -bruN procps-3.2.8.orig/proc/sysinfo.c /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/sysinfo.c
--- procps-3.2.8.orig/proc/sysinfo.c	2012-07-04 16:36:07.572291071 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/sysinfo.c	2012-07-04 16:37:32.108710229 +0200
@@ -124,24 +124,25 @@
 unsigned long long Hertz;
 
 static void old_Hertz_hack(void){
-  unsigned long long user_j, nice_j, sys_j, other_j;  /* jiffies (clock ticks) */
+  unsigned long long user_j, nice_j, sys_j, other_j, wait_j, hirq_j, sirq_j, stol_j;  /* jiffies (clock ticks) */
   double up_1, up_2, seconds;
   unsigned long long jiffies;
   unsigned h;
   char *restrict savelocale;
 
+  wait_j = hirq_j = sirq_j = stol_j = 0;
   savelocale = setlocale(LC_NUMERIC, NULL);
   setlocale(LC_NUMERIC, "C");
   do{
     FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_1);
     /* uptime(&up_1, NULL); */
     FILE_TO_BUF(STAT_FILE,stat_fd);
-    sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &user_j, &nice_j, &sys_j, &other_j);
+    sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &user_j, &nice_j, &sys_j, &other_j, &wait_j, &hirq_j, &sirq_j, &stol_j);
     FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_2);
     /* uptime(&up_2, NULL); */
   } while((long long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */
   setlocale(LC_NUMERIC, savelocale);
-  jiffies = user_j + nice_j + sys_j + other_j;
+  jiffies = user_j + nice_j + sys_j + other_j + wait_j + hirq_j + sirq_j + stol_j ;
   seconds = (up_1 + up_2) / 2;
   h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
   /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
@@ -187,6 +188,7 @@
 //extern char** environ;
 
 /* for ELF executables, notes are pushed before environment and args */
+/*
 static unsigned long find_elf_note(unsigned long findme){
   unsigned long *ep = (unsigned long *)environ;
   while(*ep++);
@@ -194,11 +196,13 @@
     if(ep[0]==findme) return ep[1];
     ep+=2;
   }
+
   return NOTE_NOT_FOUND;
 }
-
+*/
 int have_privs;
 
+/*
 static int check_for_privs(void){
   unsigned long rc = find_elf_note(AT_SECURE);
   if(rc==NOTE_NOT_FOUND){
@@ -208,10 +212,12 @@
   }
   return !!rc;
 }
+*/
 
 static void init_libproc(void) __attribute__((constructor));
 static void init_libproc(void){
-  have_privs = check_for_privs();
+  //have_privs = check_for_privs();
+  init_Linux_version(); /* Must be called before we check code */
   // ought to count CPUs in /proc/stat instead of relying
   // on glibc, which foolishly tries to parse /proc/cpuinfo
   //
@@ -221,13 +227,24 @@
   // _SC_NPROCESSORS_ONLN returns 1, which should work OK
   smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
   if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
-
+/*
+#ifdef __linux__
   if(linux_version_code > LINUX_VERSION(2, 4, 0)){ 
     Hertz = find_elf_note(AT_CLKTCK);
     if(Hertz!=NOTE_NOT_FOUND) return;
     fputs("2.4+ kernel w/o ELF notes? -- report this\n", stderr);
   }
-  old_Hertz_hack();
+#endif
+*/
+#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
+  /* On FreeBSD the Hertz hack is unrelaible, there is no ELF note and
+   * Hertz isn't defined in asm/params.h 
+   * See Debian Bug #460331
+   */
+    Hertz = 100;
+    return;
+#endif
+//  old_Hertz_hack();
 }
 
 #if 0
@@ -604,7 +621,7 @@
     );
     head = tail+1;
     if(!found) goto nextline;
-    *(found->slot) = strtoul(head,&tail,10);
+    *(found->slot) = (unsigned long)strtoull(head,&tail,10);
 nextline:
     tail = strchr(head, '\n');
     if(!tail) break;
@@ -794,6 +811,18 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////
+static int is_disk(char *dev)
+{
+  char syspath[PATH_MAX];
+  char *slash;
+
+  while ((slash = strchr(dev, '/')))
+    *slash = '!';
+  snprintf(syspath, sizeof(syspath), "/sys/block/%s", dev);
+  return !(access(syspath, F_OK));
+}
+
+/////////////////////////////////////////////////////////////////////////////
 
 unsigned int getdiskstat(struct disk_stat **disks, struct partition_stat **partitions){
   FILE* fd;
@@ -801,6 +830,7 @@
   int cPartition = 0;
   int fields;
   unsigned dummy;
+  char devname[PATH_MAX];
 
   *disks = NULL;
   *partitions = NULL;
@@ -813,8 +843,9 @@
       fclose(fd);
       break;
     }
-    fields = sscanf(buff, " %*d %*d %*s %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u", &dummy);
-    if (fields == 1){
+    fields = sscanf(buff, " %*d %*d %15s %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u",
+            &devname[0], &dummy);
+    if (fields == 2 && is_disk(devname)){
       (*disks) = realloc(*disks, (cDisk+1)*sizeof(struct disk_stat));
       sscanf(buff,  "   %*d    %*d %15s %u %u %llu %u %u %u %llu %u %u %u %u",
         //&disk_major,
@@ -837,7 +868,9 @@
     }else{
       (*partitions) = realloc(*partitions, (cPartition+1)*sizeof(struct partition_stat));
       fflush(stdout);
-      sscanf(buff,  "   %*d    %*d %15s %u %llu %u %u",
+      sscanf(buff,  (fields == 2)
+          ? "   %*d    %*d %15s %u %*u %llu %*u %u %*u %llu %*u %*u %*u %*u"
+          : "   %*d    %*d %15s %u %llu %u %llu",
         //&part_major,
         //&part_minor,
         (*partitions)[cPartition].partition_name,
diff -bruN procps-3.2.8.orig/proc/sysinfo.h /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/sysinfo.h
--- procps-3.2.8.orig/proc/sysinfo.h	2012-07-04 16:36:07.568290991 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/sysinfo.h	2012-07-04 16:37:32.108710229 +0200
@@ -113,7 +113,7 @@
 	unsigned           parent_disk;  // index into a struct disk_stat array
 	unsigned           reads;
 	unsigned           writes;
-	unsigned           requested_writes;
+	unsigned long long requested_writes;
 }partition_stat;
 
 extern unsigned int getpartitions_num(struct disk_stat *disks, int ndisks);
diff -bruN procps-3.2.8.orig/proc/version.c /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/version.c
--- procps-3.2.8.orig/proc/version.c	2012-07-04 16:36:07.572291071 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/version.c	2012-07-04 16:37:32.108710229 +0200
@@ -33,17 +33,26 @@
 
 int linux_version_code;
 
-static void init_Linux_version(void) __attribute__((constructor));
-static void init_Linux_version(void) {
-    static struct utsname uts;
+void init_Linux_version(void) {
     int x = 0, y = 0, z = 0;	/* cleared in case sscanf() < 3 */
+    FILE *fp;
+    char buf[256];
     
-    if (uname(&uts) == -1)	/* failure implies impending death */
+    if ( (fp=fopen("/proc/version","r")) == NULL) {
+      fprintf(stderr, "Cannot find /proc/version - is /proc mounted?\n");
 	exit(1);
-    if (sscanf(uts.release, "%d.%d.%d", &x, &y, &z) < 3)
+    }
+    if (fgets(buf, 256, fp) == NULL) {
+      fprintf(stderr, "Cannot read kernel version from /proc/version\n");
+      fclose(fp);
+      exit(1);
+    }
+    fclose(fp);
+    if (sscanf(buf, "Linux version %d.%d.%d", &x, &y, &z) < 3)
 	fprintf(stderr,		/* *very* unlikely to happen by accident */
 		"Non-standard uts for running kernel:\n"
 		"release %s=%d.%d.%d gives version code %d\n",
-		uts.release, x, y, z, LINUX_VERSION(x,y,z));
+        buf,
+        x, y, z, LINUX_VERSION(x,y,z));
     linux_version_code = LINUX_VERSION(x, y, z);
 }
diff -bruN procps-3.2.8.orig/proc/version.h /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/version.h
--- procps-3.2.8.orig/proc/version.h	2012-07-04 16:36:07.568290991 +0200
+++ /home/ale/devel/debian/pkg-collab/packages/ulatencyd/src/proc/version.h	2012-07-04 16:37:32.112710235 +0200
@@ -14,6 +14,7 @@
 
 EXTERN_C_BEGIN
 
+void init_Linux_version(void);    /* Get Linux version */
 extern void display_version(void);	/* display suite version */
 extern const char procps_version[];		/* global buf for suite version */
 

Attachment: signature.asc
Description: Digital signature

Reply via email to