#!/usr/sbin/dtrace -s
/*
** anonprofile.d - snoop process anonymous memory reservation as it occurs.
**		 Written in DTrace (Solaris 10 x86 build 51).
**
** 18-May-2004, ver 0.60	(early release, check for newer versions)
**
**
** USAGE:	./anonprofile.d
**
**	Different styles of output can be selected by changing
**	the "PFORMAT" variable below.
** 	
** FIELDS:
**		UID	user ID
**		PID	process ID
**		PPID	parent process ID
**		TOTAL	total size of anon mem usage, bytes
**		SIZE	size of anon mem resv or unresv, bytes
**		ARGS	command (full arguments)
**		TIME	timestamp, us
**
** SEE ALSO: pmap
**
** NOTE: private kernel structures are read, this script may not work on
**	newer builds of Solaris 10.
**
** Standard Disclaimer: This is freeware, use at your own risk.
**
** 18-May-2004	Brendan Gregg	Created this.
**
*/

inline int PFORMAT = 1;
/*			1 - Default output
**			2 - Timestamp output (includes TIME)
**			3 - Everything, space delimited (for spreadsheets)
*/

#pragma D option quiet


/*
**  Print header
*/
dtrace:::BEGIN /PFORMAT == 1/ { 
	printf("%5s %5s %9s %s\n","UID","PID","TOTAL","ARGS");
}
dtrace:::BEGIN /PFORMAT == 2/ { 
	printf("%-14s %5s %5s %9s %s\n",
	 "TIME","UID","PID","TOTAL","ARGS");
}
dtrace:::BEGIN /PFORMAT == 3/ { 
	printf("%s %s %s %s %s %s %s\n",
	 "TIME","UID","PID","PPID","TOTAL","SIZE","ARGS");
}


/*
**  Main
*/
fbt:genunix:anon_resvmem:entry
/arg1 != 0/
{
	/* Store values for a reservation of anon mem */
	self->size = arg0;
	self->uid = curpsinfo->pr_euid;
	self->pid = pid;
	self->ppid = curpsinfo->pr_ppid;
	self->args = (char *)curpsinfo->pr_psargs;
}

fbt:genunix:anon_resvmem:return
/total[pid] == 0 && self->args != NULL && arg1 != 0/
{
	/* Increment total anon mem if successful */
	total[self->pid] = self->size;
	self->ok = 1;
}
fbt:genunix:anon_resvmem:return
/total[pid] != 0 && self->args != NULL && arg1 != 0 && ! self->ok/
{
	/* Increment total anon mem if successful */
	total[self->pid] += self->size;
	self->ok = 1;
}

fbt:genunix:anon_unresv:entry
/total[pid] > 0/
{
	/* Decrement anon mem for unreservations */
	self->size = - arg0;
	self->uid = curpsinfo->pr_euid;
	self->pid = pid;
	self->ppid = curpsinfo->pr_ppid;
	self->args = (char *)curpsinfo->pr_psargs;
	total[pid] += self->size;
	self->ok = 1;
}


/*
**  Print output
*/
fbt:genunix:anon_resvmem:return, fbt:genunix:anon_unresv:entry
/PFORMAT == 1 && self->ok/
{
	printf("%5d %5d %9d %s\n",
	 self->uid,self->pid,total[self->pid],stringof(self->args));
}
fbt:genunix:anon_resvmem:return, fbt:genunix:anon_unresv:entry
/PFORMAT == 2 && self->ok/
{
	printf("%-14d %5d %5d %9d %s\n",
	 timestamp/1000,self->uid,self->pid,
	 total[self->pid],stringof(self->args));
}
fbt:genunix:anon_resvmem:return, fbt:genunix:anon_unresv:entry
/PFORMAT == 3 && self->ok/
{
	printf("%d %d %d %d %d %d %s\n",
	 timestamp/1000,self->uid,self->pid,self->ppid,
	 total[self->pid],self->size,stringof(self->args));
}


/*
**  Cleanup
*/
fbt:genunix:anon_resvmem:return,
fbt:genunix:anon_unresv:entry
/self->ok/
{
	self->size = 0;
	self->ok = 0;
	self->pid = 0;
	self->ppid = 0;
	self->uid = 0;
	self->args = NULL;
}
syscall::rexit:entry
{
	total[pid] = 0;
}
	
