This section provides code examples for accessing exacct files.
Example 3 Displaying exacct Data for a Designated pidThis example displays a specific pid's exacct data snapshot from the kernel.
...
ea_object_t *scratch;
int unpk_flag = EUP_ALLOC; /* use the same allocation flag */
/* for unpack and free */
/* Omit return value checking, to keep code samples short */
bsize = getacct(P_PID, pid, NULL, 0);
buf = malloc(bsize);
/* Retrieve exacct object and unpack */
getacct(P_PID, pid, buf, bsize);
ea_unpack_object(&scratch, unpk_flag, buf, bsize);
/* Display the exacct record */
disp_obj(scratch);
if (scratch->eo_type == EO_GROUP) {
disp_group(scratch);
}
ea_free_object(scratch, unpk_flag);
...
Example 4 Identifying Individual Tasks During a Kernel Build
This example evaluates kernel builds and displays a string that describes the portion of the source tree being built by this task. It displays the portion of the source being built to aid in the per-source-directory analysis.
Note the following key points for this example:
To aggregate the time for a make, which could include many processes, each make is initiated as a task. Child make processes are created as different tasks. To aggregate across the makefile tree, the parent-child task relationship must be identified.
Add a tag with this information to the task's exacct file. Add a current working directory string that describes the portion of the source tree being built by this task's make operation.
ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD,
cwdbuf, strlen(cwdbuf));
... /* Omit return value checking and error processing */ /* to keep code sample short */ ptid = gettaskid(); /* Save "parent" task-id */ tid = settaskid(getprojid(), TASK_NORMAL); /* Create new task */ /* Set data for item objects ptskid and cwd */ ea_set_item(&ptskid, EXT_UINT32 | EXC_LOCAL | MY_PTID, &ptid, 0); ea_set_item(&cwd, EXT_STRING | EXC_LOCAL | MY_CWD, cwdbuf, strlen(cwdbuf)); /* Set grp object and attach ptskid and cwd to grp */ ea_set_group(&grp, EXT_GROUP | EXC_LOCAL | EXD_GROUP_HEADER); ea_attach_to_group(&grp, &ptskid); ea_attach_to_group(&grp, &cwd); /* Pack the object and put it back into the accounting stream */ ea_buflen = ea_pack_object(&grp, ea_buf, sizeof(ea_buf)); putacct(P_TASKID, tid, ea_buf, ea_buflen, EP_EXACCT_OBJECT); /* Memory management: free memory allocate in ea_set_item */ ea_free_item(&cwd, EUP_ALLOC); ...Example 5 Reading and Displaying the Contents of a System exacct File
This example shows how to read and display a system exacct file for a process or a task.
Note the following key points for this example:
Calls ea_get_object() to get the next object in the file. Calls ea_get_object() in a loop until EOF enables a complete traversal of the exacct file.
catalog_name() uses the catalog_item structure to convert an Oracle Solaris catalog's type ID to a meaningful string that describes the content of the object's data. The type ID is obtained by masking the lowest 24 bits, or 3 bytes.
switch(o->eo_catalog & EXT_TYPE_MASK) {
case EXT_UINT8:
printf(" 8: %u", o->eo_item.ei_uint8);
break;
case EXT_UINT16:
...
}
The upper 4 bits of TYPE_MASK are used to find out the data type to print the object's actual data.
disp_group() takes a pointer to a group object and the number of objects in the group. For each object in the group, disp_group() calls disp_obj() and recursively calls disp_group() if the object is a group object.
/* Omit return value checking and error processing */
/* to keep code sample short */
main(int argc, char *argv)
{
ea_file_t ef;
ea_object_t scratch;
char *fname;
fname = argv[1];
ea_open(&ef, fname, NULL, EO_NO_VALID_HDR, O_RDONLY, 0);
bzero(&scratch, sizeof (ea_object_t));
while (ea_get_object(&ef, &scratch) != -1) {
disp_obj(&scratch);
if (scratch.eo_type == EO_GROUP)
disp_group(&ef, scratch.eo_group.eg_nobjs);
bzero(&scratch, sizeof (ea_object_t));
}
ea_close(&ef);
}
struct catalog_item { /* convert Oracle Solaris catalog's type ID */
/* to a meaningful string */
int type;
char *name;
} catalog[] = {
{ EXD_VERSION, "version\t" },
...
{ EXD_PROC_PID, " pid\t" },
...
};
static char *
catalog_name(int type)
{
int i = 0;
while (catalog[i].type != EXD_NONE) {
if (catalog[i].type == type)
return (catalog[i].name);
else
i++;
}
return ("unknown\t");
}
static void disp_obj(ea_object_t *o)
{
printf("%s\t", catalog_name(o->eo_catalog & 0xffffff));
switch(o->eo_catalog & EXT_TYPE_MASK) {
case EXT_UINT8:
printf(" 8: %u", o->eo_item.ei_uint8);
break;
case EXT_UINT16:
...
}
static void disp_group(ea_file_t *ef, uint_t nobjs)
{
for (i = 0; i < nobjs; i++) {
ea_get_object(ef, &scratch));
disp_obj(&scratch);
if (scratch.eo_type == EO_GROUP)
disp_group(ef, scratch.eo_group.eg_nobjs);
}
}