From dmberezin at hotmail.com Mon Nov 1 14:05:40 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Mon, 1 Nov 2004 14:05:40 -0800 Subject: [Orca-checkins] r400 - in trunk/orca: data_gatherers/orcallator lib/SE/3.2.1 lib/SE/3.3 lib/SE/3.3.1 Message-ID: <200411012205.iA1M5epE006618@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Mon Nov 1 14:00:49 2004 New Revision: 400 Added: trunk/orca/lib/SE/3.2.1/workinfo_class.se trunk/orca/lib/SE/3.3.1/workinfo_class.se trunk/orca/lib/SE/3.3/workinfo_class.se Modified: trunk/orca/data_gatherers/orcallator/orcallator.se Log: Add workload data gathering support * lib/SE/3.3.1/workinfo_class.se * lib/SE/3.2.1/workinfo_class.se * lib/SE/3.3/workinfo_class.se This is a new SE class, based on workload class included in SEToolkit, which allows for integration of workload data gathering into orcallator.se. Set WORKLOAD_INFO and WORKLOAD_FIRSTMATCH to define data collection rules. * data_gatherers/orcallator/orcallator.se (measure_workload): New function to collect workload data. Define WATCH_WORKLOAD to activate it. Define WORKLOAD_TOTAL to collect total process data with workinfo class. Modified: trunk/orca/data_gatherers/orcallator/orcallator.se ============================================================================== --- trunk/orca/data_gatherers/orcallator/orcallator.se (original) +++ trunk/orca/data_gatherers/orcallator/orcallator.se Mon Nov 1 14:00:49 2004 @@ -97,6 +97,10 @@ #include #include +#ifdef WATCH_WORKLOAD +#include +#endif + #ifdef WATCH_MOUNTS #include #include @@ -1026,6 +1030,11 @@ #ifdef WATCH_PAGES measure_pages(); #endif + + // Get workload data +#ifdef WATCH_WORKLOAD + measure_workload(); +#endif } /* @@ -2406,3 +2415,45 @@ #endif } #endif + +#ifdef WATCH_WORKLOAD +measure_workload() +{ + work_info_class_t ww; + double millisecs_per_switch; + + ww.number = -1; +#ifndef WORKLOAD_TOTAL + refresh$(ww); +#endif // WORKLOAD_TOTAL + for (refresh$(ww); ww.number != -1; refresh$(ww)) { + put_output(sprintf("%s_cnt", ww.w.name), sprintf("%4d", ww.w.count)); + put_output(sprintf("%s_lwpcnt", ww.w.name), sprintf("%4d", ww.w.info.lwp_count)); + + if (ww.w.cnt == 0) { + millisecs_per_switch = ww.w.info.vcontexts + ww.w.info.icontexts; + if (millisecs_per_switch > 0.0) { + millisecs_per_switch = 1000 * (ww.w.info.user_time + ww.w.info.system_time) / millisecs_per_switch; + } + + put_output(sprintf("%s_usr%%", ww.w.name), sprintf("%6.1f", 100.0*ww.w.info.user_time)); + put_output(sprintf("%s_sys%%", ww.w.name), sprintf("%6.1f", 100.0*(ww.w.info.system_time + + ww.w.info.trap_time))); + put_output(sprintf("%s_cpwt%%", ww.w.name), sprintf("%5.0f", 100.0*(ww.w.info.cpu_wait_time))); + put_output(sprintf("%s_chld%%", ww.w.name), sprintf("%5.0f", 100.0*ww.w.info.child_time)); + put_output(sprintf("%s_sizeM", ww.w.name), sprintf("%7d", ww.w.info.vmem_size/1024)); + put_output(sprintf("%s_pf", ww.w.name), sprintf("%4d", ww.w.info.maj_faults)); + put_output(sprintf("%s_pgwt%%", ww.w.name), sprintf("%6.0f", 100.0*(ww.w.info.text_pf_time + + ww.w.info.data_pf_time + + ww.w.info.kernel_pf_time))); + put_output(sprintf("%s_ulkwt%%", ww.w.name), sprintf("%6.0f", 100.0*ww.w.info.user_lock_time)); + put_output(sprintf("%s_ioK", ww.w.name), sprintf("%6.0f", ww.w.info.charios/1024.0)); + put_output(sprintf("%s_sysc", ww.w.name), sprintf("%6d", ww.w.info.syscalls)); + put_output(sprintf("%s_vctx", ww.w.name), sprintf("%6d", ww.w.info.vcontexts)); + put_output(sprintf("%s_ictx", ww.w.name), sprintf("%6d", ww.w.info.icontexts)); + put_output(sprintf("%s_msps", ww.w.name), sprintf("%6.2f", millisecs_per_switch)); + } + } + return; +} +#endif // WATCH_WORKLOAD Added: trunk/orca/lib/SE/3.2.1/workinfo_class.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.2.1/workinfo_class.se Mon Nov 1 14:00:49 2004 @@ -0,0 +1,341 @@ +#ifndef _WORKINFO_CLASS_SE_ +#define _WORKINFO_CLASS_SE_ + +/*********************************************************** +* * +* Workinfo class is based on Adrian's workload class * +* * +***********************************************************/ + +/************************************************************************** +Usage notes - +This class is designed to collect process statistics for any group of +processes defined by executed command, command arguments, executing user, +and processor set binding. +This class looks for WORKLOAD_INFO environment variable to initialize. + +To initialize workload information set WORKLOAD_INFO in the environment +in the following way: +WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;... +export WORKLOAD_INFO + +DO NOT use quotes ("") around string values (name,command,args,user). +To skip one of the parameters use a SINGLE space. Missing or skipped +parameters are ignored during process matching. +Missing name defaults to WorkloadN, where N is workload number. +Missing command, args, or user are skipped. +By default pset is set to -1, cnt and exact are set to 0; + +Set pset to -1 to unset matching on processor set. +Set exact to non-zero for exact matching, or 0 for pattern matching. +Set cnt to non-zero to only count the number of processes and threads +in a given workload. Other data is neither collected nor printed. + +If there is not enough process parameters defined in a set, workload +parameters initialized in order with supplied data and the rest of the +parameters are set to their default values. + +Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process +for all workloads. +Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process +for one workload only. + +If WORKINFO_PRINT is defined, workload information is printed after +initialization to allow for verification of workload data. + +Examples: +export WORKLOAD_INFO='SE,se.sparc' +Defines one workload with the name SE, command se.sparc, args and user +empty string, exact 0 (match patterns), and no processor set. + +export WORKLOAD_INFO='SE,se.sparc, , ,1' +The same as the above except matching is exact + +export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1' +Defines two workloads. In addition to SE workload, defines a workload named Ora +that counts all processes owned by user oracle. + +Class usage example: +######################################## + +#include + +measure_workload() +{ + work_info_class_t ww; + + ww.number = -1; +#ifdef WORKLOAD_NO_TOTAL + refresh$(ww); +#endif // WORKLOAD_NO_TOTAL + for (refresh$(ww); ww.number != -1; refresh$(ww)) { + printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count); + printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count); + // Get other data if not just counting processes + if (ww.w.cnt == 0) { + printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time); + printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+ + ww.w.info.trap_time)); + printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time); + <...> + } + } +<...> +} +######################################## + +**************************************************************************/ + +#include +#include +#include +#include +#include +#include + +struct work_info_t { + string name; // Used by orcallator for header names for this workload + string command; // String to match against command name + string args; // String to match against command args + string user; // String to match against user name + int exact; // Set to match exact names instead of patterns + int cnt; // Set to count processes and threads only + int pset; // Processor set to match against + int count; // Number of processes that matched + proc_class_t info; // Use same data type to accumulate data +}; + +int match_proc(proc_class_t p, work_info_t w) { + passwd_t pw; + pointer_t ppw; + + if (w.command != "") { // If command is defined and... + if(w.exact == 0) { // pattern matching and... + if(!(p.fname =~ w.command)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact command matching and... + if(p.fname != w.command) { // command does not match - + return 0; // exit and signal no match + } + } + } + + if (w.args != "") { // If args is defined and... + if(w.exact == 0) { // pattern matching and... + if(!(p.args =~ w.args)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact args matching and... + if(p.args != w.args) { // args does not match - + return 0; // exit and signal no match + } + } + } + + if (w.user != "") { // If user name is defined and... + ppw = getpwuid(p.uid); // Get user information for this process + if (ppw == 0) { // If unsuccessful... + return 0; // return no match + } + pw = *((passwd_t *) ppw); + if(w.exact == 0) { // pattern matching and... + if(!(pw.pw_name =~ w.user)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact user name matching and... + if(pw.pw_name != w.user) { // user name does not match - + return 0; // exit and signal no match + } + } + } + + if ((w.pset != -1) && (p.bindpset != w.pset)) { + return 0; + } + + return 1; +} + +class work_info_class_t { + int number; // Current workload + work_info_t w; // Data for current workload + + work_info$() { + work_info_t wi[]; // Workload data dynamic array + int wc = 0; // Number of workloads + int firstmatch; // Set to use first workload that matches only + string fmstring; + proc_class_t pp; // Underlying process class data (snapshot) + proc_class_t ppzero; // Used to zero out by copying + double iv; + int i; + string wstring; + string wstr; + string dstr; + ulong pwstring; + ulong pwstr; + int initialized = 0; + + if (initialized == 0) { // Initialize class + refresh$(pp); // Setup proc_class + fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy + wstring = getenv("WORKLOAD_INFO"); // Load user defined data for matching + + // Set matching policy + if (fmstring != nil) { + firstmatch = atoi(fmstring); + } else { + // Default to each process in one workload only + firstmatch = 1; + } + + // Allocate memory for collecting totals + wi = new work_info_t[1]; + wi[wc].name = "Total"; + wi[wc].command = ""; + wi[wc].args = ""; + wi[wc].user = ""; + wi[wc].pset = -1; + + // Parse wstring into individual workloads + for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) { + // Allocate memory for this workload + wi = renew wi[++wc+1]; + wi[wc].name = strtok_r(wstr, ",", &pwstr); // Get name + if (wi[wc].name == nil || wi[wc].name == " ") { + wi[wc].name = sprintf("Workload%d", wc); + } + wi[wc].command = strtok_r(nil, ",", &pwstr); // Get command + if (wi[wc].command == nil || wi[wc].command == " ") { + wi[wc].command = ""; + } + wi[wc].args = strtok_r(nil, ",", &pwstr); // Get args + if (wi[wc].args == nil || wi[wc].args == " ") { + wi[wc].args = ""; + } + wi[wc].user = strtok_r(nil, ",", &pwstr); // Get user + if (wi[wc].user == nil || wi[wc].user == " ") { + wi[wc].user = ""; + } + dstr = strtok_r(nil, ",", &pwstr); // Get exact + if (dstr != nil) { + wi[wc].exact = atoi(dstr); + } + dstr = strtok_r(nil, ",", &pwstr); // Get cnt + if (dstr != nil) { + wi[wc].cnt = atoi(dstr); + } + dstr = strtok_r(nil, ",", &pwstr); // Get pset + if (dstr == nil || dstr == " ") { + wi[wc].pset = -1; + } else { + wi[wc].pset = atoi(dstr); + } + } + +#ifdef WORKINFO_PRINT + printf("\nWorkinfo class is initialized with the following data\n"); + printf("Number of workloads = %d, firstmatch = %d (%s)\n", + wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once")); + for(i=1; i <= wc; i++) { + printf("Workload number %3d\n-------------------\n", i); + printf("name .................... %s\n", wi[i].name); + printf("command ................. %s\n", wi[i].command); + printf("args .................... %s\n", wi[i].args); + printf("user .................... %s\n", wi[i].user); + printf("exact ................... %d\n", wi[i].exact); + printf("pset .................... %d\n", wi[i].pset); + printf("Only count the number of\nprocesses and threads ... %s\n\n", + (wi[i].cnt == 0 ? "No" : "Yes")); + } +#endif // WORKINFO_PRINT + + number = -1; + initialized = 1; + return; + } + + if (number != -1) { // Data is available + if (number < wc) { + w = wi[++number]; // Return next workload data + } else { + w = wi[0]; // Set w to Total data + number = -1; // Signal end of data + } + return; + } + + for(i=0; i <= wc; i++) { // Reset counters + wi[i].count = 0; + wi[i].info = ppzero; // Not easy to use memset instead + } + refresh$(pp); // Get the snapshot + while (pp.index$ != -1) { + if (pp.termination != 0.0) { + continue; // Don't add in dead processes + } + for(i=0; i <= wc; i++) { + if (i == 0 || // Accumulate totals + (match_proc(pp, wi[i]) != 0)) { + wi[i].info.interval = pp.interval; // Take the last interval seen + iv = pp.interval; + if (iv == 0.0) { iv = 1.0; } // Safety net + if (pp.creation < wi[i].info.creation) { // Take the earliest creation + wi[i].info.creation = pp.creation; + } + if (wi[i].cnt == 0) { + // Track individual times + wi[i].info.lasttime = pp.lasttime; + wi[i].info.total_user += pp.total_user; + wi[i].info.total_system += pp.total_system; + wi[i].info.total_child += pp.total_child; + // Intervals vary, so accumulate here + wi[i].info.user_time += pp.user_time/iv; + wi[i].info.system_time += pp.system_time/iv; + wi[i].info.trap_time += pp.trap_time/iv; + wi[i].info.child_time += pp.child_time/iv; + wi[i].info.text_pf_time += pp.text_pf_time/iv; + wi[i].info.data_pf_time += pp.data_pf_time/iv; + wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv; + wi[i].info.user_lock_time += pp.user_lock_time/iv; + wi[i].info.sleep_time += pp.sleep_time/iv; + wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv; + wi[i].info.stoptime += pp.stoptime/iv; + wi[i].info.syscalls += pp.syscalls/iv; + wi[i].info.inblocks += pp.inblocks/iv; + wi[i].info.outblocks += pp.outblocks/iv; + // Next four are sizes not rates + wi[i].info.vmem_size += pp.vmem_size; + wi[i].info.rmem_size += pp.rmem_size; +#ifdef XMAP + wi[i].info.pmem_size += pp.pmem_size; + wi[i].info.smem_size += pp.smem_size; +#endif + wi[i].info.maj_faults += pp.maj_faults/iv; + wi[i].info.min_faults += pp.min_faults/iv; + wi[i].info.total_swaps += pp.total_swaps/iv; + wi[i].info.messages += pp.messages/iv; + wi[i].info.signals += pp.signals/iv; + wi[i].info.vcontexts += pp.vcontexts/iv; + wi[i].info.icontexts += pp.icontexts/iv; + wi[i].info.charios += pp.charios/iv; + // Divide these three by wi[i].count + wi[i].info.priority += pp.priority; + wi[i].info.niceness += pp.niceness; + } + wi[i].info.lwp_count += pp.lwp_count; + wi[i].count++; + if (firstmatch == 1 && i > 0) { // First match only counts + break; + } + } + } + refresh$(pp); // Next process + } + number = 0; + w = wi[number]; + } +}; + +#endif Added: trunk/orca/lib/SE/3.3.1/workinfo_class.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.3.1/workinfo_class.se Mon Nov 1 14:00:49 2004 @@ -0,0 +1,341 @@ +#ifndef _WORKINFO_CLASS_SE_ +#define _WORKINFO_CLASS_SE_ + +/*********************************************************** +* * +* Workinfo class is based on Adrian's workload class * +* * +***********************************************************/ + +/************************************************************************** +Usage notes - +This class is designed to collect process statistics for any group of +processes defined by executed command, command arguments, executing user, +and processor set binding. +This class looks for WORKLOAD_INFO environment variable to initialize. + +To initialize workload information set WORKLOAD_INFO in the environment +in the following way: +WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;... +export WORKLOAD_INFO + +DO NOT use quotes ("") around string values (name,command,args,user). +To skip one of the parameters use a SINGLE space. Missing or skipped +parameters are ignored during process matching. +Missing name defaults to WorkloadN, where N is workload number. +Missing command, args, or user are skipped. +By default pset is set to -1, cnt and exact are set to 0; + +Set pset to -1 to unset matching on processor set. +Set exact to non-zero for exact matching, or 0 for pattern matching. +Set cnt to non-zero to only count the number of processes and threads +in a given workload. Other data is neither collected nor printed. + +If there is not enough process parameters defined in a set, workload +parameters initialized in order with supplied data and the rest of the +parameters are set to their default values. + +Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process +for all workloads. +Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process +for one workload only. + +If WORKINFO_PRINT is defined, workload information is printed after +initialization to allow for verification of workload data. + +Examples: +export WORKLOAD_INFO='SE,se.sparc' +Defines one workload with the name SE, command se.sparc, args and user +empty string, exact 0 (match patterns), and no processor set. + +export WORKLOAD_INFO='SE,se.sparc, , ,1' +The same as the above except matching is exact + +export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1' +Defines two workloads. In addition to SE workload, defines a workload named Ora +that counts all processes owned by user oracle. + +Class usage example: +######################################## + +#include + +measure_workload() +{ + work_info_class_t ww; + + ww.number = -1; +#ifdef WORKLOAD_NO_TOTAL + refresh$(ww); +#endif // WORKLOAD_NO_TOTAL + for (refresh$(ww); ww.number != -1; refresh$(ww)) { + printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count); + printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count); + // Get other data if not just counting processes + if (ww.w.cnt == 0) { + printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time); + printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+ + ww.w.info.trap_time)); + printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time); + <...> + } + } +<...> +} +######################################## + +**************************************************************************/ + +#include +#include +#include +#include +#include +#include + +struct work_info_t { + string name; // Used by orcallator for header names for this workload + string command; // String to match against command name + string args; // String to match against command args + string user; // String to match against user name + int exact; // Set to match exact names instead of patterns + int cnt; // Set to count processes and threads only + int pset; // Processor set to match against + int count; // Number of processes that matched + proc_class_t info; // Use same data type to accumulate data +}; + +int match_proc(proc_class_t p, work_info_t w) { + passwd_t pw; + pointer_t ppw; + + if (w.command != "") { // If command is defined and... + if(w.exact == 0) { // pattern matching and... + if(!(p.fname =~ w.command)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact command matching and... + if(p.fname != w.command) { // command does not match - + return 0; // exit and signal no match + } + } + } + + if (w.args != "") { // If args is defined and... + if(w.exact == 0) { // pattern matching and... + if(!(p.args =~ w.args)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact args matching and... + if(p.args != w.args) { // args does not match - + return 0; // exit and signal no match + } + } + } + + if (w.user != "") { // If user name is defined and... + ppw = getpwuid(p.uid); // Get user information for this process + if (ppw == 0) { // If unsuccessful... + return 0; // return no match + } + pw = *((passwd_t *) ppw); + if(w.exact == 0) { // pattern matching and... + if(!(pw.pw_name =~ w.user)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact user name matching and... + if(pw.pw_name != w.user) { // user name does not match - + return 0; // exit and signal no match + } + } + } + + if ((w.pset != -1) && (p.bindpset != w.pset)) { + return 0; + } + + return 1; +} + +class work_info_class_t { + int number; // Current workload + work_info_t w; // Data for current workload + + work_info$() { + work_info_t wi[]; // Workload data dynamic array + int wc = 0; // Number of workloads + int firstmatch; // Set to use first workload that matches only + string fmstring; + proc_class_t pp; // Underlying process class data (snapshot) + proc_class_t ppzero; // Used to zero out by copying + double iv; + int i; + string wstring; + string wstr; + string dstr; + ulong pwstring; + ulong pwstr; + int initialized = 0; + + if (initialized == 0) { // Initialize class + refresh$(pp); // Setup proc_class + fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy + wstring = getenv("WORKLOAD_INFO"); // Load user defined data for matching + + // Set matching policy + if (fmstring != nil) { + firstmatch = atoi(fmstring); + } else { + // Default to each process in one workload only + firstmatch = 1; + } + + // Allocate memory for collecting totals + wi = new work_info_t[1]; + wi[wc].name = "Total"; + wi[wc].command = ""; + wi[wc].args = ""; + wi[wc].user = ""; + wi[wc].pset = -1; + + // Parse wstring into individual workloads + for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) { + // Allocate memory for this workload + wi = renew wi[++wc+1]; + wi[wc].name = strtok_r(wstr, ",", &pwstr); // Get name + if (wi[wc].name == nil || wi[wc].name == " ") { + wi[wc].name = sprintf("Workload%d", wc); + } + wi[wc].command = strtok_r(nil, ",", &pwstr); // Get command + if (wi[wc].command == nil || wi[wc].command == " ") { + wi[wc].command = ""; + } + wi[wc].args = strtok_r(nil, ",", &pwstr); // Get args + if (wi[wc].args == nil || wi[wc].args == " ") { + wi[wc].args = ""; + } + wi[wc].user = strtok_r(nil, ",", &pwstr); // Get user + if (wi[wc].user == nil || wi[wc].user == " ") { + wi[wc].user = ""; + } + dstr = strtok_r(nil, ",", &pwstr); // Get exact + if (dstr != nil) { + wi[wc].exact = atoi(dstr); + } + dstr = strtok_r(nil, ",", &pwstr); // Get cnt + if (dstr != nil) { + wi[wc].cnt = atoi(dstr); + } + dstr = strtok_r(nil, ",", &pwstr); // Get pset + if (dstr == nil || dstr == " ") { + wi[wc].pset = -1; + } else { + wi[wc].pset = atoi(dstr); + } + } + +#ifdef WORKINFO_PRINT + printf("\nWorkinfo class is initialized with the following data\n"); + printf("Number of workloads = %d, firstmatch = %d (%s)\n", + wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once")); + for(i=1; i <= wc; i++) { + printf("Workload number %3d\n-------------------\n", i); + printf("name .................... %s\n", wi[i].name); + printf("command ................. %s\n", wi[i].command); + printf("args .................... %s\n", wi[i].args); + printf("user .................... %s\n", wi[i].user); + printf("exact ................... %d\n", wi[i].exact); + printf("pset .................... %d\n", wi[i].pset); + printf("Only count the number of\nprocesses and threads ... %s\n\n", + (wi[i].cnt == 0 ? "No" : "Yes")); + } +#endif // WORKINFO_PRINT + + number = -1; + initialized = 1; + return; + } + + if (number != -1) { // Data is available + if (number < wc) { + w = wi[++number]; // Return next workload data + } else { + w = wi[0]; // Set w to Total data + number = -1; // Signal end of data + } + return; + } + + for(i=0; i <= wc; i++) { // Reset counters + wi[i].count = 0; + wi[i].info = ppzero; // Not easy to use memset instead + } + refresh$(pp); // Get the snapshot + while (pp.index$ != -1) { + if (pp.termination != 0.0) { + continue; // Don't add in dead processes + } + for(i=0; i <= wc; i++) { + if (i == 0 || // Accumulate totals + (match_proc(pp, wi[i]) != 0)) { + wi[i].info.interval = pp.interval; // Take the last interval seen + iv = pp.interval; + if (iv == 0.0) { iv = 1.0; } // Safety net + if (pp.creation < wi[i].info.creation) { // Take the earliest creation + wi[i].info.creation = pp.creation; + } + if (wi[i].cnt == 0) { + // Track individual times + wi[i].info.lasttime = pp.lasttime; + wi[i].info.total_user += pp.total_user; + wi[i].info.total_system += pp.total_system; + wi[i].info.total_child += pp.total_child; + // Intervals vary, so accumulate here + wi[i].info.user_time += pp.user_time/iv; + wi[i].info.system_time += pp.system_time/iv; + wi[i].info.trap_time += pp.trap_time/iv; + wi[i].info.child_time += pp.child_time/iv; + wi[i].info.text_pf_time += pp.text_pf_time/iv; + wi[i].info.data_pf_time += pp.data_pf_time/iv; + wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv; + wi[i].info.user_lock_time += pp.user_lock_time/iv; + wi[i].info.sleep_time += pp.sleep_time/iv; + wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv; + wi[i].info.stoptime += pp.stoptime/iv; + wi[i].info.syscalls += pp.syscalls/iv; + wi[i].info.inblocks += pp.inblocks/iv; + wi[i].info.outblocks += pp.outblocks/iv; + // Next four are sizes not rates + wi[i].info.vmem_size += pp.vmem_size; + wi[i].info.rmem_size += pp.rmem_size; +#ifdef XMAP + wi[i].info.pmem_size += pp.pmem_size; + wi[i].info.smem_size += pp.smem_size; +#endif + wi[i].info.maj_faults += pp.maj_faults/iv; + wi[i].info.min_faults += pp.min_faults/iv; + wi[i].info.total_swaps += pp.total_swaps/iv; + wi[i].info.messages += pp.messages/iv; + wi[i].info.signals += pp.signals/iv; + wi[i].info.vcontexts += pp.vcontexts/iv; + wi[i].info.icontexts += pp.icontexts/iv; + wi[i].info.charios += pp.charios/iv; + // Divide these three by wi[i].count + wi[i].info.priority += pp.priority; + wi[i].info.niceness += pp.niceness; + } + wi[i].info.lwp_count += pp.lwp_count; + wi[i].count++; + if (firstmatch == 1 && i > 0) { // First match only counts + break; + } + } + } + refresh$(pp); // Next process + } + number = 0; + w = wi[number]; + } +}; + +#endif Added: trunk/orca/lib/SE/3.3/workinfo_class.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.3/workinfo_class.se Mon Nov 1 14:00:49 2004 @@ -0,0 +1,341 @@ +#ifndef _WORKINFO_CLASS_SE_ +#define _WORKINFO_CLASS_SE_ + +/*********************************************************** +* * +* Workinfo class is based on Adrian's workload class * +* * +***********************************************************/ + +/************************************************************************** +Usage notes - +This class is designed to collect process statistics for any group of +processes defined by executed command, command arguments, executing user, +and processor set binding. +This class looks for WORKLOAD_INFO environment variable to initialize. + +To initialize workload information set WORKLOAD_INFO in the environment +in the following way: +WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;... +export WORKLOAD_INFO + +DO NOT use quotes ("") around string values (name,command,args,user). +To skip one of the parameters use a SINGLE space. Missing or skipped +parameters are ignored during process matching. +Missing name defaults to WorkloadN, where N is workload number. +Missing command, args, or user are skipped. +By default pset is set to -1, cnt and exact are set to 0; + +Set pset to -1 to unset matching on processor set. +Set exact to non-zero for exact matching, or 0 for pattern matching. +Set cnt to non-zero to only count the number of processes and threads +in a given workload. Other data is neither collected nor printed. + +If there is not enough process parameters defined in a set, workload +parameters initialized in order with supplied data and the rest of the +parameters are set to their default values. + +Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process +for all workloads. +Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process +for one workload only. + +If WORKINFO_PRINT is defined, workload information is printed after +initialization to allow for verification of workload data. + +Examples: +export WORKLOAD_INFO='SE,se.sparc' +Defines one workload with the name SE, command se.sparc, args and user +empty string, exact 0 (match patterns), and no processor set. + +export WORKLOAD_INFO='SE,se.sparc, , ,1' +The same as the above except matching is exact + +export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1' +Defines two workloads. In addition to SE workload, defines a workload named Ora +that counts all processes owned by user oracle. + +Class usage example: +######################################## + +#include + +measure_workload() +{ + work_info_class_t ww; + + ww.number = -1; +#ifdef WORKLOAD_NO_TOTAL + refresh$(ww); +#endif // WORKLOAD_NO_TOTAL + for (refresh$(ww); ww.number != -1; refresh$(ww)) { + printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count); + printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count); + // Get other data if not just counting processes + if (ww.w.cnt == 0) { + printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time); + printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+ + ww.w.info.trap_time)); + printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time); + <...> + } + } +<...> +} +######################################## + +**************************************************************************/ + +#include +#include +#include +#include +#include +#include + +struct work_info_t { + string name; // Used by orcallator for header names for this workload + string command; // String to match against command name + string args; // String to match against command args + string user; // String to match against user name + int exact; // Set to match exact names instead of patterns + int cnt; // Set to count processes and threads only + int pset; // Processor set to match against + int count; // Number of processes that matched + proc_class_t info; // Use same data type to accumulate data +}; + +int match_proc(proc_class_t p, work_info_t w) { + passwd_t pw; + pointer_t ppw; + + if (w.command != "") { // If command is defined and... + if(w.exact == 0) { // pattern matching and... + if(!(p.fname =~ w.command)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact command matching and... + if(p.fname != w.command) { // command does not match - + return 0; // exit and signal no match + } + } + } + + if (w.args != "") { // If args is defined and... + if(w.exact == 0) { // pattern matching and... + if(!(p.args =~ w.args)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact args matching and... + if(p.args != w.args) { // args does not match - + return 0; // exit and signal no match + } + } + } + + if (w.user != "") { // If user name is defined and... + ppw = getpwuid(p.uid); // Get user information for this process + if (ppw == 0) { // If unsuccessful... + return 0; // return no match + } + pw = *((passwd_t *) ppw); + if(w.exact == 0) { // pattern matching and... + if(!(pw.pw_name =~ w.user)) { // pattern does not match - + return 0; // exit and signal no match + } + } else { // exact user name matching and... + if(pw.pw_name != w.user) { // user name does not match - + return 0; // exit and signal no match + } + } + } + + if ((w.pset != -1) && (p.bindpset != w.pset)) { + return 0; + } + + return 1; +} + +class work_info_class_t { + int number; // Current workload + work_info_t w; // Data for current workload + + work_info$() { + work_info_t wi[]; // Workload data dynamic array + int wc = 0; // Number of workloads + int firstmatch; // Set to use first workload that matches only + string fmstring; + proc_class_t pp; // Underlying process class data (snapshot) + proc_class_t ppzero; // Used to zero out by copying + double iv; + int i; + string wstring; + string wstr; + string dstr; + ulong pwstring; + ulong pwstr; + int initialized = 0; + + if (initialized == 0) { // Initialize class + refresh$(pp); // Setup proc_class + fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy + wstring = getenv("WORKLOAD_INFO"); // Load user defined data for matching + + // Set matching policy + if (fmstring != nil) { + firstmatch = atoi(fmstring); + } else { + // Default to each process in one workload only + firstmatch = 1; + } + + // Allocate memory for collecting totals + wi = new work_info_t[1]; + wi[wc].name = "Total"; + wi[wc].command = ""; + wi[wc].args = ""; + wi[wc].user = ""; + wi[wc].pset = -1; + + // Parse wstring into individual workloads + for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) { + // Allocate memory for this workload + wi = renew wi[++wc+1]; + wi[wc].name = strtok_r(wstr, ",", &pwstr); // Get name + if (wi[wc].name == nil || wi[wc].name == " ") { + wi[wc].name = sprintf("Workload%d", wc); + } + wi[wc].command = strtok_r(nil, ",", &pwstr); // Get command + if (wi[wc].command == nil || wi[wc].command == " ") { + wi[wc].command = ""; + } + wi[wc].args = strtok_r(nil, ",", &pwstr); // Get args + if (wi[wc].args == nil || wi[wc].args == " ") { + wi[wc].args = ""; + } + wi[wc].user = strtok_r(nil, ",", &pwstr); // Get user + if (wi[wc].user == nil || wi[wc].user == " ") { + wi[wc].user = ""; + } + dstr = strtok_r(nil, ",", &pwstr); // Get exact + if (dstr != nil) { + wi[wc].exact = atoi(dstr); + } + dstr = strtok_r(nil, ",", &pwstr); // Get cnt + if (dstr != nil) { + wi[wc].cnt = atoi(dstr); + } + dstr = strtok_r(nil, ",", &pwstr); // Get pset + if (dstr == nil || dstr == " ") { + wi[wc].pset = -1; + } else { + wi[wc].pset = atoi(dstr); + } + } + +#ifdef WORKINFO_PRINT + printf("\nWorkinfo class is initialized with the following data\n"); + printf("Number of workloads = %d, firstmatch = %d (%s)\n", + wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once")); + for(i=1; i <= wc; i++) { + printf("Workload number %3d\n-------------------\n", i); + printf("name .................... %s\n", wi[i].name); + printf("command ................. %s\n", wi[i].command); + printf("args .................... %s\n", wi[i].args); + printf("user .................... %s\n", wi[i].user); + printf("exact ................... %d\n", wi[i].exact); + printf("pset .................... %d\n", wi[i].pset); + printf("Only count the number of\nprocesses and threads ... %s\n\n", + (wi[i].cnt == 0 ? "No" : "Yes")); + } +#endif // WORKINFO_PRINT + + number = -1; + initialized = 1; + return; + } + + if (number != -1) { // Data is available + if (number < wc) { + w = wi[++number]; // Return next workload data + } else { + w = wi[0]; // Set w to Total data + number = -1; // Signal end of data + } + return; + } + + for(i=0; i <= wc; i++) { // Reset counters + wi[i].count = 0; + wi[i].info = ppzero; // Not easy to use memset instead + } + refresh$(pp); // Get the snapshot + while (pp.index$ != -1) { + if (pp.termination != 0.0) { + continue; // Don't add in dead processes + } + for(i=0; i <= wc; i++) { + if (i == 0 || // Accumulate totals + (match_proc(pp, wi[i]) != 0)) { + wi[i].info.interval = pp.interval; // Take the last interval seen + iv = pp.interval; + if (iv == 0.0) { iv = 1.0; } // Safety net + if (pp.creation < wi[i].info.creation) { // Take the earliest creation + wi[i].info.creation = pp.creation; + } + if (wi[i].cnt == 0) { + // Track individual times + wi[i].info.lasttime = pp.lasttime; + wi[i].info.total_user += pp.total_user; + wi[i].info.total_system += pp.total_system; + wi[i].info.total_child += pp.total_child; + // Intervals vary, so accumulate here + wi[i].info.user_time += pp.user_time/iv; + wi[i].info.system_time += pp.system_time/iv; + wi[i].info.trap_time += pp.trap_time/iv; + wi[i].info.child_time += pp.child_time/iv; + wi[i].info.text_pf_time += pp.text_pf_time/iv; + wi[i].info.data_pf_time += pp.data_pf_time/iv; + wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv; + wi[i].info.user_lock_time += pp.user_lock_time/iv; + wi[i].info.sleep_time += pp.sleep_time/iv; + wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv; + wi[i].info.stoptime += pp.stoptime/iv; + wi[i].info.syscalls += pp.syscalls/iv; + wi[i].info.inblocks += pp.inblocks/iv; + wi[i].info.outblocks += pp.outblocks/iv; + // Next four are sizes not rates + wi[i].info.vmem_size += pp.vmem_size; + wi[i].info.rmem_size += pp.rmem_size; +#ifdef XMAP + wi[i].info.pmem_size += pp.pmem_size; + wi[i].info.smem_size += pp.smem_size; +#endif + wi[i].info.maj_faults += pp.maj_faults/iv; + wi[i].info.min_faults += pp.min_faults/iv; + wi[i].info.total_swaps += pp.total_swaps/iv; + wi[i].info.messages += pp.messages/iv; + wi[i].info.signals += pp.signals/iv; + wi[i].info.vcontexts += pp.vcontexts/iv; + wi[i].info.icontexts += pp.icontexts/iv; + wi[i].info.charios += pp.charios/iv; + // Divide these three by wi[i].count + wi[i].info.priority += pp.priority; + wi[i].info.niceness += pp.niceness; + } + wi[i].info.lwp_count += pp.lwp_count; + wi[i].count++; + if (firstmatch == 1 && i > 0) { // First match only counts + break; + } + } + } + refresh$(pp); // Next process + } + number = 0; + w = wi[number]; + } +}; + +#endif From blair at orcaware.com Tue Nov 2 21:55:38 2004 From: blair at orcaware.com (Blair Zajac) Date: Tue, 2 Nov 2004 21:55:38 -0800 Subject: [Orca-checkins] r401 - trunk/orca/lib Message-ID: <200411030555.iA35tcF1025864@gw.orcaware.com> Author: blair Date: Tue Nov 2 21:52:59 2004 New Revision: 401 Modified: trunk/orca/lib/Makefile.in Log: * lib/Makefile.in (install): Fix a bug where the install fails with some versions of make if svnversion is not found in the PATH, even if svnversion's output is captured via ``. Redirect the shell's message the svnversion cannot be found to /dev/null. Modified: trunk/orca/lib/Makefile.in ============================================================================== --- trunk/orca/lib/Makefile.in (original) +++ trunk/orca/lib/Makefile.in Tue Nov 2 21:52:59 2004 @@ -51,8 +51,8 @@ $(INSTALL) -m 0644 $$f $(libdir)/$$d; \ done \ done - @echo 'cd ..; svnversion . 2>/dev/null' - @current_rev="`cd ..; svnversion . 2>/dev/null`"; \ + @echo "cd ..; sh -c 'svnversion .' 2>/dev/null || true" + @current_rev="`cd ..; sh -c 'svnversion .' 2>/dev/null || true`"; \ if test "$$current_rev" != "" && \ test "$$current_rev" != "exported"; then \ echo "Found good svnversion for `cd ..; pwd`: $$current_rev"; \ From dmberezin at hotmail.com Thu Nov 4 13:32:20 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Thu, 4 Nov 2004 13:32:20 -0800 Subject: [Orca-checkins] r402 - in trunk/orca/data_gatherers: aix hp orca_services orcallator procallator winallator Message-ID: <200411042132.iA4LWK4j024944@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Thu Nov 4 13:30:20 2004 New Revision: 402 Modified: trunk/orca/data_gatherers/aix/Makefile.in trunk/orca/data_gatherers/hp/Makefile.in trunk/orca/data_gatherers/orca_services/Makefile.in trunk/orca/data_gatherers/orcallator/Makefile.in trunk/orca/data_gatherers/procallator/Makefile.in trunk/orca/data_gatherers/winallator/Makefile.in Log: Fix common block of code in a number of Makefiles * data_gatherers/aix/Makefile.in * data_gatherers/procallator/Makefile.in * data_gatherers/orcallator/Makefile.in * data_gatherers/hp/Makefile.in * data_gatherers/orca_services/Makefile.in * data_gatherers/winallator/Makefile.in Fix a bug to properly handle the case when BIN_TARGETS variable is empty. Modified: trunk/orca/data_gatherers/aix/Makefile.in ============================================================================== --- trunk/orca/data_gatherers/aix/Makefile.in (original) +++ trunk/orca/data_gatherers/aix/Makefile.in Thu Nov 4 13:30:20 2004 @@ -35,12 +35,10 @@ install: all $(MKDIR) $(bindir) - @if test "`echo $(BIN_TARGETS)`"; then \ - for file in $(BIN_TARGETS); do \ - echo $(INSTALL) $$file $(bindir); \ - $(INSTALL) $$file $(bindir); \ - done; \ - fi + @for file in `echo $(BIN_TARGETS)`; do \ + echo $(INSTALL) $$file $(bindir); \ + $(INSTALL) $$file $(bindir); \ + done clean: $(RM) $(TARGETS) Modified: trunk/orca/data_gatherers/hp/Makefile.in ============================================================================== --- trunk/orca/data_gatherers/hp/Makefile.in (original) +++ trunk/orca/data_gatherers/hp/Makefile.in Thu Nov 4 13:30:20 2004 @@ -35,12 +35,10 @@ install: all $(MKDIR) $(bindir) - @if test "`echo $(BIN_TARGETS)`"; then \ - for file in $(BIN_TARGETS); do \ - echo $(INSTALL) $$file $(bindir); \ - $(INSTALL) $$file $(bindir); \ - done; \ - fi + @for file in `echo $(BIN_TARGETS)`; do \ + echo $(INSTALL) $$file $(bindir); \ + $(INSTALL) $$file $(bindir); \ + done clean: $(RM) $(TARGETS) Modified: trunk/orca/data_gatherers/orca_services/Makefile.in ============================================================================== --- trunk/orca/data_gatherers/orca_services/Makefile.in (original) +++ trunk/orca/data_gatherers/orca_services/Makefile.in Thu Nov 4 13:30:20 2004 @@ -47,18 +47,14 @@ $(MKDIR) $(sysconfdir) $(MKDIR) $(RAW_ORCA_SERVICES_DIR) $(MKDIR) $(RRD_ORCA_SERVICES_DIR) - @if test "`echo $(BIN_TARGETS)`"; then \ - for file in $(BIN_TARGETS); do \ - echo $(INSTALL) $$file $(bindir); \ - $(INSTALL) $$file $(bindir); \ - done; \ - fi - @if test "`echo $(LIBEXEC_TARGETS)`"; then \ - for file in $(LIBEXEC_TARGETS); do \ - echo $(INSTALL) $$file $(libexecdir); \ - $(INSTALL) $$file $(libexecdir); \ - done; \ - fi + @for file in `echo $(BIN_TARGETS)`; do \ + echo $(INSTALL) $$file $(bindir); \ + $(INSTALL) $$file $(bindir); \ + done + @for file in `echo $(LIBEXEC_TARGETS)`; do \ + echo $(INSTALL) $$file $(libexecdir); \ + $(INSTALL) $$file $(libexecdir); \ + done @if test -r $(sysconfdir)/orca_services.cfg; then \ date="`date +%Y-%m-%d-%H:%M:%S`"; \ echo $(INSTALL) -m 0644 orca_services.cfg $(sysconfdir)/orca_services.cfg.$$date; \ Modified: trunk/orca/data_gatherers/orcallator/Makefile.in ============================================================================== --- trunk/orca/data_gatherers/orcallator/Makefile.in (original) +++ trunk/orca/data_gatherers/orcallator/Makefile.in Thu Nov 4 13:30:20 2004 @@ -48,12 +48,10 @@ $(MKDIR) $(sysconfdir) $(MKDIR) $(RAW_ORCALLATOR_DIR) $(MKDIR) $(RRD_ORCALLATOR_DIR) - @if test "`echo $(BIN_TARGETS)`"; then \ - for file in $(BIN_TARGETS); do \ - echo $(INSTALL) $$file $(bindir); \ - $(INSTALL) $$file $(bindir); \ - done; \ - fi + @for file in `echo $(BIN_TARGETS)`; do \ + echo $(INSTALL) $$file $(bindir); \ + $(INSTALL) $$file $(bindir); \ + done $(INSTALL) -m 0644 orcallator.se $(libdir) @if test -r $(sysconfdir)/orcallator.cfg; then \ date="`date +%Y-%m-%d-%H:%M:%S`"; \ Modified: trunk/orca/data_gatherers/procallator/Makefile.in ============================================================================== --- trunk/orca/data_gatherers/procallator/Makefile.in (original) +++ trunk/orca/data_gatherers/procallator/Makefile.in Thu Nov 4 13:30:20 2004 @@ -44,12 +44,10 @@ $(MKDIR) $(bindir) $(MKDIR) $(RAW_PROCALLATOR_DIR) $(MKDIR) $(RRD_PROCALLATOR_DIR) - @if test "`echo $(BIN_TARGETS)`"; then \ - for file in $(BIN_TARGETS); do \ - echo $(INSTALL) $$file $(bindir); \ - $(INSTALL) $$file $(bindir); \ - done; \ - fi + @for file in `echo $(BIN_TARGETS)`; do \ + echo $(INSTALL) $$file $(bindir); \ + $(INSTALL) $$file $(bindir); \ + done @if test -r $(sysconfdir)/procallator.cfg; then \ date="`date +%Y-%m-%d-%H:%M:%S`"; \ echo $(INSTALL) -m 0644 procallator.cfg $(sysconfdir)/procallator.cfg.$$date; \ Modified: trunk/orca/data_gatherers/winallator/Makefile.in ============================================================================== --- trunk/orca/data_gatherers/winallator/Makefile.in (original) +++ trunk/orca/data_gatherers/winallator/Makefile.in Thu Nov 4 13:30:20 2004 @@ -42,12 +42,10 @@ $(MKDIR) $(sysconfdir) $(MKDIR) $(RAW_WINALLATOR_DIR) $(MKDIR) $(RRD_WINALLATOR_DIR) - @if test "`echo $(BIN_TARGETS)`"; then \ - for file in $(BIN_TARGETS); do \ - echo $(INSTALL) $$file $(bindir); \ - $(INSTALL) $$file $(bindir); \ - done; \ - fi + @for file in `echo $(BIN_TARGETS)`; do \ + echo $(INSTALL) $$file $(bindir); \ + $(INSTALL) $$file $(bindir); \ + done @if test -r $(sysconfdir)/winallator.cfg; then \ date="`date +%Y-%m-%d-%H:%M:%S`"; \ echo $(INSTALL) -m 0644 winallator.cfg $(sysconfdir)/winallator.cfg.$$date; \ From dmberezin at hotmail.com Wed Nov 17 14:56:14 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Wed, 17 Nov 2004 14:56:14 -0800 Subject: [Orca-checkins] r403 - in trunk/orca/lib/SE: 3.2.1 3.3 3.3.1 Message-ID: <200411172256.iAHMuEaK001258@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Wed Nov 17 14:52:09 2004 New Revision: 403 Added: trunk/orca/lib/SE/3.2.1/orca_process_class.se trunk/orca/lib/SE/3.3.1/orca_process_class.se trunk/orca/lib/SE/3.3/orca_process_class.se Log: Add process_class.se from SE Toolkit to orca distribution * lib/SE/3.2.1/orca_process_class.se * lib/SE/3.3.1/orca_process_class.se * lib/SE/3.3/orca_process_class.se Add a copy of process_class.se as orca_process_class.se for future bug fixing. Added: trunk/orca/lib/SE/3.2.1/orca_process_class.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.2.1/orca_process_class.se Wed Nov 17 14:52:09 2004 @@ -0,0 +1,909 @@ +// +// Copyright (c) 1995-1998, by Sun Microsystems, Inc. +// All Rights Reserved +// + +#ifndef _PROCESS_CLASS_SE_ +#define _PROCESS_CLASS_SE_ + +// 16 Oct 01 richp - more clean ups, some fields not being computed +// 19 Sep 01 richp - replaced struct_fill and changed long to pointer_t +// process class 19 Feb 98 Adrian - 2.6 extras added +// measured and sampled cpu comparison version 18/5/98 +// vmem_delta added for process_rules 27 Nov 98 +// added processor set info 16 Apr 99 +// merged rules version 22 Apri 99 +// added lwp info 5-27-99 Rick Weisner +// added PCUNSET 11-05-99 Rick Weisner +// added se_trees 08-2000 Rick Weisner +// patched linked list login Jul 2001 Rick Weisner + +// Obtain data averaged over the interval between updates +// return one process at a time, snapshot all good stuff +// in one update then provide index$, pid$ methods to extract groups +// of processes. +// Store data in raw form taken from psinfo and pusage ioctls, and +// process it when called up by class. Feeds data to workload_class.se + + +#if MINOR_VERSION < 60 +# error "process_class only works on 2.6 or newer" +#endif + +#include + +long msaccton[2] = { PCSET, PR_MSACCT | PR_MSFORK }; +long msacctoff[2] = { PCUNSET, PR_MSACCT }; + +// codes for action$ +#define PROC_ACTION_INIT 0 // starting point -> next index +#define PROC_ACTION_PID 1 // get the specified pid + // do not sample all PIDS +#define PROC_ACTION_NEXT_INDEX 2 // index order is based on /proc +#define PROC_ACTION_NEXT_PID 3 // search for pid and return data + // do sample all PIDS +#define PROC_ACTION_NEXT_LWP 4 // search for lwp and return data + +// index$ returns -1 if no more data +// proc data updates if index$ is -1 + +struct pr_header_t { + long number_lwps; + size_t size_of_entries; +}; + +struct lwp_prusage { + prusage_t lwp_pru; + long next_lwp_pru; +}; + +struct raw_proc_info_t { // all the per process info + pointer_t orp; // old prusage_t pointer + pointer_t nrp; // new prusage_t pointer + long nextpid; // next pid in list + long gencnt; // update generation counter + // stuff from prpsinfo_t + long pr_flag; // process flags + long pr_size; // size of process image in pages + long pr_oldsize; // previous size of process image + long pr_rssize; // resident set size in pages + long pr_pri; // priority, high value is high priority + char pr_nice; // nice for cpu usage + char pr_sname; // printable character representing pr_state + timestruc_t o_pr_time; // old sampled user+system CPU time + timestruc_t n_pr_time; // sampled user+system CPU time + timestruc_t o_pr_ctime; // old usr+sys cpu time for reaped children + timestruc_t n_pr_ctime; // new usr+sys cpu time for reaped children + long pr_uid; // real user id + long pr_ppid; // process id of parent + int pr_bindpset; // processor set binding +#define PRCLSZ 8 + char pr_clname[PRCLSZ]; // scheduling class name +#define PRFNSZ 16 + char pr_fname[PRFNSZ]; // last component of execed pathname +#define PRARGSZ 80 + char pr_psargs[PRARGSZ];// initial characters of arg list + int lwp_count; + pointer_t olwp; // pointers to prev. lwp prusage linked list + pointer_t nlwp; // pointers to current lwp prusage linked list +}; + +struct lwp_pr_info { + int lwp_id; // always contains lwp_id + double timestamp; // last time lwp was measured + double creation; // lwp start time + double termination; // lwp termination time stamp + double user_time; // user time in this interval + double system_time; // system call time in this interval + double trap_time; // system trap time in interval + double text_pf_time; // text page fault wait in interval + double data_pf_time; // data page fault wait in interval + double kernel_pf_time; // kernel page fault wait in interval + double user_lock_time; // user lock wait in interval + double sleep_time; // all other sleep time + double cpu_wait_time; // time on runqueue waiting for CPU + double stoptime; // time stopped from ^Z + ulong syscalls; // syscall/interval for this process + ulong maj_faults; // majf/interval + ulong min_faults; // minf/interval + ulong total_swaps; // swapout count + ulong inblocks; // input blocks/interval + ulong outblocks; // output blocks/interval + ulong messages; // msgin+msgout/interval + ulong signals; // signals/interval + ulong vcontexts; // voluntary context switches/interval + ulong icontexts; // in-ditto + ulong charios; // characters in and out/interval + ulong next_class; +}; +// the process class that does all the real work + +// get both types of hires timestamp into a common more useful form +#define timestruc(t) (t.tv_sec + (t.tv_nsec / 1000000000.0)) +#define timeval(t) (t.tv_sec + (t.tv_usec / 1000000.0)) +#define hr_min_sec(t) sprintf("%.3f", timestruc(t)) + +// double timestruc(timestruc_t ts_time) { +// return ts_time.tv_sec + (ts_time.tv_nsec / 1000000000.0); +// } + +// double timeval(timeval_t tv_time) { +// return tv_time.tv_sec + (tv_time.tv_usec / 1000000.0); +// } + +// string hr_min_sec(timestruc_t ts) { +// char buf[80]; +// double tmp; +// tmp = timestruc(ts); +// buf = sprintf("%.3f", tmp); +// return buf; +// } + +msprint(prusage_t pru, int pid, string cmd, string arg) { + puts("\n--------------- BEGIN ----------------"); + printf("%d %s %s\n", pid, cmd, arg); + printf("Elapsed time %12s ", hr_min_sec(pru.pr_rtime)); + printf("Create time %s Timestamp %s\n", hr_min_sec(pru.pr_create), + hr_min_sec(pru.pr_tstamp)); + printf("User CPU time %12s ", hr_min_sec(pru.pr_utime)); + printf("System call time %12s\n", hr_min_sec(pru.pr_stime)); + printf("System trap time %12s ", hr_min_sec(pru.pr_ttime)); + printf("Text pfault sleep %12s\n", hr_min_sec(pru.pr_tftime)); + printf("Data pfault sleep %12s ", hr_min_sec(pru.pr_dftime)); + printf("Kernel pfault sleep %12s\n", hr_min_sec(pru.pr_kftime)); + printf("User lock sleep %12s ", hr_min_sec(pru.pr_ltime)); + printf("Other sleep time %12s\n", hr_min_sec(pru.pr_slptime)); + printf("Wait for CPU time %12s ", hr_min_sec(pru.pr_wtime)); + printf("Stopped time %12s\n", hr_min_sec(pru.pr_stoptime)); + printf("pf %d mf %d sw %d inb %d oub %d ms %d mr %d\n", + pru.pr_minf, pru.pr_majf, pru.pr_nswap, pru.pr_inblk, pru.pr_oublk, + pru.pr_msnd, pru.pr_mrcv); + printf("sig %d vctx %d ictx %d sysc %d ioch %d\n", + pru.pr_sigs, pru.pr_vctx, pru.pr_ictx, pru.pr_sysc, pru.pr_ioch); + puts("---------------- END -----------------"); +} + +class proc_class_t { + // input controls + int index$; // always contains current index or -1 + int pid$; // always contains current pid + // for ACTION_PID mode set pid$ and set index$ to -1 to get new data + int action$; + int off$; + int wantlwp$; // 0 = do not want lwps, 1 = want lsps + // summary totals + double lasttime; // timestamp for the end of the last update + int nproc; // current number of processes + int newproc; + int deadproc; + int missedproc; // number of fork+vfork - newproc + // output data for specified process + long flags; // latest pr_flag for the process + double interval; // measured time interval for averages + double timestamp; // last time process was measured + double creation; // process start time + double termination; // process termination time stamp + double elapsed; // elapsed time for all lwps in process + double total_user; // current totals in seconds + double total_system; + double total_sampled_cpu; + double total_child; + double user_time; // user time in this interval + double system_time; // system call time in this interval + double sampled_cpu; // total sampled cpu time + double trap_time; // system trap time in interval + double child_time; // child CPU in this interval + double text_pf_time; // text page fault wait in interval + double data_pf_time; // data page fault wait in interval + double kernel_pf_time; // kernel page fault wait in interval + double user_lock_time; // user lock wait in interval + double sleep_time; // all other sleep time + double cpu_wait_time; // time on runqueue waiting for CPU + double stoptime; // time stopped from ^Z + ulong syscalls; // syscall/interval for this process + ulong inblocks; // input blocks/interval + ulong outblocks; // output blocks/interval + ulong vmem_size; // size in KB + long vmem_delta; // size change in KB + ulong rmem_size; // RSS in KB +#ifdef XMAP + ulong pmem_size; // private mem in KB + ulong smem_size; // shared mem in KB +#endif + ulong maj_faults; // majf/interval + ulong min_faults; // minf/interval + ulong total_swaps; // swapout count + long priority; // current sched priority + long niceness; // current nice value + char sched_class[PRCLSZ]; // name of class + ulong messages; // msgin+msgout/interval + ulong signals; // signals/interval + ulong vcontexts; // voluntary context switches/interval + ulong icontexts; // in-ditto + ulong charios; // characters in and out/interval + ulong lwp_count; // number of lwps for the process + int uid; // current uid + long ppid; // parent pid + int bindpset; // processor set binding + char fname[PRFNSZ]; // last components of exec'd pathname + char args[PRARGSZ]; // initial part of arg list + ulong lwp_class_ptr; // head of linked list of lwp_class_ptrs + + proc$() { + ulong_t MAX_PID; + ulong_t pp; // pointer to malloc for raw proc info + ulong_t pp_tmp; // temp pointer to malloc for raw proc info + ulong_t pp_ret; // temp pointer to malloc for raw proc info + // chained using nextpid + ulong_t pp_tree; + raw_proc_info_t rpi; + raw_proc_info_t t_rpi; + prusage_t ou; // old and new usage data +#define NU nu[0] + prusage_t nu[1]; // array of one for read and ioctl +#define PS ps[0] + psinfo_t ps[1]; // format changes when read used + pr_header_t prh; + prusage_t plwp; + ulong pnu; + ulong pps; + int i; + dirent_t directory_data; + ulong directory_pointer; + ulong directory_entry; + ulong_t tag; + int process_number; // current link in chain + int first_process; // fixed first link in search chain + int previous_process; // last one used to build chain + int next_process; // next pid + int broken_chain; // flag that chain changed this time + int cleaning_chain; // flag that we are in cleanup mode + int pfd; + int lfd; // file descriptor for /prod/PID/lusage + char procname[64]; + char lwpname[64]; // String for /prod/PID/lusage + long gen; // number of generations of update + int err; + int new_entry; + ulong tmp; + double dtmp; + timeval_t tmp_tval[1]; + int pg_to_kb; + + // lwp working storage + prusage_t lwp_info; + pointer_t lwp_t_ptr; + pointer_t olwp_t_ptr; + lwp_prusage lwp_t_struct; + lwp_prusage olwp_t_struct; + lwp_pr_info lwp_t_class; + long lwp_t_class_ptr; + int ircw; + +// ********************************************************** + + if (action$ == PROC_ACTION_INIT) { + action$ = PROC_ACTION_NEXT_INDEX; + // open the directory containing the process data + directory_pointer = opendir("/proc"); + index$ = -1; + off$ = 0 ; + gen = -1; + wantlwp$ = 0; + first_process=-1; + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + pg_to_kb = sysconf(_SC_PAGESIZE) / 1024; + pp_tree= int2int_init(); + if (pnu == 0 || pps == 0) { + pnu = malloc(sizeof(nu)); + pps = malloc(sizeof(ps)); + } + return; + } + + if (index$ == -1) { // update the data from /proc + // read the first entry in the directory + rewinddir(directory_pointer); + directory_entry = readdir(directory_pointer); // read . + directory_entry = readdir(directory_pointer); // read .. + directory_entry = readdir(directory_pointer); + MAX_PID=0; + nproc = 0; + newproc = 0; + deadproc = 0; + gen++; + previous_process = -1; + broken_chain = 0; + cleaning_chain = 0; + while(directory_entry != NULL) { + directory_data = *((dirent_t *) directory_entry); + // get the process number and open the data file + // only look at specified process + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + directory_entry = NULL; + } else { + process_number = atoi(directory_data.d_name); + } + procname = sprintf("/proc/%d/usage", process_number); + pfd = open(procname, O_RDONLY, 0); + // file cannot be accessed if pfd = -1; ignore this process + // may be that there is no permission or just died + if (pfd != -1) { // start of good pfd + if ( process_number > MAX_PID ) { + MAX_PID = process_number ; + } + tag = process_number; + pp_tmp = NULL ; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret != NULL) { + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + // Process Found + } + if (pp_tmp == NULL) { + // load the tree , new process + pp = malloc(sizeof(rpi)); + memset(pp, 0, sizeof(rpi)); + new_entry = 1; + broken_chain = 1; + pp_ret= int2int_put(pp_tree, tag, pp); + if ( pp_ret < 0 ) { + printf(" Error unable to insert into tree %d, %d , %x\n", + pp_ret, tag, pp); + exit(1); + } + pp_ret = int2int_get(pp_tree, tag); + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp != pp_tmp) { + printf(" Error pointers do not match %x, %x \n", + pp, pp_tmp); + exit(1); + } + } else { + new_entry = 0; + // Process Found + } + + // get the existing or blank data + tag = process_number; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret== NULL) { + printf(" Error pointer not found for process_number %d\n", + tag); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid2 \n", process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); + + // read usage info directly + // 2.6 specific, can read usage and psinfo without needing + // ownership or permissions on /proc entry but can't read + // directly into SE structure so go via malloc buffers + + err = read(pfd, pnu, sizeof(nu)); + close(pfd); + + // turn on msacct + + procname = sprintf("/proc/%d/ctl", process_number); + pfd = open(procname, O_WRONLY, 0); + if (pfd != -1) { + if ( off$ == 0 ) { + write(pfd, &msaccton, sizeof(msaccton)); + } else { + printf("%d ms accounting off \n", process_number ); + write(pfd, &msacctoff, sizeof(msaccton)); + } + close(pfd); + } + + // get usage + procname = sprintf("/proc/%d/psinfo", process_number); + pfd = open(procname, O_RDONLY, 0); + err += read(pfd, pps, sizeof(ps)); + NU = *((prusage_t *) pnu); + PS = *((psinfo_t *) pps); + close(pfd); + if (err == 0) { + // process went away since directory was opened + // unlikely but still need to tidy up mallocs + // when it is a new entry + if ( new_entry == 1 ) { + deadproc++; + free(pp); + tag = process_number; + pp_ret=int2int_put(pp_tree, tag, NULL); + if ( pp_ret < 0 ) { + printf("unable to free tag = %d \n",tag); + exit(1); + } + } + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } else { + directory_entry = readdir(directory_pointer); + } + continue; + } else { // good pfd + +// *************************************************************** + + if ( wantlwp$ == 1 ) { + // read the lwp info + lwpname = sprintf("/proc/%d/lusage", process_number); + lfd = open(lwpname, O_RDONLY, 0); + if ( lfd > 0 ) { + lwp_t_ptr = malloc(sizeof(prh)); + err = read(lfd, lwp_t_ptr, sizeof(prh)); + prh = *((pr_header_t *) lwp_t_ptr); + free(lwp_t_ptr); + if (err <= 0) { + printf("Error reading pr_header %s error code = %d \n", + lwpname, err); + } else { // good read of pr_head + // if there is an old lwp linked list free it + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + rpi.olwp = rpi.nlwp; + rpi.nlwp = NULL; + // create new lwp linked list + for (ircw=0; ircw lasttime) { + newproc++; + if (new_entry == 0) { + // leftover from an old process at same pid + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; // dump old rp, and overwrite new + } +// ***************** delete old lwp info ********************* + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + rpi.olwp = NULL; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } +// ***************** end delete old lwp info ********************* + } + // static psinfo needs updating + rpi.pr_uid = PS.pr_uid; + rpi.pr_ppid = PS.pr_ppid; + rpi.pr_bindpset = PS.pr_lwp.pr_bindpset; + rpi.pr_clname = PS.pr_lwp.pr_clname; + rpi.pr_fname = PS.pr_fname; + rpi.pr_psargs = PS.pr_psargs; + } + // update usage data + tmp = rpi.orp; // hang on to malloced data + rpi.orp = rpi.nrp; // switch new to old + if (tmp == NULL) { + rpi.nrp = malloc(sizeof(ou)); + } else { + rpi.nrp = tmp; + } + struct_empty(NU, rpi.nrp); // save whole block + // update dynamic psinfo data + rpi.pr_oldsize = rpi.pr_size; + rpi.pr_size = PS.pr_size; + rpi.pr_rssize = PS.pr_rssize; + rpi.pr_pri = PS.pr_lwp.pr_pri; + rpi.pr_nice = PS.pr_lwp.pr_nice; + rpi.pr_sname = PS.pr_lwp.pr_sname; + rpi.pr_flag = PS.pr_flag; + rpi.o_pr_time = rpi.n_pr_time; + rpi.n_pr_time = PS.pr_time; + rpi.o_pr_ctime = rpi.n_pr_ctime; + rpi.n_pr_ctime = PS.pr_ctime; + rpi.gencnt = gen; + struct_empty(rpi, pp); + nproc++; + // printf("processed %d \n" , process_number ); + } // end of good pfd + // step through the files in the directory ... + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } else { + directory_entry = readdir(directory_pointer); + } + } // end of directory +// ************************************************************** + // go through list and remove deadwood + // printf("first process_number %d \n",first_process); + process_number = first_process; + next_process = -1; + previous_process = -1; + while ( process_number > 0 ) { + // printf("processing %d \n",process_number); + if (process_number > 0 ) { + pp_ret = int2int_get(pp_tree, process_number); + if ( pp_ret == NULL) { + printf("unable to get process_number %d \n", process_number); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid4 \n",process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + next_process = rpi.nextpid; + // printf("next process %d \n",next_process); + // unhook dead processes + if (rpi.gencnt != gen) { + deadproc++; + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; + } + if (rpi.nrp != NULL) { + free(rpi.nrp); + rpi.nrp = NULL; + } + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + lwp_t_ptr = t_rpi.nlwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } + free(pp); + pp_ret = int2int_put(pp_tree, process_number , NULL); + if ( pp_ret < 0 ) { + printf("unable to free process_number \n"); + exit(1); + } + if ( previous_process > 0 ) { // there was a previous process + pp_tmp = int2int_get(pp_tree, previous_process); + if ( pp_tmp == NULL) { + printf("unable to get process_number %d \n", + previous_process); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_tmp)); + if ( pp == NULL) { + printf("process_number %d invalid5 \n", + previous_process); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + // printf("previous process %d \n",previous_process); + rpi.nextpid = next_process; + struct_empty(rpi, pp); + } else { + first_process = next_process; + } + } else { + // update previous process ptr + previous_process = process_number; + } + } + process_number = next_process; + } + // printf(" end of deadwood removal \n"); + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + process_number = first_process; + index$ = -1; + } + // printf("done updating \n"); + // printf("MAX_PID = %d \n", MAX_PID); +// ****************************** end of update section ******************* + + if (action$ == PROC_ACTION_NEXT_INDEX ) { + // printf("PROC_ACTION_NEXT_INDEX \n"); + if (index$ == -1) { + process_number = first_process; + } else { + process_number = rpi.nextpid; + } + if (process_number < 0 || process_number > MAX_PID) { + // ran out of data + process_number = -1; + index$ = -1; + pid$ = -1; + // printf(" thats all there is \n"); + return; + } + index$++; + } + + if (action$ == PROC_ACTION_NEXT_PID) { + // printf("PROC_ACTION_NEXT_PID \n"); + if (index$ == -1) { + process_number = 0; + } else { + process_number++; + } + index$++; + // look for the next data + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + while (process_number < MAX_PID && pp == NULL) { + process_number++; + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + } + if (process_number < 0 || process_number > MAX_PID) { + // ran out of data + process_number = -1; + index$ = -1; + pid$ = -1; + // printf(" ran out of data NEXT PID \n"); + return; + } + } + + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + index$ = 0; + } + + // common code to update class once process has been chosen + + pp_ret=int2int_get(pp_tree,process_number); + pp = NULL; + if (pp_ret != NULL) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + if ( pp != NULL) { + rpi = *((raw_proc_info_t *) pp); + // make sure that all class data is updated + // index$ is already set + pid$ = process_number; + uid = rpi.pr_uid; + // nproc, , are already set + missedproc = rpi.nextpid; // for debug until fork counting + + // nrp will always be set + NU = *((prusage_t *) rpi.nrp); + creation = timestruc(NU.pr_create); + timestamp = timestruc(NU.pr_tstamp); + termination = 0.0; // set later if process is dead + elapsed = timestruc(NU.pr_rtime); + total_user = timestruc(NU.pr_utime); + total_system = timestruc(NU.pr_stime); + total_child = timestruc(rpi.n_pr_ctime); + total_sampled_cpu = timestruc(rpi.n_pr_time); + flags = rpi.pr_flag; +#ifdef PDEBUG + msprint(NU, pid$, rpi.pr_fname, rpi.pr_psargs); +#endif + if (rpi.orp != NULL) { + ou = *((prusage_t *) rpi.orp); + interval = timestamp - timestruc(ou.pr_tstamp); + // interval should never be zero + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(ou, pid$, fname, args); + interval = 1.0; + } + user_time = total_user - timestruc(ou.pr_utime); + system_time = total_system - timestruc(ou.pr_stime); + sampled_cpu = total_sampled_cpu - timestruc(rpi.o_pr_time); + trap_time = timestruc(NU.pr_ttime) - timestruc(ou.pr_ttime); + child_time = total_child - timestruc(rpi.o_pr_ctime); + text_pf_time = timestruc(NU.pr_tftime) - timestruc(ou.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime) - timestruc(ou.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime) - timestruc(ou.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime) - timestruc(ou.pr_ltime); + sleep_time = timestruc(NU.pr_slptime) - timestruc(ou.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime) - timestruc(ou.pr_wtime); + stoptime = timestruc(NU.pr_stoptime) - timestruc(ou.pr_stoptime); + syscalls = NU.pr_sysc - ou.pr_sysc; + inblocks = NU.pr_inblk - ou.pr_inblk; + outblocks = NU.pr_oublk - ou.pr_oublk; + maj_faults = NU.pr_majf - ou.pr_majf; + min_faults = NU.pr_minf - ou.pr_minf; + messages = (NU.pr_msnd + NU.pr_mrcv) - (ou.pr_msnd + ou.pr_mrcv); + signals = NU.pr_sigs - ou.pr_sigs; + vcontexts = NU.pr_vctx - ou.pr_vctx; + icontexts = NU.pr_ictx - ou.pr_ictx; + charios = NU.pr_ioch - ou.pr_ioch; + } else { + // new process will only have rpi.nrp set + interval = timestamp - creation; // elapsed time so far + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(NU, pid$, fname, args); + interval = 1.0; + } + user_time = total_user; + system_time = total_system; + sampled_cpu = total_sampled_cpu; + trap_time = timestruc(NU.pr_ttime); + child_time = total_child; + text_pf_time = timestruc(NU.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime); + sleep_time = timestruc(NU.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime); + stoptime = timestruc(NU.pr_stoptime); + syscalls = NU.pr_sysc; + inblocks = NU.pr_inblk; + outblocks = NU.pr_oublk; + maj_faults = NU.pr_majf; + min_faults = NU.pr_minf; + messages = NU.pr_msnd + NU.pr_mrcv; + signals = NU.pr_sigs; + vcontexts = NU.pr_vctx; + icontexts = NU.pr_ictx; + charios = NU.pr_ioch; + } + vmem_size = rpi.pr_size; + vmem_delta = rpi.pr_size - rpi.pr_oldsize; + rmem_size = rpi.pr_rssize; + total_swaps = NU.pr_nswap; + priority = rpi.pr_pri; + niceness = rpi.pr_nice; + sched_class = rpi.pr_clname; + lwp_count = NU.pr_count; + ppid = rpi.pr_ppid; + bindpset = rpi.pr_bindpset; + fname = rpi.pr_fname; + if (fname == "" && rpi.pr_sname == 'Z') { + fname = "Zombie"; + bindpset = -1; // no pset, but Zomb defaults to 0 + } + args = rpi.pr_psargs; + // bug in sched pid 0 gives 100% system time + if (pid$ == 0) { + total_system = 0.0; + system_time = 0.0; + } +#ifdef PDEBUG + printf("interval %.5f\n", interval); +#endif +// ******************************************************* + if ( wantlwp$ == 1 ) { + // process lwp info + lwp_t_ptr = lwp_class_ptr; + lwp_class_ptr = NULL; + // if there is an old lwp class linked list free it + while ( lwp_t_ptr != NULL ) { + lwp_t_class = *((lwp_pr_info *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_class.next_class ; + } + // Process lwp information + if ( rpi.nlwp != NULL ) { + lwp_t_ptr = rpi.nlwp ; + while ( lwp_t_ptr != NULL) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + lwp_t_class.lwp_id = lwp_t_struct.lwp_pru.pr_lwpid; + lwp_t_class.timestamp = timestruc(lwp_t_struct.lwp_pru.pr_tstamp); + lwp_t_class.creation = timestruc(lwp_t_struct.lwp_pru.pr_create); + lwp_t_class.termination = timestruc(lwp_t_struct.lwp_pru.pr_term); + lwp_t_class.user_time = timestruc(lwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = timestruc(lwp_t_struct.lwp_pru.pr_stime) + timestruc(lwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = timestruc(lwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = timestruc(lwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = timestruc(lwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = timestruc(lwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_struct.lwp_pru.pr_ioch; + + olwp_t_ptr = rpi.olwp; + while ( olwp_t_ptr != NULL ) { + olwp_t_struct = *((lwp_prusage *) olwp_t_ptr); + if ( olwp_t_struct.lwp_pru.pr_lwpid == + lwp_t_struct.lwp_pru.pr_lwpid) { + break; + } + olwp_t_ptr = olwp_t_struct.next_lwp_pru ; + } + if ( olwp_t_ptr != NULL) { + lwp_t_class.user_time = lwp_t_class.user_time - timestruc(olwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = lwp_t_class.system_time - timestruc(olwp_t_struct.lwp_pru.pr_stime) - timestruc(olwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = lwp_t_class.text_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = lwp_t_class.data_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = lwp_t_class.kernel_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = lwp_t_class.user_lock_time - timestruc(olwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = lwp_t_class.sleep_time - timestruc(olwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = lwp_t_class.cpu_wait_time - timestruc(olwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = lwp_t_class.stoptime - timestruc(olwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_class.min_faults - olwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_class.maj_faults - olwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_class.total_swaps - olwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_class.inblocks - olwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_class.outblocks - olwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_class.messages - olwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_class.signals - olwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_class.vcontexts - olwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_class.icontexts - olwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_class.syscalls - olwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_class.charios - olwp_t_struct.lwp_pru.pr_ioch; + + } // end of if old pointer + lwp_t_class_ptr = malloc(sizeof(lwp_t_class)); + memset(lwp_t_class_ptr, NULL, sizeof(lwp_t_class)); + lwp_t_class.next_class = lwp_class_ptr; + lwp_class_ptr = lwp_t_class_ptr; + struct_empty(lwp_t_class, lwp_t_class_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } // end of while + } // end of if we have lwps + } // end of we want lwps + } else { // End if valid pp + process_number = -1; + index$ = -1; + pid$ = -1; + } + } +}; + +#endif Added: trunk/orca/lib/SE/3.3.1/orca_process_class.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.3.1/orca_process_class.se Wed Nov 17 14:52:09 2004 @@ -0,0 +1,909 @@ +// +// Copyright (c) 1995-1998, by Sun Microsystems, Inc. +// All Rights Reserved +// + +#ifndef _PROCESS_CLASS_SE_ +#define _PROCESS_CLASS_SE_ + +// 16 Oct 01 richp - more clean ups, some fields not being computed +// 19 Sep 01 richp - replaced struct_fill and changed long to pointer_t +// process class 19 Feb 98 Adrian - 2.6 extras added +// measured and sampled cpu comparison version 18/5/98 +// vmem_delta added for process_rules 27 Nov 98 +// added processor set info 16 Apr 99 +// merged rules version 22 Apri 99 +// added lwp info 5-27-99 Rick Weisner +// added PCUNSET 11-05-99 Rick Weisner +// added se_trees 08-2000 Rick Weisner +// patched linked list login Jul 2001 Rick Weisner + +// Obtain data averaged over the interval between updates +// return one process at a time, snapshot all good stuff +// in one update then provide index$, pid$ methods to extract groups +// of processes. +// Store data in raw form taken from psinfo and pusage ioctls, and +// process it when called up by class. Feeds data to workload_class.se + + +#if MINOR_VERSION < 60 +# error "process_class only works on 2.6 or newer" +#endif + +#include + +long msaccton[2] = { PCSET, PR_MSACCT | PR_MSFORK }; +long msacctoff[2] = { PCUNSET, PR_MSACCT }; + +// codes for action$ +#define PROC_ACTION_INIT 0 // starting point -> next index +#define PROC_ACTION_PID 1 // get the specified pid + // do not sample all PIDS +#define PROC_ACTION_NEXT_INDEX 2 // index order is based on /proc +#define PROC_ACTION_NEXT_PID 3 // search for pid and return data + // do sample all PIDS +#define PROC_ACTION_NEXT_LWP 4 // search for lwp and return data + +// index$ returns -1 if no more data +// proc data updates if index$ is -1 + +struct pr_header_t { + long number_lwps; + size_t size_of_entries; +}; + +struct lwp_prusage { + prusage_t lwp_pru; + long next_lwp_pru; +}; + +struct raw_proc_info_t { // all the per process info + pointer_t orp; // old prusage_t pointer + pointer_t nrp; // new prusage_t pointer + long nextpid; // next pid in list + long gencnt; // update generation counter + // stuff from prpsinfo_t + long pr_flag; // process flags + long pr_size; // size of process image in pages + long pr_oldsize; // previous size of process image + long pr_rssize; // resident set size in pages + long pr_pri; // priority, high value is high priority + char pr_nice; // nice for cpu usage + char pr_sname; // printable character representing pr_state + timestruc_t o_pr_time; // old sampled user+system CPU time + timestruc_t n_pr_time; // sampled user+system CPU time + timestruc_t o_pr_ctime; // old usr+sys cpu time for reaped children + timestruc_t n_pr_ctime; // new usr+sys cpu time for reaped children + long pr_uid; // real user id + long pr_ppid; // process id of parent + int pr_bindpset; // processor set binding +#define PRCLSZ 8 + char pr_clname[PRCLSZ]; // scheduling class name +#define PRFNSZ 16 + char pr_fname[PRFNSZ]; // last component of execed pathname +#define PRARGSZ 80 + char pr_psargs[PRARGSZ];// initial characters of arg list + int lwp_count; + pointer_t olwp; // pointers to prev. lwp prusage linked list + pointer_t nlwp; // pointers to current lwp prusage linked list +}; + +struct lwp_pr_info { + int lwp_id; // always contains lwp_id + double timestamp; // last time lwp was measured + double creation; // lwp start time + double termination; // lwp termination time stamp + double user_time; // user time in this interval + double system_time; // system call time in this interval + double trap_time; // system trap time in interval + double text_pf_time; // text page fault wait in interval + double data_pf_time; // data page fault wait in interval + double kernel_pf_time; // kernel page fault wait in interval + double user_lock_time; // user lock wait in interval + double sleep_time; // all other sleep time + double cpu_wait_time; // time on runqueue waiting for CPU + double stoptime; // time stopped from ^Z + ulong syscalls; // syscall/interval for this process + ulong maj_faults; // majf/interval + ulong min_faults; // minf/interval + ulong total_swaps; // swapout count + ulong inblocks; // input blocks/interval + ulong outblocks; // output blocks/interval + ulong messages; // msgin+msgout/interval + ulong signals; // signals/interval + ulong vcontexts; // voluntary context switches/interval + ulong icontexts; // in-ditto + ulong charios; // characters in and out/interval + ulong next_class; +}; +// the process class that does all the real work + +// get both types of hires timestamp into a common more useful form +#define timestruc(t) (t.tv_sec + (t.tv_nsec / 1000000000.0)) +#define timeval(t) (t.tv_sec + (t.tv_usec / 1000000.0)) +#define hr_min_sec(t) sprintf("%.3f", timestruc(t)) + +// double timestruc(timestruc_t ts_time) { +// return ts_time.tv_sec + (ts_time.tv_nsec / 1000000000.0); +// } + +// double timeval(timeval_t tv_time) { +// return tv_time.tv_sec + (tv_time.tv_usec / 1000000.0); +// } + +// string hr_min_sec(timestruc_t ts) { +// char buf[80]; +// double tmp; +// tmp = timestruc(ts); +// buf = sprintf("%.3f", tmp); +// return buf; +// } + +msprint(prusage_t pru, int pid, string cmd, string arg) { + puts("\n--------------- BEGIN ----------------"); + printf("%d %s %s\n", pid, cmd, arg); + printf("Elapsed time %12s ", hr_min_sec(pru.pr_rtime)); + printf("Create time %s Timestamp %s\n", hr_min_sec(pru.pr_create), + hr_min_sec(pru.pr_tstamp)); + printf("User CPU time %12s ", hr_min_sec(pru.pr_utime)); + printf("System call time %12s\n", hr_min_sec(pru.pr_stime)); + printf("System trap time %12s ", hr_min_sec(pru.pr_ttime)); + printf("Text pfault sleep %12s\n", hr_min_sec(pru.pr_tftime)); + printf("Data pfault sleep %12s ", hr_min_sec(pru.pr_dftime)); + printf("Kernel pfault sleep %12s\n", hr_min_sec(pru.pr_kftime)); + printf("User lock sleep %12s ", hr_min_sec(pru.pr_ltime)); + printf("Other sleep time %12s\n", hr_min_sec(pru.pr_slptime)); + printf("Wait for CPU time %12s ", hr_min_sec(pru.pr_wtime)); + printf("Stopped time %12s\n", hr_min_sec(pru.pr_stoptime)); + printf("pf %d mf %d sw %d inb %d oub %d ms %d mr %d\n", + pru.pr_minf, pru.pr_majf, pru.pr_nswap, pru.pr_inblk, pru.pr_oublk, + pru.pr_msnd, pru.pr_mrcv); + printf("sig %d vctx %d ictx %d sysc %d ioch %d\n", + pru.pr_sigs, pru.pr_vctx, pru.pr_ictx, pru.pr_sysc, pru.pr_ioch); + puts("---------------- END -----------------"); +} + +class proc_class_t { + // input controls + int index$; // always contains current index or -1 + int pid$; // always contains current pid + // for ACTION_PID mode set pid$ and set index$ to -1 to get new data + int action$; + int off$; + int wantlwp$; // 0 = do not want lwps, 1 = want lsps + // summary totals + double lasttime; // timestamp for the end of the last update + int nproc; // current number of processes + int newproc; + int deadproc; + int missedproc; // number of fork+vfork - newproc + // output data for specified process + long flags; // latest pr_flag for the process + double interval; // measured time interval for averages + double timestamp; // last time process was measured + double creation; // process start time + double termination; // process termination time stamp + double elapsed; // elapsed time for all lwps in process + double total_user; // current totals in seconds + double total_system; + double total_sampled_cpu; + double total_child; + double user_time; // user time in this interval + double system_time; // system call time in this interval + double sampled_cpu; // total sampled cpu time + double trap_time; // system trap time in interval + double child_time; // child CPU in this interval + double text_pf_time; // text page fault wait in interval + double data_pf_time; // data page fault wait in interval + double kernel_pf_time; // kernel page fault wait in interval + double user_lock_time; // user lock wait in interval + double sleep_time; // all other sleep time + double cpu_wait_time; // time on runqueue waiting for CPU + double stoptime; // time stopped from ^Z + ulong syscalls; // syscall/interval for this process + ulong inblocks; // input blocks/interval + ulong outblocks; // output blocks/interval + ulong vmem_size; // size in KB + long vmem_delta; // size change in KB + ulong rmem_size; // RSS in KB +#ifdef XMAP + ulong pmem_size; // private mem in KB + ulong smem_size; // shared mem in KB +#endif + ulong maj_faults; // majf/interval + ulong min_faults; // minf/interval + ulong total_swaps; // swapout count + long priority; // current sched priority + long niceness; // current nice value + char sched_class[PRCLSZ]; // name of class + ulong messages; // msgin+msgout/interval + ulong signals; // signals/interval + ulong vcontexts; // voluntary context switches/interval + ulong icontexts; // in-ditto + ulong charios; // characters in and out/interval + ulong lwp_count; // number of lwps for the process + int uid; // current uid + long ppid; // parent pid + int bindpset; // processor set binding + char fname[PRFNSZ]; // last components of exec'd pathname + char args[PRARGSZ]; // initial part of arg list + ulong lwp_class_ptr; // head of linked list of lwp_class_ptrs + + proc$() { + ulong_t MAX_PID; + ulong_t pp; // pointer to malloc for raw proc info + ulong_t pp_tmp; // temp pointer to malloc for raw proc info + ulong_t pp_ret; // temp pointer to malloc for raw proc info + // chained using nextpid + ulong_t pp_tree; + raw_proc_info_t rpi; + raw_proc_info_t t_rpi; + prusage_t ou; // old and new usage data +#define NU nu[0] + prusage_t nu[1]; // array of one for read and ioctl +#define PS ps[0] + psinfo_t ps[1]; // format changes when read used + pr_header_t prh; + prusage_t plwp; + ulong pnu; + ulong pps; + int i; + dirent_t directory_data; + ulong directory_pointer; + ulong directory_entry; + ulong_t tag; + int process_number; // current link in chain + int first_process; // fixed first link in search chain + int previous_process; // last one used to build chain + int next_process; // next pid + int broken_chain; // flag that chain changed this time + int cleaning_chain; // flag that we are in cleanup mode + int pfd; + int lfd; // file descriptor for /prod/PID/lusage + char procname[64]; + char lwpname[64]; // String for /prod/PID/lusage + long gen; // number of generations of update + int err; + int new_entry; + ulong tmp; + double dtmp; + timeval_t tmp_tval[1]; + int pg_to_kb; + + // lwp working storage + prusage_t lwp_info; + pointer_t lwp_t_ptr; + pointer_t olwp_t_ptr; + lwp_prusage lwp_t_struct; + lwp_prusage olwp_t_struct; + lwp_pr_info lwp_t_class; + long lwp_t_class_ptr; + int ircw; + +// ********************************************************** + + if (action$ == PROC_ACTION_INIT) { + action$ = PROC_ACTION_NEXT_INDEX; + // open the directory containing the process data + directory_pointer = opendir("/proc"); + index$ = -1; + off$ = 0 ; + gen = -1; + wantlwp$ = 0; + first_process=-1; + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + pg_to_kb = sysconf(_SC_PAGESIZE) / 1024; + pp_tree= int2int_init(); + if (pnu == 0 || pps == 0) { + pnu = malloc(sizeof(nu)); + pps = malloc(sizeof(ps)); + } + return; + } + + if (index$ == -1) { // update the data from /proc + // read the first entry in the directory + rewinddir(directory_pointer); + directory_entry = readdir(directory_pointer); // read . + directory_entry = readdir(directory_pointer); // read .. + directory_entry = readdir(directory_pointer); + MAX_PID=0; + nproc = 0; + newproc = 0; + deadproc = 0; + gen++; + previous_process = -1; + broken_chain = 0; + cleaning_chain = 0; + while(directory_entry != NULL) { + directory_data = *((dirent_t *) directory_entry); + // get the process number and open the data file + // only look at specified process + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + directory_entry = NULL; + } else { + process_number = atoi(directory_data.d_name); + } + procname = sprintf("/proc/%d/usage", process_number); + pfd = open(procname, O_RDONLY, 0); + // file cannot be accessed if pfd = -1; ignore this process + // may be that there is no permission or just died + if (pfd != -1) { // start of good pfd + if ( process_number > MAX_PID ) { + MAX_PID = process_number ; + } + tag = process_number; + pp_tmp = NULL ; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret != NULL) { + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + // Process Found + } + if (pp_tmp == NULL) { + // load the tree , new process + pp = malloc(sizeof(rpi)); + memset(pp, 0, sizeof(rpi)); + new_entry = 1; + broken_chain = 1; + pp_ret= int2int_put(pp_tree, tag, pp); + if ( pp_ret < 0 ) { + printf(" Error unable to insert into tree %d, %d , %x\n", + pp_ret, tag, pp); + exit(1); + } + pp_ret = int2int_get(pp_tree, tag); + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp != pp_tmp) { + printf(" Error pointers do not match %x, %x \n", + pp, pp_tmp); + exit(1); + } + } else { + new_entry = 0; + // Process Found + } + + // get the existing or blank data + tag = process_number; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret== NULL) { + printf(" Error pointer not found for process_number %d\n", + tag); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid2 \n", process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); + + // read usage info directly + // 2.6 specific, can read usage and psinfo without needing + // ownership or permissions on /proc entry but can't read + // directly into SE structure so go via malloc buffers + + err = read(pfd, pnu, sizeof(nu)); + close(pfd); + + // turn on msacct + + procname = sprintf("/proc/%d/ctl", process_number); + pfd = open(procname, O_WRONLY, 0); + if (pfd != -1) { + if ( off$ == 0 ) { + write(pfd, &msaccton, sizeof(msaccton)); + } else { + printf("%d ms accounting off \n", process_number ); + write(pfd, &msacctoff, sizeof(msaccton)); + } + close(pfd); + } + + // get usage + procname = sprintf("/proc/%d/psinfo", process_number); + pfd = open(procname, O_RDONLY, 0); + err += read(pfd, pps, sizeof(ps)); + NU = *((prusage_t *) pnu); + PS = *((psinfo_t *) pps); + close(pfd); + if (err == 0) { + // process went away since directory was opened + // unlikely but still need to tidy up mallocs + // when it is a new entry + if ( new_entry == 1 ) { + deadproc++; + free(pp); + tag = process_number; + pp_ret=int2int_put(pp_tree, tag, NULL); + if ( pp_ret < 0 ) { + printf("unable to free tag = %d \n",tag); + exit(1); + } + } + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } else { + directory_entry = readdir(directory_pointer); + } + continue; + } else { // good pfd + +// *************************************************************** + + if ( wantlwp$ == 1 ) { + // read the lwp info + lwpname = sprintf("/proc/%d/lusage", process_number); + lfd = open(lwpname, O_RDONLY, 0); + if ( lfd > 0 ) { + lwp_t_ptr = malloc(sizeof(prh)); + err = read(lfd, lwp_t_ptr, sizeof(prh)); + prh = *((pr_header_t *) lwp_t_ptr); + free(lwp_t_ptr); + if (err <= 0) { + printf("Error reading pr_header %s error code = %d \n", + lwpname, err); + } else { // good read of pr_head + // if there is an old lwp linked list free it + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + rpi.olwp = rpi.nlwp; + rpi.nlwp = NULL; + // create new lwp linked list + for (ircw=0; ircw lasttime) { + newproc++; + if (new_entry == 0) { + // leftover from an old process at same pid + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; // dump old rp, and overwrite new + } +// ***************** delete old lwp info ********************* + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + rpi.olwp = NULL; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } +// ***************** end delete old lwp info ********************* + } + // static psinfo needs updating + rpi.pr_uid = PS.pr_uid; + rpi.pr_ppid = PS.pr_ppid; + rpi.pr_bindpset = PS.pr_lwp.pr_bindpset; + rpi.pr_clname = PS.pr_lwp.pr_clname; + rpi.pr_fname = PS.pr_fname; + rpi.pr_psargs = PS.pr_psargs; + } + // update usage data + tmp = rpi.orp; // hang on to malloced data + rpi.orp = rpi.nrp; // switch new to old + if (tmp == NULL) { + rpi.nrp = malloc(sizeof(ou)); + } else { + rpi.nrp = tmp; + } + struct_empty(NU, rpi.nrp); // save whole block + // update dynamic psinfo data + rpi.pr_oldsize = rpi.pr_size; + rpi.pr_size = PS.pr_size; + rpi.pr_rssize = PS.pr_rssize; + rpi.pr_pri = PS.pr_lwp.pr_pri; + rpi.pr_nice = PS.pr_lwp.pr_nice; + rpi.pr_sname = PS.pr_lwp.pr_sname; + rpi.pr_flag = PS.pr_flag; + rpi.o_pr_time = rpi.n_pr_time; + rpi.n_pr_time = PS.pr_time; + rpi.o_pr_ctime = rpi.n_pr_ctime; + rpi.n_pr_ctime = PS.pr_ctime; + rpi.gencnt = gen; + struct_empty(rpi, pp); + nproc++; + // printf("processed %d \n" , process_number ); + } // end of good pfd + // step through the files in the directory ... + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } else { + directory_entry = readdir(directory_pointer); + } + } // end of directory +// ************************************************************** + // go through list and remove deadwood + // printf("first process_number %d \n",first_process); + process_number = first_process; + next_process = -1; + previous_process = -1; + while ( process_number > 0 ) { + // printf("processing %d \n",process_number); + if (process_number > 0 ) { + pp_ret = int2int_get(pp_tree, process_number); + if ( pp_ret == NULL) { + printf("unable to get process_number %d \n", process_number); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid4 \n",process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + next_process = rpi.nextpid; + // printf("next process %d \n",next_process); + // unhook dead processes + if (rpi.gencnt != gen) { + deadproc++; + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; + } + if (rpi.nrp != NULL) { + free(rpi.nrp); + rpi.nrp = NULL; + } + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + lwp_t_ptr = t_rpi.nlwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } + free(pp); + pp_ret = int2int_put(pp_tree, process_number , NULL); + if ( pp_ret < 0 ) { + printf("unable to free process_number \n"); + exit(1); + } + if ( previous_process > 0 ) { // there was a previous process + pp_tmp = int2int_get(pp_tree, previous_process); + if ( pp_tmp == NULL) { + printf("unable to get process_number %d \n", + previous_process); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_tmp)); + if ( pp == NULL) { + printf("process_number %d invalid5 \n", + previous_process); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + // printf("previous process %d \n",previous_process); + rpi.nextpid = next_process; + struct_empty(rpi, pp); + } else { + first_process = next_process; + } + } else { + // update previous process ptr + previous_process = process_number; + } + } + process_number = next_process; + } + // printf(" end of deadwood removal \n"); + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + process_number = first_process; + index$ = -1; + } + // printf("done updating \n"); + // printf("MAX_PID = %d \n", MAX_PID); +// ****************************** end of update section ******************* + + if (action$ == PROC_ACTION_NEXT_INDEX ) { + // printf("PROC_ACTION_NEXT_INDEX \n"); + if (index$ == -1) { + process_number = first_process; + } else { + process_number = rpi.nextpid; + } + if (process_number < 0 || process_number > MAX_PID) { + // ran out of data + process_number = -1; + index$ = -1; + pid$ = -1; + // printf(" thats all there is \n"); + return; + } + index$++; + } + + if (action$ == PROC_ACTION_NEXT_PID) { + // printf("PROC_ACTION_NEXT_PID \n"); + if (index$ == -1) { + process_number = 0; + } else { + process_number++; + } + index$++; + // look for the next data + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + while (process_number < MAX_PID && pp == NULL) { + process_number++; + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + } + if (process_number < 0 || process_number > MAX_PID) { + // ran out of data + process_number = -1; + index$ = -1; + pid$ = -1; + // printf(" ran out of data NEXT PID \n"); + return; + } + } + + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + index$ = 0; + } + + // common code to update class once process has been chosen + + pp_ret=int2int_get(pp_tree,process_number); + pp = NULL; + if (pp_ret != NULL) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + if ( pp != NULL) { + rpi = *((raw_proc_info_t *) pp); + // make sure that all class data is updated + // index$ is already set + pid$ = process_number; + uid = rpi.pr_uid; + // nproc, , are already set + missedproc = rpi.nextpid; // for debug until fork counting + + // nrp will always be set + NU = *((prusage_t *) rpi.nrp); + creation = timestruc(NU.pr_create); + timestamp = timestruc(NU.pr_tstamp); + termination = 0.0; // set later if process is dead + elapsed = timestruc(NU.pr_rtime); + total_user = timestruc(NU.pr_utime); + total_system = timestruc(NU.pr_stime); + total_child = timestruc(rpi.n_pr_ctime); + total_sampled_cpu = timestruc(rpi.n_pr_time); + flags = rpi.pr_flag; +#ifdef PDEBUG + msprint(NU, pid$, rpi.pr_fname, rpi.pr_psargs); +#endif + if (rpi.orp != NULL) { + ou = *((prusage_t *) rpi.orp); + interval = timestamp - timestruc(ou.pr_tstamp); + // interval should never be zero + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(ou, pid$, fname, args); + interval = 1.0; + } + user_time = total_user - timestruc(ou.pr_utime); + system_time = total_system - timestruc(ou.pr_stime); + sampled_cpu = total_sampled_cpu - timestruc(rpi.o_pr_time); + trap_time = timestruc(NU.pr_ttime) - timestruc(ou.pr_ttime); + child_time = total_child - timestruc(rpi.o_pr_ctime); + text_pf_time = timestruc(NU.pr_tftime) - timestruc(ou.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime) - timestruc(ou.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime) - timestruc(ou.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime) - timestruc(ou.pr_ltime); + sleep_time = timestruc(NU.pr_slptime) - timestruc(ou.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime) - timestruc(ou.pr_wtime); + stoptime = timestruc(NU.pr_stoptime) - timestruc(ou.pr_stoptime); + syscalls = NU.pr_sysc - ou.pr_sysc; + inblocks = NU.pr_inblk - ou.pr_inblk; + outblocks = NU.pr_oublk - ou.pr_oublk; + maj_faults = NU.pr_majf - ou.pr_majf; + min_faults = NU.pr_minf - ou.pr_minf; + messages = (NU.pr_msnd + NU.pr_mrcv) - (ou.pr_msnd + ou.pr_mrcv); + signals = NU.pr_sigs - ou.pr_sigs; + vcontexts = NU.pr_vctx - ou.pr_vctx; + icontexts = NU.pr_ictx - ou.pr_ictx; + charios = NU.pr_ioch - ou.pr_ioch; + } else { + // new process will only have rpi.nrp set + interval = timestamp - creation; // elapsed time so far + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(NU, pid$, fname, args); + interval = 1.0; + } + user_time = total_user; + system_time = total_system; + sampled_cpu = total_sampled_cpu; + trap_time = timestruc(NU.pr_ttime); + child_time = total_child; + text_pf_time = timestruc(NU.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime); + sleep_time = timestruc(NU.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime); + stoptime = timestruc(NU.pr_stoptime); + syscalls = NU.pr_sysc; + inblocks = NU.pr_inblk; + outblocks = NU.pr_oublk; + maj_faults = NU.pr_majf; + min_faults = NU.pr_minf; + messages = NU.pr_msnd + NU.pr_mrcv; + signals = NU.pr_sigs; + vcontexts = NU.pr_vctx; + icontexts = NU.pr_ictx; + charios = NU.pr_ioch; + } + vmem_size = rpi.pr_size; + vmem_delta = rpi.pr_size - rpi.pr_oldsize; + rmem_size = rpi.pr_rssize; + total_swaps = NU.pr_nswap; + priority = rpi.pr_pri; + niceness = rpi.pr_nice; + sched_class = rpi.pr_clname; + lwp_count = NU.pr_count; + ppid = rpi.pr_ppid; + bindpset = rpi.pr_bindpset; + fname = rpi.pr_fname; + if (fname == "" && rpi.pr_sname == 'Z') { + fname = "Zombie"; + bindpset = -1; // no pset, but Zomb defaults to 0 + } + args = rpi.pr_psargs; + // bug in sched pid 0 gives 100% system time + if (pid$ == 0) { + total_system = 0.0; + system_time = 0.0; + } +#ifdef PDEBUG + printf("interval %.5f\n", interval); +#endif +// ******************************************************* + if ( wantlwp$ == 1 ) { + // process lwp info + lwp_t_ptr = lwp_class_ptr; + lwp_class_ptr = NULL; + // if there is an old lwp class linked list free it + while ( lwp_t_ptr != NULL ) { + lwp_t_class = *((lwp_pr_info *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_class.next_class ; + } + // Process lwp information + if ( rpi.nlwp != NULL ) { + lwp_t_ptr = rpi.nlwp ; + while ( lwp_t_ptr != NULL) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + lwp_t_class.lwp_id = lwp_t_struct.lwp_pru.pr_lwpid; + lwp_t_class.timestamp = timestruc(lwp_t_struct.lwp_pru.pr_tstamp); + lwp_t_class.creation = timestruc(lwp_t_struct.lwp_pru.pr_create); + lwp_t_class.termination = timestruc(lwp_t_struct.lwp_pru.pr_term); + lwp_t_class.user_time = timestruc(lwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = timestruc(lwp_t_struct.lwp_pru.pr_stime) + timestruc(lwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = timestruc(lwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = timestruc(lwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = timestruc(lwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = timestruc(lwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_struct.lwp_pru.pr_ioch; + + olwp_t_ptr = rpi.olwp; + while ( olwp_t_ptr != NULL ) { + olwp_t_struct = *((lwp_prusage *) olwp_t_ptr); + if ( olwp_t_struct.lwp_pru.pr_lwpid == + lwp_t_struct.lwp_pru.pr_lwpid) { + break; + } + olwp_t_ptr = olwp_t_struct.next_lwp_pru ; + } + if ( olwp_t_ptr != NULL) { + lwp_t_class.user_time = lwp_t_class.user_time - timestruc(olwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = lwp_t_class.system_time - timestruc(olwp_t_struct.lwp_pru.pr_stime) - timestruc(olwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = lwp_t_class.text_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = lwp_t_class.data_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = lwp_t_class.kernel_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = lwp_t_class.user_lock_time - timestruc(olwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = lwp_t_class.sleep_time - timestruc(olwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = lwp_t_class.cpu_wait_time - timestruc(olwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = lwp_t_class.stoptime - timestruc(olwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_class.min_faults - olwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_class.maj_faults - olwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_class.total_swaps - olwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_class.inblocks - olwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_class.outblocks - olwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_class.messages - olwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_class.signals - olwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_class.vcontexts - olwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_class.icontexts - olwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_class.syscalls - olwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_class.charios - olwp_t_struct.lwp_pru.pr_ioch; + + } // end of if old pointer + lwp_t_class_ptr = malloc(sizeof(lwp_t_class)); + memset(lwp_t_class_ptr, NULL, sizeof(lwp_t_class)); + lwp_t_class.next_class = lwp_class_ptr; + lwp_class_ptr = lwp_t_class_ptr; + struct_empty(lwp_t_class, lwp_t_class_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } // end of while + } // end of if we have lwps + } // end of we want lwps + } else { // End if valid pp + process_number = -1; + index$ = -1; + pid$ = -1; + } + } +}; + +#endif Added: trunk/orca/lib/SE/3.3/orca_process_class.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.3/orca_process_class.se Wed Nov 17 14:52:09 2004 @@ -0,0 +1,909 @@ +// +// Copyright (c) 1995-1998, by Sun Microsystems, Inc. +// All Rights Reserved +// + +#ifndef _PROCESS_CLASS_SE_ +#define _PROCESS_CLASS_SE_ + +// 16 Oct 01 richp - more clean ups, some fields not being computed +// 19 Sep 01 richp - replaced struct_fill and changed long to pointer_t +// process class 19 Feb 98 Adrian - 2.6 extras added +// measured and sampled cpu comparison version 18/5/98 +// vmem_delta added for process_rules 27 Nov 98 +// added processor set info 16 Apr 99 +// merged rules version 22 Apri 99 +// added lwp info 5-27-99 Rick Weisner +// added PCUNSET 11-05-99 Rick Weisner +// added se_trees 08-2000 Rick Weisner +// patched linked list login Jul 2001 Rick Weisner + +// Obtain data averaged over the interval between updates +// return one process at a time, snapshot all good stuff +// in one update then provide index$, pid$ methods to extract groups +// of processes. +// Store data in raw form taken from psinfo and pusage ioctls, and +// process it when called up by class. Feeds data to workload_class.se + + +#if MINOR_VERSION < 60 +# error "process_class only works on 2.6 or newer" +#endif + +#include + +long msaccton[2] = { PCSET, PR_MSACCT | PR_MSFORK }; +long msacctoff[2] = { PCUNSET, PR_MSACCT }; + +// codes for action$ +#define PROC_ACTION_INIT 0 // starting point -> next index +#define PROC_ACTION_PID 1 // get the specified pid + // do not sample all PIDS +#define PROC_ACTION_NEXT_INDEX 2 // index order is based on /proc +#define PROC_ACTION_NEXT_PID 3 // search for pid and return data + // do sample all PIDS +#define PROC_ACTION_NEXT_LWP 4 // search for lwp and return data + +// index$ returns -1 if no more data +// proc data updates if index$ is -1 + +struct pr_header_t { + long number_lwps; + size_t size_of_entries; +}; + +struct lwp_prusage { + prusage_t lwp_pru; + long next_lwp_pru; +}; + +struct raw_proc_info_t { // all the per process info + pointer_t orp; // old prusage_t pointer + pointer_t nrp; // new prusage_t pointer + long nextpid; // next pid in list + long gencnt; // update generation counter + // stuff from prpsinfo_t + long pr_flag; // process flags + long pr_size; // size of process image in pages + long pr_oldsize; // previous size of process image + long pr_rssize; // resident set size in pages + long pr_pri; // priority, high value is high priority + char pr_nice; // nice for cpu usage + char pr_sname; // printable character representing pr_state + timestruc_t o_pr_time; // old sampled user+system CPU time + timestruc_t n_pr_time; // sampled user+system CPU time + timestruc_t o_pr_ctime; // old usr+sys cpu time for reaped children + timestruc_t n_pr_ctime; // new usr+sys cpu time for reaped children + long pr_uid; // real user id + long pr_ppid; // process id of parent + int pr_bindpset; // processor set binding +#define PRCLSZ 8 + char pr_clname[PRCLSZ]; // scheduling class name +#define PRFNSZ 16 + char pr_fname[PRFNSZ]; // last component of execed pathname +#define PRARGSZ 80 + char pr_psargs[PRARGSZ];// initial characters of arg list + int lwp_count; + pointer_t olwp; // pointers to prev. lwp prusage linked list + pointer_t nlwp; // pointers to current lwp prusage linked list +}; + +struct lwp_pr_info { + int lwp_id; // always contains lwp_id + double timestamp; // last time lwp was measured + double creation; // lwp start time + double termination; // lwp termination time stamp + double user_time; // user time in this interval + double system_time; // system call time in this interval + double trap_time; // system trap time in interval + double text_pf_time; // text page fault wait in interval + double data_pf_time; // data page fault wait in interval + double kernel_pf_time; // kernel page fault wait in interval + double user_lock_time; // user lock wait in interval + double sleep_time; // all other sleep time + double cpu_wait_time; // time on runqueue waiting for CPU + double stoptime; // time stopped from ^Z + ulong syscalls; // syscall/interval for this process + ulong maj_faults; // majf/interval + ulong min_faults; // minf/interval + ulong total_swaps; // swapout count + ulong inblocks; // input blocks/interval + ulong outblocks; // output blocks/interval + ulong messages; // msgin+msgout/interval + ulong signals; // signals/interval + ulong vcontexts; // voluntary context switches/interval + ulong icontexts; // in-ditto + ulong charios; // characters in and out/interval + ulong next_class; +}; +// the process class that does all the real work + +// get both types of hires timestamp into a common more useful form +#define timestruc(t) (t.tv_sec + (t.tv_nsec / 1000000000.0)) +#define timeval(t) (t.tv_sec + (t.tv_usec / 1000000.0)) +#define hr_min_sec(t) sprintf("%.3f", timestruc(t)) + +// double timestruc(timestruc_t ts_time) { +// return ts_time.tv_sec + (ts_time.tv_nsec / 1000000000.0); +// } + +// double timeval(timeval_t tv_time) { +// return tv_time.tv_sec + (tv_time.tv_usec / 1000000.0); +// } + +// string hr_min_sec(timestruc_t ts) { +// char buf[80]; +// double tmp; +// tmp = timestruc(ts); +// buf = sprintf("%.3f", tmp); +// return buf; +// } + +msprint(prusage_t pru, int pid, string cmd, string arg) { + puts("\n--------------- BEGIN ----------------"); + printf("%d %s %s\n", pid, cmd, arg); + printf("Elapsed time %12s ", hr_min_sec(pru.pr_rtime)); + printf("Create time %s Timestamp %s\n", hr_min_sec(pru.pr_create), + hr_min_sec(pru.pr_tstamp)); + printf("User CPU time %12s ", hr_min_sec(pru.pr_utime)); + printf("System call time %12s\n", hr_min_sec(pru.pr_stime)); + printf("System trap time %12s ", hr_min_sec(pru.pr_ttime)); + printf("Text pfault sleep %12s\n", hr_min_sec(pru.pr_tftime)); + printf("Data pfault sleep %12s ", hr_min_sec(pru.pr_dftime)); + printf("Kernel pfault sleep %12s\n", hr_min_sec(pru.pr_kftime)); + printf("User lock sleep %12s ", hr_min_sec(pru.pr_ltime)); + printf("Other sleep time %12s\n", hr_min_sec(pru.pr_slptime)); + printf("Wait for CPU time %12s ", hr_min_sec(pru.pr_wtime)); + printf("Stopped time %12s\n", hr_min_sec(pru.pr_stoptime)); + printf("pf %d mf %d sw %d inb %d oub %d ms %d mr %d\n", + pru.pr_minf, pru.pr_majf, pru.pr_nswap, pru.pr_inblk, pru.pr_oublk, + pru.pr_msnd, pru.pr_mrcv); + printf("sig %d vctx %d ictx %d sysc %d ioch %d\n", + pru.pr_sigs, pru.pr_vctx, pru.pr_ictx, pru.pr_sysc, pru.pr_ioch); + puts("---------------- END -----------------"); +} + +class proc_class_t { + // input controls + int index$; // always contains current index or -1 + int pid$; // always contains current pid + // for ACTION_PID mode set pid$ and set index$ to -1 to get new data + int action$; + int off$; + int wantlwp$; // 0 = do not want lwps, 1 = want lsps + // summary totals + double lasttime; // timestamp for the end of the last update + int nproc; // current number of processes + int newproc; + int deadproc; + int missedproc; // number of fork+vfork - newproc + // output data for specified process + long flags; // latest pr_flag for the process + double interval; // measured time interval for averages + double timestamp; // last time process was measured + double creation; // process start time + double termination; // process termination time stamp + double elapsed; // elapsed time for all lwps in process + double total_user; // current totals in seconds + double total_system; + double total_sampled_cpu; + double total_child; + double user_time; // user time in this interval + double system_time; // system call time in this interval + double sampled_cpu; // total sampled cpu time + double trap_time; // system trap time in interval + double child_time; // child CPU in this interval + double text_pf_time; // text page fault wait in interval + double data_pf_time; // data page fault wait in interval + double kernel_pf_time; // kernel page fault wait in interval + double user_lock_time; // user lock wait in interval + double sleep_time; // all other sleep time + double cpu_wait_time; // time on runqueue waiting for CPU + double stoptime; // time stopped from ^Z + ulong syscalls; // syscall/interval for this process + ulong inblocks; // input blocks/interval + ulong outblocks; // output blocks/interval + ulong vmem_size; // size in KB + long vmem_delta; // size change in KB + ulong rmem_size; // RSS in KB +#ifdef XMAP + ulong pmem_size; // private mem in KB + ulong smem_size; // shared mem in KB +#endif + ulong maj_faults; // majf/interval + ulong min_faults; // minf/interval + ulong total_swaps; // swapout count + long priority; // current sched priority + long niceness; // current nice value + char sched_class[PRCLSZ]; // name of class + ulong messages; // msgin+msgout/interval + ulong signals; // signals/interval + ulong vcontexts; // voluntary context switches/interval + ulong icontexts; // in-ditto + ulong charios; // characters in and out/interval + ulong lwp_count; // number of lwps for the process + int uid; // current uid + long ppid; // parent pid + int bindpset; // processor set binding + char fname[PRFNSZ]; // last components of exec'd pathname + char args[PRARGSZ]; // initial part of arg list + ulong lwp_class_ptr; // head of linked list of lwp_class_ptrs + + proc$() { + ulong_t MAX_PID; + ulong_t pp; // pointer to malloc for raw proc info + ulong_t pp_tmp; // temp pointer to malloc for raw proc info + ulong_t pp_ret; // temp pointer to malloc for raw proc info + // chained using nextpid + ulong_t pp_tree; + raw_proc_info_t rpi; + raw_proc_info_t t_rpi; + prusage_t ou; // old and new usage data +#define NU nu[0] + prusage_t nu[1]; // array of one for read and ioctl +#define PS ps[0] + psinfo_t ps[1]; // format changes when read used + pr_header_t prh; + prusage_t plwp; + ulong pnu; + ulong pps; + int i; + dirent_t directory_data; + ulong directory_pointer; + ulong directory_entry; + ulong_t tag; + int process_number; // current link in chain + int first_process; // fixed first link in search chain + int previous_process; // last one used to build chain + int next_process; // next pid + int broken_chain; // flag that chain changed this time + int cleaning_chain; // flag that we are in cleanup mode + int pfd; + int lfd; // file descriptor for /prod/PID/lusage + char procname[64]; + char lwpname[64]; // String for /prod/PID/lusage + long gen; // number of generations of update + int err; + int new_entry; + ulong tmp; + double dtmp; + timeval_t tmp_tval[1]; + int pg_to_kb; + + // lwp working storage + prusage_t lwp_info; + pointer_t lwp_t_ptr; + pointer_t olwp_t_ptr; + lwp_prusage lwp_t_struct; + lwp_prusage olwp_t_struct; + lwp_pr_info lwp_t_class; + long lwp_t_class_ptr; + int ircw; + +// ********************************************************** + + if (action$ == PROC_ACTION_INIT) { + action$ = PROC_ACTION_NEXT_INDEX; + // open the directory containing the process data + directory_pointer = opendir("/proc"); + index$ = -1; + off$ = 0 ; + gen = -1; + wantlwp$ = 0; + first_process=-1; + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + pg_to_kb = sysconf(_SC_PAGESIZE) / 1024; + pp_tree= int2int_init(); + if (pnu == 0 || pps == 0) { + pnu = malloc(sizeof(nu)); + pps = malloc(sizeof(ps)); + } + return; + } + + if (index$ == -1) { // update the data from /proc + // read the first entry in the directory + rewinddir(directory_pointer); + directory_entry = readdir(directory_pointer); // read . + directory_entry = readdir(directory_pointer); // read .. + directory_entry = readdir(directory_pointer); + MAX_PID=0; + nproc = 0; + newproc = 0; + deadproc = 0; + gen++; + previous_process = -1; + broken_chain = 0; + cleaning_chain = 0; + while(directory_entry != NULL) { + directory_data = *((dirent_t *) directory_entry); + // get the process number and open the data file + // only look at specified process + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + directory_entry = NULL; + } else { + process_number = atoi(directory_data.d_name); + } + procname = sprintf("/proc/%d/usage", process_number); + pfd = open(procname, O_RDONLY, 0); + // file cannot be accessed if pfd = -1; ignore this process + // may be that there is no permission or just died + if (pfd != -1) { // start of good pfd + if ( process_number > MAX_PID ) { + MAX_PID = process_number ; + } + tag = process_number; + pp_tmp = NULL ; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret != NULL) { + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + // Process Found + } + if (pp_tmp == NULL) { + // load the tree , new process + pp = malloc(sizeof(rpi)); + memset(pp, 0, sizeof(rpi)); + new_entry = 1; + broken_chain = 1; + pp_ret= int2int_put(pp_tree, tag, pp); + if ( pp_ret < 0 ) { + printf(" Error unable to insert into tree %d, %d , %x\n", + pp_ret, tag, pp); + exit(1); + } + pp_ret = int2int_get(pp_tree, tag); + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp != pp_tmp) { + printf(" Error pointers do not match %x, %x \n", + pp, pp_tmp); + exit(1); + } + } else { + new_entry = 0; + // Process Found + } + + // get the existing or blank data + tag = process_number; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret== NULL) { + printf(" Error pointer not found for process_number %d\n", + tag); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid2 \n", process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); + + // read usage info directly + // 2.6 specific, can read usage and psinfo without needing + // ownership or permissions on /proc entry but can't read + // directly into SE structure so go via malloc buffers + + err = read(pfd, pnu, sizeof(nu)); + close(pfd); + + // turn on msacct + + procname = sprintf("/proc/%d/ctl", process_number); + pfd = open(procname, O_WRONLY, 0); + if (pfd != -1) { + if ( off$ == 0 ) { + write(pfd, &msaccton, sizeof(msaccton)); + } else { + printf("%d ms accounting off \n", process_number ); + write(pfd, &msacctoff, sizeof(msaccton)); + } + close(pfd); + } + + // get usage + procname = sprintf("/proc/%d/psinfo", process_number); + pfd = open(procname, O_RDONLY, 0); + err += read(pfd, pps, sizeof(ps)); + NU = *((prusage_t *) pnu); + PS = *((psinfo_t *) pps); + close(pfd); + if (err == 0) { + // process went away since directory was opened + // unlikely but still need to tidy up mallocs + // when it is a new entry + if ( new_entry == 1 ) { + deadproc++; + free(pp); + tag = process_number; + pp_ret=int2int_put(pp_tree, tag, NULL); + if ( pp_ret < 0 ) { + printf("unable to free tag = %d \n",tag); + exit(1); + } + } + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } else { + directory_entry = readdir(directory_pointer); + } + continue; + } else { // good pfd + +// *************************************************************** + + if ( wantlwp$ == 1 ) { + // read the lwp info + lwpname = sprintf("/proc/%d/lusage", process_number); + lfd = open(lwpname, O_RDONLY, 0); + if ( lfd > 0 ) { + lwp_t_ptr = malloc(sizeof(prh)); + err = read(lfd, lwp_t_ptr, sizeof(prh)); + prh = *((pr_header_t *) lwp_t_ptr); + free(lwp_t_ptr); + if (err <= 0) { + printf("Error reading pr_header %s error code = %d \n", + lwpname, err); + } else { // good read of pr_head + // if there is an old lwp linked list free it + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + rpi.olwp = rpi.nlwp; + rpi.nlwp = NULL; + // create new lwp linked list + for (ircw=0; ircw lasttime) { + newproc++; + if (new_entry == 0) { + // leftover from an old process at same pid + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; // dump old rp, and overwrite new + } +// ***************** delete old lwp info ********************* + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + rpi.olwp = NULL; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } +// ***************** end delete old lwp info ********************* + } + // static psinfo needs updating + rpi.pr_uid = PS.pr_uid; + rpi.pr_ppid = PS.pr_ppid; + rpi.pr_bindpset = PS.pr_lwp.pr_bindpset; + rpi.pr_clname = PS.pr_lwp.pr_clname; + rpi.pr_fname = PS.pr_fname; + rpi.pr_psargs = PS.pr_psargs; + } + // update usage data + tmp = rpi.orp; // hang on to malloced data + rpi.orp = rpi.nrp; // switch new to old + if (tmp == NULL) { + rpi.nrp = malloc(sizeof(ou)); + } else { + rpi.nrp = tmp; + } + struct_empty(NU, rpi.nrp); // save whole block + // update dynamic psinfo data + rpi.pr_oldsize = rpi.pr_size; + rpi.pr_size = PS.pr_size; + rpi.pr_rssize = PS.pr_rssize; + rpi.pr_pri = PS.pr_lwp.pr_pri; + rpi.pr_nice = PS.pr_lwp.pr_nice; + rpi.pr_sname = PS.pr_lwp.pr_sname; + rpi.pr_flag = PS.pr_flag; + rpi.o_pr_time = rpi.n_pr_time; + rpi.n_pr_time = PS.pr_time; + rpi.o_pr_ctime = rpi.n_pr_ctime; + rpi.n_pr_ctime = PS.pr_ctime; + rpi.gencnt = gen; + struct_empty(rpi, pp); + nproc++; + // printf("processed %d \n" , process_number ); + } // end of good pfd + // step through the files in the directory ... + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } else { + directory_entry = readdir(directory_pointer); + } + } // end of directory +// ************************************************************** + // go through list and remove deadwood + // printf("first process_number %d \n",first_process); + process_number = first_process; + next_process = -1; + previous_process = -1; + while ( process_number > 0 ) { + // printf("processing %d \n",process_number); + if (process_number > 0 ) { + pp_ret = int2int_get(pp_tree, process_number); + if ( pp_ret == NULL) { + printf("unable to get process_number %d \n", process_number); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid4 \n",process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + next_process = rpi.nextpid; + // printf("next process %d \n",next_process); + // unhook dead processes + if (rpi.gencnt != gen) { + deadproc++; + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; + } + if (rpi.nrp != NULL) { + free(rpi.nrp); + rpi.nrp = NULL; + } + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + lwp_t_ptr = t_rpi.nlwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } + free(pp); + pp_ret = int2int_put(pp_tree, process_number , NULL); + if ( pp_ret < 0 ) { + printf("unable to free process_number \n"); + exit(1); + } + if ( previous_process > 0 ) { // there was a previous process + pp_tmp = int2int_get(pp_tree, previous_process); + if ( pp_tmp == NULL) { + printf("unable to get process_number %d \n", + previous_process); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_tmp)); + if ( pp == NULL) { + printf("process_number %d invalid5 \n", + previous_process); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + // printf("previous process %d \n",previous_process); + rpi.nextpid = next_process; + struct_empty(rpi, pp); + } else { + first_process = next_process; + } + } else { + // update previous process ptr + previous_process = process_number; + } + } + process_number = next_process; + } + // printf(" end of deadwood removal \n"); + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + process_number = first_process; + index$ = -1; + } + // printf("done updating \n"); + // printf("MAX_PID = %d \n", MAX_PID); +// ****************************** end of update section ******************* + + if (action$ == PROC_ACTION_NEXT_INDEX ) { + // printf("PROC_ACTION_NEXT_INDEX \n"); + if (index$ == -1) { + process_number = first_process; + } else { + process_number = rpi.nextpid; + } + if (process_number < 0 || process_number > MAX_PID) { + // ran out of data + process_number = -1; + index$ = -1; + pid$ = -1; + // printf(" thats all there is \n"); + return; + } + index$++; + } + + if (action$ == PROC_ACTION_NEXT_PID) { + // printf("PROC_ACTION_NEXT_PID \n"); + if (index$ == -1) { + process_number = 0; + } else { + process_number++; + } + index$++; + // look for the next data + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + while (process_number < MAX_PID && pp == NULL) { + process_number++; + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + } + if (process_number < 0 || process_number > MAX_PID) { + // ran out of data + process_number = -1; + index$ = -1; + pid$ = -1; + // printf(" ran out of data NEXT PID \n"); + return; + } + } + + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + index$ = 0; + } + + // common code to update class once process has been chosen + + pp_ret=int2int_get(pp_tree,process_number); + pp = NULL; + if (pp_ret != NULL) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + if ( pp != NULL) { + rpi = *((raw_proc_info_t *) pp); + // make sure that all class data is updated + // index$ is already set + pid$ = process_number; + uid = rpi.pr_uid; + // nproc, , are already set + missedproc = rpi.nextpid; // for debug until fork counting + + // nrp will always be set + NU = *((prusage_t *) rpi.nrp); + creation = timestruc(NU.pr_create); + timestamp = timestruc(NU.pr_tstamp); + termination = 0.0; // set later if process is dead + elapsed = timestruc(NU.pr_rtime); + total_user = timestruc(NU.pr_utime); + total_system = timestruc(NU.pr_stime); + total_child = timestruc(rpi.n_pr_ctime); + total_sampled_cpu = timestruc(rpi.n_pr_time); + flags = rpi.pr_flag; +#ifdef PDEBUG + msprint(NU, pid$, rpi.pr_fname, rpi.pr_psargs); +#endif + if (rpi.orp != NULL) { + ou = *((prusage_t *) rpi.orp); + interval = timestamp - timestruc(ou.pr_tstamp); + // interval should never be zero + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(ou, pid$, fname, args); + interval = 1.0; + } + user_time = total_user - timestruc(ou.pr_utime); + system_time = total_system - timestruc(ou.pr_stime); + sampled_cpu = total_sampled_cpu - timestruc(rpi.o_pr_time); + trap_time = timestruc(NU.pr_ttime) - timestruc(ou.pr_ttime); + child_time = total_child - timestruc(rpi.o_pr_ctime); + text_pf_time = timestruc(NU.pr_tftime) - timestruc(ou.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime) - timestruc(ou.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime) - timestruc(ou.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime) - timestruc(ou.pr_ltime); + sleep_time = timestruc(NU.pr_slptime) - timestruc(ou.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime) - timestruc(ou.pr_wtime); + stoptime = timestruc(NU.pr_stoptime) - timestruc(ou.pr_stoptime); + syscalls = NU.pr_sysc - ou.pr_sysc; + inblocks = NU.pr_inblk - ou.pr_inblk; + outblocks = NU.pr_oublk - ou.pr_oublk; + maj_faults = NU.pr_majf - ou.pr_majf; + min_faults = NU.pr_minf - ou.pr_minf; + messages = (NU.pr_msnd + NU.pr_mrcv) - (ou.pr_msnd + ou.pr_mrcv); + signals = NU.pr_sigs - ou.pr_sigs; + vcontexts = NU.pr_vctx - ou.pr_vctx; + icontexts = NU.pr_ictx - ou.pr_ictx; + charios = NU.pr_ioch - ou.pr_ioch; + } else { + // new process will only have rpi.nrp set + interval = timestamp - creation; // elapsed time so far + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(NU, pid$, fname, args); + interval = 1.0; + } + user_time = total_user; + system_time = total_system; + sampled_cpu = total_sampled_cpu; + trap_time = timestruc(NU.pr_ttime); + child_time = total_child; + text_pf_time = timestruc(NU.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime); + sleep_time = timestruc(NU.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime); + stoptime = timestruc(NU.pr_stoptime); + syscalls = NU.pr_sysc; + inblocks = NU.pr_inblk; + outblocks = NU.pr_oublk; + maj_faults = NU.pr_majf; + min_faults = NU.pr_minf; + messages = NU.pr_msnd + NU.pr_mrcv; + signals = NU.pr_sigs; + vcontexts = NU.pr_vctx; + icontexts = NU.pr_ictx; + charios = NU.pr_ioch; + } + vmem_size = rpi.pr_size; + vmem_delta = rpi.pr_size - rpi.pr_oldsize; + rmem_size = rpi.pr_rssize; + total_swaps = NU.pr_nswap; + priority = rpi.pr_pri; + niceness = rpi.pr_nice; + sched_class = rpi.pr_clname; + lwp_count = NU.pr_count; + ppid = rpi.pr_ppid; + bindpset = rpi.pr_bindpset; + fname = rpi.pr_fname; + if (fname == "" && rpi.pr_sname == 'Z') { + fname = "Zombie"; + bindpset = -1; // no pset, but Zomb defaults to 0 + } + args = rpi.pr_psargs; + // bug in sched pid 0 gives 100% system time + if (pid$ == 0) { + total_system = 0.0; + system_time = 0.0; + } +#ifdef PDEBUG + printf("interval %.5f\n", interval); +#endif +// ******************************************************* + if ( wantlwp$ == 1 ) { + // process lwp info + lwp_t_ptr = lwp_class_ptr; + lwp_class_ptr = NULL; + // if there is an old lwp class linked list free it + while ( lwp_t_ptr != NULL ) { + lwp_t_class = *((lwp_pr_info *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_class.next_class ; + } + // Process lwp information + if ( rpi.nlwp != NULL ) { + lwp_t_ptr = rpi.nlwp ; + while ( lwp_t_ptr != NULL) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + lwp_t_class.lwp_id = lwp_t_struct.lwp_pru.pr_lwpid; + lwp_t_class.timestamp = timestruc(lwp_t_struct.lwp_pru.pr_tstamp); + lwp_t_class.creation = timestruc(lwp_t_struct.lwp_pru.pr_create); + lwp_t_class.termination = timestruc(lwp_t_struct.lwp_pru.pr_term); + lwp_t_class.user_time = timestruc(lwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = timestruc(lwp_t_struct.lwp_pru.pr_stime) + timestruc(lwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = timestruc(lwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = timestruc(lwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = timestruc(lwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = timestruc(lwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_struct.lwp_pru.pr_ioch; + + olwp_t_ptr = rpi.olwp; + while ( olwp_t_ptr != NULL ) { + olwp_t_struct = *((lwp_prusage *) olwp_t_ptr); + if ( olwp_t_struct.lwp_pru.pr_lwpid == + lwp_t_struct.lwp_pru.pr_lwpid) { + break; + } + olwp_t_ptr = olwp_t_struct.next_lwp_pru ; + } + if ( olwp_t_ptr != NULL) { + lwp_t_class.user_time = lwp_t_class.user_time - timestruc(olwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = lwp_t_class.system_time - timestruc(olwp_t_struct.lwp_pru.pr_stime) - timestruc(olwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = lwp_t_class.text_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = lwp_t_class.data_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = lwp_t_class.kernel_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = lwp_t_class.user_lock_time - timestruc(olwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = lwp_t_class.sleep_time - timestruc(olwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = lwp_t_class.cpu_wait_time - timestruc(olwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = lwp_t_class.stoptime - timestruc(olwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_class.min_faults - olwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_class.maj_faults - olwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_class.total_swaps - olwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_class.inblocks - olwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_class.outblocks - olwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_class.messages - olwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_class.signals - olwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_class.vcontexts - olwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_class.icontexts - olwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_class.syscalls - olwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_class.charios - olwp_t_struct.lwp_pru.pr_ioch; + + } // end of if old pointer + lwp_t_class_ptr = malloc(sizeof(lwp_t_class)); + memset(lwp_t_class_ptr, NULL, sizeof(lwp_t_class)); + lwp_t_class.next_class = lwp_class_ptr; + lwp_class_ptr = lwp_t_class_ptr; + struct_empty(lwp_t_class, lwp_t_class_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } // end of while + } // end of if we have lwps + } // end of we want lwps + } else { // End if valid pp + process_number = -1; + index$ = -1; + pid$ = -1; + } + } +}; + +#endif From dmberezin at hotmail.com Wed Nov 17 15:34:09 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Wed, 17 Nov 2004 15:34:09 -0800 Subject: [Orca-checkins] r404 - in trunk/orca: data_gatherers/orcallator lib/SE/3.2.1 lib/SE/3.3 lib/SE/3.3.1 Message-ID: <200411172334.iAHNY90r002053@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Wed Nov 17 15:32:25 2004 New Revision: 404 Modified: trunk/orca/data_gatherers/orcallator/orcallator.se trunk/orca/lib/SE/3.2.1/orca_process_class.se trunk/orca/lib/SE/3.2.1/workinfo_class.se trunk/orca/lib/SE/3.3.1/orca_process_class.se trunk/orca/lib/SE/3.3.1/workinfo_class.se trunk/orca/lib/SE/3.3/orca_process_class.se trunk/orca/lib/SE/3.3/workinfo_class.se Log: Fix a thread counting bug in orca_process_class.se * lib/SE/3.2.1/orca_process_class.se * lib/SE/3.3.1/orca_process_class.se * lib/SE/3.3/orca_process_class.se Fix a bug where highest thread id was reported as current number of threads. Support both current thread count and contributing thread count. Add lwp_max variable. The original version of orca_process_class.se is from SEToolkit 3.3.1. * lib/SE/3.2.1/workinfo_class.se * lib/SE/3.3.1/workinfo_class.se * lib/SE/3.3/workinfo_class.se Add support for maximum thread id, introduced in orca_process_class.se Include orca_process_class.se instead of process_class.se * data_gatherers/orcallator/orcallator.se (measure_workload): Add support for maximum thread id, introduced in orca_process_class.se Modified: trunk/orca/data_gatherers/orcallator/orcallator.se ============================================================================== --- trunk/orca/data_gatherers/orcallator/orcallator.se (original) +++ trunk/orca/data_gatherers/orcallator/orcallator.se Wed Nov 17 15:32:25 2004 @@ -2429,6 +2429,7 @@ for (refresh$(ww); ww.number != -1; refresh$(ww)) { put_output(sprintf("%s_cnt", ww.w.name), sprintf("%4d", ww.w.count)); put_output(sprintf("%s_lwpcnt", ww.w.name), sprintf("%4d", ww.w.info.lwp_count)); + put_output(sprintf("%s_lwpmax", ww.w.name), sprintf("%4d", ww.w.info.lwp_max)); if (ww.w.cnt == 0) { millisecs_per_switch = ww.w.info.vcontexts + ww.w.info.icontexts; Modified: trunk/orca/lib/SE/3.2.1/orca_process_class.se ============================================================================== --- trunk/orca/lib/SE/3.2.1/orca_process_class.se (original) +++ trunk/orca/lib/SE/3.2.1/orca_process_class.se Wed Nov 17 15:32:25 2004 @@ -222,6 +222,7 @@ ulong icontexts; // in-ditto ulong charios; // characters in and out/interval ulong lwp_count; // number of lwps for the process + ulong lwp_max; // number of contributing lwps for the process int uid; // current uid long ppid; // parent pid int bindpset; // processor set binding @@ -543,6 +544,7 @@ rpi.n_pr_time = PS.pr_time; rpi.o_pr_ctime = rpi.n_pr_ctime; rpi.n_pr_ctime = PS.pr_ctime; + rpi.lwp_count = PS.pr_nlwp; rpi.gencnt = gen; struct_empty(rpi, pp); nproc++; @@ -799,7 +801,8 @@ priority = rpi.pr_pri; niceness = rpi.pr_nice; sched_class = rpi.pr_clname; - lwp_count = NU.pr_count; + lwp_max = NU.pr_count; + lwp_count = rpi.lwp_count; ppid = rpi.pr_ppid; bindpset = rpi.pr_bindpset; fname = rpi.pr_fname; Modified: trunk/orca/lib/SE/3.2.1/workinfo_class.se ============================================================================== --- trunk/orca/lib/SE/3.2.1/workinfo_class.se (original) +++ trunk/orca/lib/SE/3.2.1/workinfo_class.se Wed Nov 17 15:32:25 2004 @@ -90,7 +90,7 @@ #include #include #include -#include +#include #include struct work_info_t { @@ -324,6 +324,7 @@ wi[i].info.priority += pp.priority; wi[i].info.niceness += pp.niceness; } + wi[i].info.lwp_max += pp.lwp_max; wi[i].info.lwp_count += pp.lwp_count; wi[i].count++; if (firstmatch == 1 && i > 0) { // First match only counts Modified: trunk/orca/lib/SE/3.3.1/orca_process_class.se ============================================================================== --- trunk/orca/lib/SE/3.3.1/orca_process_class.se (original) +++ trunk/orca/lib/SE/3.3.1/orca_process_class.se Wed Nov 17 15:32:25 2004 @@ -222,6 +222,7 @@ ulong icontexts; // in-ditto ulong charios; // characters in and out/interval ulong lwp_count; // number of lwps for the process + ulong lwp_max; // number of contributing lwps for the process int uid; // current uid long ppid; // parent pid int bindpset; // processor set binding @@ -543,6 +544,7 @@ rpi.n_pr_time = PS.pr_time; rpi.o_pr_ctime = rpi.n_pr_ctime; rpi.n_pr_ctime = PS.pr_ctime; + rpi.lwp_count = PS.pr_nlwp; rpi.gencnt = gen; struct_empty(rpi, pp); nproc++; @@ -799,7 +801,8 @@ priority = rpi.pr_pri; niceness = rpi.pr_nice; sched_class = rpi.pr_clname; - lwp_count = NU.pr_count; + lwp_max = NU.pr_count; + lwp_count = rpi.lwp_count; ppid = rpi.pr_ppid; bindpset = rpi.pr_bindpset; fname = rpi.pr_fname; Modified: trunk/orca/lib/SE/3.3.1/workinfo_class.se ============================================================================== --- trunk/orca/lib/SE/3.3.1/workinfo_class.se (original) +++ trunk/orca/lib/SE/3.3.1/workinfo_class.se Wed Nov 17 15:32:25 2004 @@ -90,7 +90,7 @@ #include #include #include -#include +#include #include struct work_info_t { @@ -324,6 +324,7 @@ wi[i].info.priority += pp.priority; wi[i].info.niceness += pp.niceness; } + wi[i].info.lwp_max += pp.lwp_max; wi[i].info.lwp_count += pp.lwp_count; wi[i].count++; if (firstmatch == 1 && i > 0) { // First match only counts Modified: trunk/orca/lib/SE/3.3/orca_process_class.se ============================================================================== --- trunk/orca/lib/SE/3.3/orca_process_class.se (original) +++ trunk/orca/lib/SE/3.3/orca_process_class.se Wed Nov 17 15:32:25 2004 @@ -222,6 +222,7 @@ ulong icontexts; // in-ditto ulong charios; // characters in and out/interval ulong lwp_count; // number of lwps for the process + ulong lwp_max; // number of contributing lwps for the process int uid; // current uid long ppid; // parent pid int bindpset; // processor set binding @@ -543,6 +544,7 @@ rpi.n_pr_time = PS.pr_time; rpi.o_pr_ctime = rpi.n_pr_ctime; rpi.n_pr_ctime = PS.pr_ctime; + rpi.lwp_count = PS.pr_nlwp; rpi.gencnt = gen; struct_empty(rpi, pp); nproc++; @@ -799,7 +801,8 @@ priority = rpi.pr_pri; niceness = rpi.pr_nice; sched_class = rpi.pr_clname; - lwp_count = NU.pr_count; + lwp_max = NU.pr_count; + lwp_count = rpi.lwp_count; ppid = rpi.pr_ppid; bindpset = rpi.pr_bindpset; fname = rpi.pr_fname; Modified: trunk/orca/lib/SE/3.3/workinfo_class.se ============================================================================== --- trunk/orca/lib/SE/3.3/workinfo_class.se (original) +++ trunk/orca/lib/SE/3.3/workinfo_class.se Wed Nov 17 15:32:25 2004 @@ -90,7 +90,7 @@ #include #include #include -#include +#include #include struct work_info_t { @@ -324,6 +324,7 @@ wi[i].info.priority += pp.priority; wi[i].info.niceness += pp.niceness; } + wi[i].info.lwp_max += pp.lwp_max; wi[i].info.lwp_count += pp.lwp_count; wi[i].count++; if (firstmatch == 1 && i > 0) { // First match only counts From dmberezin at hotmail.com Fri Nov 19 07:06:59 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Fri, 19 Nov 2004 07:06:59 -0800 Subject: [Orca-checkins] r405 - trunk/orca/lib/SE/3.2.1 Message-ID: <200411191506.iAJF6xYL028108@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Fri Nov 19 07:04:32 2004 New Revision: 405 Modified: trunk/orca/lib/SE/3.2.1/orca_process_class.se Log: Replace orca_process_class.se with the correct version from SE Toolkit * lib/SE/3.2.1/orca_process_class.se Replace with a copy of process_class.se from SE Toolkit version 3.2.1 Modified: trunk/orca/lib/SE/3.2.1/orca_process_class.se ============================================================================== --- trunk/orca/lib/SE/3.2.1/orca_process_class.se (original) +++ trunk/orca/lib/SE/3.2.1/orca_process_class.se Fri Nov 19 07:04:32 2004 @@ -1,912 +1,899 @@ -// -// Copyright (c) 1995-1998, by Sun Microsystems, Inc. -// All Rights Reserved -// -#ifndef _PROCESS_CLASS_SE_ -#define _PROCESS_CLASS_SE_ - -// 16 Oct 01 richp - more clean ups, some fields not being computed // 19 Sep 01 richp - replaced struct_fill and changed long to pointer_t -// process class 19 Feb 98 Adrian - 2.6 extras added -// measured and sampled cpu comparison version 18/5/98 -// vmem_delta added for process_rules 27 Nov 98 -// added processor set info 16 Apr 99 -// merged rules version 22 Apri 99 -// added lwp info 5-27-99 Rick Weisner -// added PCUNSET 11-05-99 Rick Weisner -// added se_trees 08-2000 Rick Weisner -// patched linked list login Jul 2001 Rick Weisner - -// Obtain data averaged over the interval between updates -// return one process at a time, snapshot all good stuff -// in one update then provide index$, pid$ methods to extract groups -// of processes. -// Store data in raw form taken from psinfo and pusage ioctls, and -// process it when called up by class. Feeds data to workload_class.se - - -#if MINOR_VERSION < 60 -# error "process_class only works on 2.6 or newer" -#endif +/* process class 19 Feb 98 Adrian - 2.6 extras added */ +/* measured and sampled cpu comparison version 18/5/98 */ +/* vmem_delta added for process_rules 27 Nov 98 */ +/* added processor set info 16 Apr 99 */ +/* merged rules version 22 Apri 99 */ +/* added lwp info 5-27-99 Rick Weisner */ +/* added PCUNSET 11-05-99 Rick Weisner */ +/* added se_trees 08-2000 Rick Weisner */ +/* patched linked list login Jul 2001 Rick Weisner */ + +/* +Obtain data averaged over the interval between updates +return one process at a time, snapshot all good stuff +in one update then provide index$, pid$ methods to extract groups of processes. +Store data in raw form taken from psinfo and pusage ioctls, and +process it when called up by class. Feeds data to workload_class.se +*/ #include +#if MINOR_VERSION >= 60 +#define PCSET 16 /* set modes from long argument */ +#define PCUNSET 17 -long msaccton[2] = { PCSET, PR_MSACCT | PR_MSFORK }; +long msaccton[2] = { PCSET, PR_MSACCT | PR_MSFORK }; long msacctoff[2] = { PCUNSET, PR_MSACCT }; +#else +printf(" OS Version < 2.6 not supported \n "); +exit(1); +#endif -// codes for action$ -#define PROC_ACTION_INIT 0 // starting point -> next index -#define PROC_ACTION_PID 1 // get the specified pid - // do not sample all PIDS -#define PROC_ACTION_NEXT_INDEX 2 // index order is based on /proc -#define PROC_ACTION_NEXT_PID 3 // search for pid and return data - // do sample all PIDS -#define PROC_ACTION_NEXT_LWP 4 // search for lwp and return data - -// index$ returns -1 if no more data -// proc data updates if index$ is -1 - -struct pr_header_t { - long number_lwps; - size_t size_of_entries; +/* codes for action$ */ +#define PROC_ACTION_INIT 0 /* starting point -> next index */ +#define PROC_ACTION_PID 1 /* get the specified pid */ + /* do not sample all PIDS */ +#define PROC_ACTION_NEXT_INDEX 2 /* index order is based on /proc */ +#define PROC_ACTION_NEXT_PID 3 /* search for pid and return data */ + /* do sample all PIDS */ +#define PROC_ACTION_NEXT_LWP 4 /* search for lwp and return data */ +/* index$ returns -1 if no more data */ +/* proc data updates if index$ is -1 */ + +struct pr_header_t { + long number_lwps; + size_t size_of_entries; }; struct lwp_prusage { - prusage_t lwp_pru; - long next_lwp_pru; + prusage_t lwp_pru; + long next_lwp_pru; }; -struct raw_proc_info_t { // all the per process info - pointer_t orp; // old prusage_t pointer - pointer_t nrp; // new prusage_t pointer - long nextpid; // next pid in list - long gencnt; // update generation counter - // stuff from prpsinfo_t - long pr_flag; // process flags - long pr_size; // size of process image in pages - long pr_oldsize; // previous size of process image - long pr_rssize; // resident set size in pages - long pr_pri; // priority, high value is high priority - char pr_nice; // nice for cpu usage - char pr_sname; // printable character representing pr_state - timestruc_t o_pr_time; // old sampled user+system CPU time - timestruc_t n_pr_time; // sampled user+system CPU time - timestruc_t o_pr_ctime; // old usr+sys cpu time for reaped children - timestruc_t n_pr_ctime; // new usr+sys cpu time for reaped children - long pr_uid; // real user id - long pr_ppid; // process id of parent - int pr_bindpset; // processor set binding +struct raw_proc_info_t { // all the per process info + pointer_t orp; // old prusage_t pointer + pointer_t nrp; // new prusage_t pointer + long nextpid; // next pid in list + long gencnt; // update generation counter + // stuff from prpsinfo_t + long pr_flag; // process flags + long pr_size; // size of process image in pages + long pr_oldsize; // previous size of process image + long pr_rssize; // resident set size in pages + long pr_pri; // priority, high value is high priority + char pr_nice; //* nice for cpu usage + char pr_sname; // printable character representing pr_state + timestruc_t o_pr_time; // old sampled user+system CPU time + timestruc_t n_pr_time; // sampled user+system CPU time + timestruc_t o_pr_ctime; // old usr+sys cpu time for reaped children + timestruc_t n_pr_ctime; // new usr+sys cpu time for reaped children + long pr_uid; // real user id + long pr_ppid; // process id of parent + int pr_bindpset;// processor set binding #define PRCLSZ 8 - char pr_clname[PRCLSZ]; // scheduling class name + char pr_clname[PRCLSZ]; // scheduling class name #define PRFNSZ 16 - char pr_fname[PRFNSZ]; // last component of execed pathname + char pr_fname[PRFNSZ]; // last component of execed pathname #define PRARGSZ 80 - char pr_psargs[PRARGSZ];// initial characters of arg list - int lwp_count; - pointer_t olwp; // pointers to prev. lwp prusage linked list - pointer_t nlwp; // pointers to current lwp prusage linked list + char pr_psargs[PRARGSZ];// initial characters of arg list + int lwp_count; + pointer_t olwp; // pointers to prev. lwp prusage linked list + pointer_t nlwp; // pointers to current lwp prusage linked list }; struct lwp_pr_info { - int lwp_id; // always contains lwp_id - double timestamp; // last time lwp was measured - double creation; // lwp start time - double termination; // lwp termination time stamp - double user_time; // user time in this interval - double system_time; // system call time in this interval - double trap_time; // system trap time in interval - double text_pf_time; // text page fault wait in interval - double data_pf_time; // data page fault wait in interval - double kernel_pf_time; // kernel page fault wait in interval - double user_lock_time; // user lock wait in interval - double sleep_time; // all other sleep time - double cpu_wait_time; // time on runqueue waiting for CPU - double stoptime; // time stopped from ^Z - ulong syscalls; // syscall/interval for this process - ulong maj_faults; // majf/interval - ulong min_faults; // minf/interval - ulong total_swaps; // swapout count - ulong inblocks; // input blocks/interval - ulong outblocks; // output blocks/interval - ulong messages; // msgin+msgout/interval - ulong signals; // signals/interval - ulong vcontexts; // voluntary context switches/interval - ulong icontexts; // in-ditto - ulong charios; // characters in and out/interval - ulong next_class; + int lwp_id; /* always contains lwp_id */ + double timestamp; /* last time lwp was measured */ + double creation; /* lwp start time */ + double termination; /* lwp termination time stamp */ + double user_time; /* user time in this interval */ + double system_time; /* system call time in this interval */ + double trap_time; /* system trap time in interval */ + double text_pf_time; /* text page fault wait in interval */ + double data_pf_time; /* data page fault wait in interval */ + double kernel_pf_time; /* kernel page fault wait in interval */ + double user_lock_time; /* user lock wait in interval */ + double sleep_time; /* all other sleep time */ + double cpu_wait_time; /* time on runqueue waiting for CPU */ + double stoptime; /* time stopped from ^Z */ + ulong syscalls; /* syscall/interval for this process */ + ulong maj_faults; /* majf/interval */ + ulong min_faults; /* minf/interval */ + ulong total_swaps; /* swapout count */ + ulong inblocks; /* input blocks/interval */ + ulong outblocks; /* output blocks/interval */ + ulong messages; /* msgin+msgout/interval */ + ulong signals; /* signals/interval */ + ulong vcontexts; /* voluntary context switches/interval */ + ulong icontexts; /* in-ditto */ + ulong charios; /* characters in and out/interval */ + ulong next_class; }; -// the process class that does all the real work +/* the process class that does all the real work */ + +/* get both types of hires timestamp into a common more useful form */ +double timestruc(timestruc_t ts_time) +{ + return ts_time.tv_sec + (ts_time.tv_nsec / 1000000000.0); +} + +double timeval(timeval_t tv_time) +{ + return tv_time.tv_sec + (tv_time.tv_usec / 1000000.0); +} -// get both types of hires timestamp into a common more useful form -#define timestruc(t) (t.tv_sec + (t.tv_nsec / 1000000000.0)) -#define timeval(t) (t.tv_sec + (t.tv_usec / 1000000.0)) -#define hr_min_sec(t) sprintf("%.3f", timestruc(t)) - -// double timestruc(timestruc_t ts_time) { -// return ts_time.tv_sec + (ts_time.tv_nsec / 1000000000.0); -// } - -// double timeval(timeval_t tv_time) { -// return tv_time.tv_sec + (tv_time.tv_usec / 1000000.0); -// } - -// string hr_min_sec(timestruc_t ts) { -// char buf[80]; -// double tmp; -// tmp = timestruc(ts); -// buf = sprintf("%.3f", tmp); -// return buf; -// } +string hr_min_sec(timestruc_t ts) { + char buf[80]; + double tmp; + tmp = timestruc(ts); + buf = sprintf("%.3f", tmp); + return buf; +} msprint(prusage_t pru, int pid, string cmd, string arg) { - puts("\n--------------- BEGIN ----------------"); - printf("%d %s %s\n", pid, cmd, arg); + printf("\n%d %s %s\n", pid, cmd, arg); printf("Elapsed time %12s ", hr_min_sec(pru.pr_rtime)); printf("Create time %s Timestamp %s\n", hr_min_sec(pru.pr_create), - hr_min_sec(pru.pr_tstamp)); - printf("User CPU time %12s ", hr_min_sec(pru.pr_utime)); - printf("System call time %12s\n", hr_min_sec(pru.pr_stime)); - printf("System trap time %12s ", hr_min_sec(pru.pr_ttime)); - printf("Text pfault sleep %12s\n", hr_min_sec(pru.pr_tftime)); - printf("Data pfault sleep %12s ", hr_min_sec(pru.pr_dftime)); - printf("Kernel pfault sleep %12s\n", hr_min_sec(pru.pr_kftime)); - printf("User lock sleep %12s ", hr_min_sec(pru.pr_ltime)); - printf("Other sleep time %12s\n", hr_min_sec(pru.pr_slptime)); - printf("Wait for CPU time %12s ", hr_min_sec(pru.pr_wtime)); - printf("Stopped time %12s\n", hr_min_sec(pru.pr_stoptime)); - printf("pf %d mf %d sw %d inb %d oub %d ms %d mr %d\n", - pru.pr_minf, pru.pr_majf, pru.pr_nswap, pru.pr_inblk, pru.pr_oublk, - pru.pr_msnd, pru.pr_mrcv); - printf("sig %d vctx %d ictx %d sysc %d ioch %d\n", - pru.pr_sigs, pru.pr_vctx, pru.pr_ictx, pru.pr_sysc, pru.pr_ioch); - puts("---------------- END -----------------"); + hr_min_sec(pru.pr_tstamp)); + printf("User CPU time %12s ", hr_min_sec(pru.pr_utime)); + printf("System call time %12s\n", hr_min_sec(pru.pr_stime)); + printf("System trap time %12s ", hr_min_sec(pru.pr_ttime)); + printf("Text pfault sleep %12s\n", hr_min_sec(pru.pr_tftime)); + printf("Data pfault sleep %12s ", hr_min_sec(pru.pr_dftime)); + printf("Kernel pfault sleep %12s\n", hr_min_sec(pru.pr_kftime)); + printf("User lock sleep %12s ", hr_min_sec(pru.pr_ltime)); + printf("Other sleep time %12s\n", hr_min_sec(pru.pr_slptime)); + printf("Wait for CPU time %12s ", hr_min_sec(pru.pr_wtime)); + printf("Stopped time %12s\n", hr_min_sec(pru.pr_stoptime)); + printf("pf %d mf %d sw %d inb %d oub %d ms %d mr %d\n", pru.pr_minf, pru.pr_majf, pru.pr_nswap, pru.pr_inblk, pru.pr_oublk, + pru.pr_msnd, pru.pr_mrcv); + printf("sig %d vctx %d ictx %d sysc %d ioch %d\n", pru.pr_sigs, pru.pr_vctx, + pru.pr_ictx, pru.pr_sysc, pru.pr_ioch); } class proc_class_t { - // input controls - int index$; // always contains current index or -1 - int pid$; // always contains current pid - // for ACTION_PID mode set pid$ and set index$ to -1 to get new data - int action$; - int off$; - int wantlwp$; // 0 = do not want lwps, 1 = want lsps - // summary totals - double lasttime; // timestamp for the end of the last update - int nproc; // current number of processes - int newproc; - int deadproc; - int missedproc; // number of fork+vfork - newproc - // output data for specified process - long flags; // latest pr_flag for the process - double interval; // measured time interval for averages - double timestamp; // last time process was measured - double creation; // process start time - double termination; // process termination time stamp - double elapsed; // elapsed time for all lwps in process - double total_user; // current totals in seconds - double total_system; - double total_sampled_cpu; - double total_child; - double user_time; // user time in this interval - double system_time; // system call time in this interval - double sampled_cpu; // total sampled cpu time - double trap_time; // system trap time in interval - double child_time; // child CPU in this interval - double text_pf_time; // text page fault wait in interval - double data_pf_time; // data page fault wait in interval - double kernel_pf_time; // kernel page fault wait in interval - double user_lock_time; // user lock wait in interval - double sleep_time; // all other sleep time - double cpu_wait_time; // time on runqueue waiting for CPU - double stoptime; // time stopped from ^Z - ulong syscalls; // syscall/interval for this process - ulong inblocks; // input blocks/interval - ulong outblocks; // output blocks/interval - ulong vmem_size; // size in KB - long vmem_delta; // size change in KB - ulong rmem_size; // RSS in KB + /* input controls */ + int index$; /* always contains current index or -1 */ + int pid$; /* always contains current pid */ + /* for ACTION_PID mode set pid$ and set index$ to -1 to get new data */ + int action$; + int off$; + int wantlwp$; /* 0 = do not want lwps, 1 = want lsps */ + /* summary totals */ + double lasttime; /* timestamp for the end of the last update */ + int nproc; /* current number of processes */ + int newproc ; + int deadproc ; + int missedproc; /* number of fork+vfork - newproc */ + /* output data for specified process */ + long flags; /* latest pr_flag for the process */ + double interval; /* measured time interval for averages */ + double timestamp; /* last time process was measured */ + double creation; /* process start time */ + double termination; /* process termination time stamp */ + double elapsed; /* elapsed time for all lwps in process */ + double total_user; /* current totals in seconds */ + double total_system; + double total_sampled_cpu; + double total_child; + double user_time; /* user time in this interval */ + double system_time; /* system call time in this interval */ + double sampled_cpu; /* total sampled cpu time */ + double trap_time; /* system trap time in interval */ + double child_time; /* child CPU in this interval */ + double text_pf_time; /* text page fault wait in interval */ + double data_pf_time; /* data page fault wait in interval */ + double kernel_pf_time; /* kernel page fault wait in interval */ + double user_lock_time; /* user lock wait in interval */ + double sleep_time; /* all other sleep time */ + double cpu_wait_time; /* time on runqueue waiting for CPU */ + double stoptime; /* time stopped from ^Z */ + ulong syscalls; /* syscall/interval for this process */ + ulong inblocks; /* input blocks/interval */ + ulong outblocks; /* output blocks/interval */ + ulong vmem_size; /* size in KB */ + long vmem_delta; /* size change in KB */ + ulong rmem_size; /* RSS in KB */ #ifdef XMAP - ulong pmem_size; // private mem in KB - ulong smem_size; // shared mem in KB + ulong pmem_size; /* private mem in KB */ + ulong smem_size; /* shared mem in KB */ #endif - ulong maj_faults; // majf/interval - ulong min_faults; // minf/interval - ulong total_swaps; // swapout count - long priority; // current sched priority - long niceness; // current nice value - char sched_class[PRCLSZ]; // name of class - ulong messages; // msgin+msgout/interval - ulong signals; // signals/interval - ulong vcontexts; // voluntary context switches/interval - ulong icontexts; // in-ditto - ulong charios; // characters in and out/interval - ulong lwp_count; // number of lwps for the process - ulong lwp_max; // number of contributing lwps for the process - int uid; // current uid - long ppid; // parent pid - int bindpset; // processor set binding - char fname[PRFNSZ]; // last components of exec'd pathname - char args[PRARGSZ]; // initial part of arg list - ulong lwp_class_ptr; // head of linked list of lwp_class_ptrs - - proc$() { - ulong_t MAX_PID; - ulong_t pp; // pointer to malloc for raw proc info - ulong_t pp_tmp; // temp pointer to malloc for raw proc info - ulong_t pp_ret; // temp pointer to malloc for raw proc info - // chained using nextpid - ulong_t pp_tree; - raw_proc_info_t rpi; - raw_proc_info_t t_rpi; - prusage_t ou; // old and new usage data -#define NU nu[0] - prusage_t nu[1]; // array of one for read and ioctl -#define PS ps[0] - psinfo_t ps[1]; // format changes when read used - pr_header_t prh; - prusage_t plwp; - ulong pnu; - ulong pps; - int i; - dirent_t directory_data; - ulong directory_pointer; - ulong directory_entry; - ulong_t tag; - int process_number; // current link in chain - int first_process; // fixed first link in search chain - int previous_process; // last one used to build chain - int next_process; // next pid - int broken_chain; // flag that chain changed this time - int cleaning_chain; // flag that we are in cleanup mode - int pfd; - int lfd; // file descriptor for /prod/PID/lusage - char procname[64]; - char lwpname[64]; // String for /prod/PID/lusage - long gen; // number of generations of update - int err; - int new_entry; - ulong tmp; - double dtmp; - timeval_t tmp_tval[1]; - int pg_to_kb; - - // lwp working storage - prusage_t lwp_info; - pointer_t lwp_t_ptr; - pointer_t olwp_t_ptr; - lwp_prusage lwp_t_struct; - lwp_prusage olwp_t_struct; - lwp_pr_info lwp_t_class; - long lwp_t_class_ptr; - int ircw; - -// ********************************************************** - - if (action$ == PROC_ACTION_INIT) { - action$ = PROC_ACTION_NEXT_INDEX; - // open the directory containing the process data - directory_pointer = opendir("/proc"); - index$ = -1; - off$ = 0 ; - gen = -1; - wantlwp$ = 0; - first_process=-1; - gettimeofday(tmp_tval,0); - lasttime = timeval(tmp_tval[0]); - pg_to_kb = sysconf(_SC_PAGESIZE) / 1024; - pp_tree= int2int_init(); - if (pnu == 0 || pps == 0) { - pnu = malloc(sizeof(nu)); - pps = malloc(sizeof(ps)); - } - return; - } - - if (index$ == -1) { // update the data from /proc - // read the first entry in the directory - rewinddir(directory_pointer); - directory_entry = readdir(directory_pointer); // read . - directory_entry = readdir(directory_pointer); // read .. - directory_entry = readdir(directory_pointer); - MAX_PID=0; - nproc = 0; - newproc = 0; - deadproc = 0; - gen++; - previous_process = -1; - broken_chain = 0; - cleaning_chain = 0; - while(directory_entry != NULL) { - directory_data = *((dirent_t *) directory_entry); - // get the process number and open the data file - // only look at specified process - if (action$ == PROC_ACTION_PID) { - process_number = pid$; - directory_entry = NULL; - } else { - process_number = atoi(directory_data.d_name); - } - procname = sprintf("/proc/%d/usage", process_number); - pfd = open(procname, O_RDONLY, 0); - // file cannot be accessed if pfd = -1; ignore this process - // may be that there is no permission or just died - if (pfd != -1) { // start of good pfd - if ( process_number > MAX_PID ) { - MAX_PID = process_number ; - } - tag = process_number; - pp_tmp = NULL ; - pp_ret = int2int_get(pp_tree, tag); - if ( pp_ret != NULL) { - pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); - // Process Found - } - if (pp_tmp == NULL) { - // load the tree , new process - pp = malloc(sizeof(rpi)); - memset(pp, 0, sizeof(rpi)); - new_entry = 1; - broken_chain = 1; - pp_ret= int2int_put(pp_tree, tag, pp); - if ( pp_ret < 0 ) { - printf(" Error unable to insert into tree %d, %d , %x\n", - pp_ret, tag, pp); - exit(1); - } - pp_ret = int2int_get(pp_tree, tag); - pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); - if ( pp != pp_tmp) { - printf(" Error pointers do not match %x, %x \n", - pp, pp_tmp); - exit(1); - } - } else { - new_entry = 0; - // Process Found - } - - // get the existing or blank data - tag = process_number; - pp_ret = int2int_get(pp_tree, tag); - if ( pp_ret== NULL) { - printf(" Error pointer not found for process_number %d\n", - tag); - exit(1); - } - pp = ((ulong_t) *((ulong_t *) pp_ret)); - if ( pp == NULL) { - printf("process_number %d invalid2 \n", process_number); - exit(1); - } - rpi = *((raw_proc_info_t *) pp); - - // read usage info directly - // 2.6 specific, can read usage and psinfo without needing - // ownership or permissions on /proc entry but can't read - // directly into SE structure so go via malloc buffers - - err = read(pfd, pnu, sizeof(nu)); - close(pfd); - - // turn on msacct - - procname = sprintf("/proc/%d/ctl", process_number); - pfd = open(procname, O_WRONLY, 0); - if (pfd != -1) { - if ( off$ == 0 ) { - write(pfd, &msaccton, sizeof(msaccton)); - } else { - printf("%d ms accounting off \n", process_number ); - write(pfd, &msacctoff, sizeof(msaccton)); - } - close(pfd); - } - - // get usage - procname = sprintf("/proc/%d/psinfo", process_number); - pfd = open(procname, O_RDONLY, 0); - err += read(pfd, pps, sizeof(ps)); - NU = *((prusage_t *) pnu); - PS = *((psinfo_t *) pps); - close(pfd); - if (err == 0) { - // process went away since directory was opened - // unlikely but still need to tidy up mallocs - // when it is a new entry - if ( new_entry == 1 ) { - deadproc++; - free(pp); - tag = process_number; - pp_ret=int2int_put(pp_tree, tag, NULL); - if ( pp_ret < 0 ) { - printf("unable to free tag = %d \n",tag); - exit(1); + ulong maj_faults; /* majf/interval */ + ulong min_faults; /* minf/interval */ + ulong total_swaps; /* swapout count */ + long priority; /* current sched priority */ + long niceness; /* current nice value */ + char sched_class[PRCLSZ]; /* name of class */ + ulong messages; /* msgin+msgout/interval */ + ulong signals; /* signals/interval */ + ulong vcontexts; /* voluntary context switches/interval */ + ulong icontexts; /* in-ditto */ + ulong charios; /* characters in and out/interval */ + ulong lwp_count; /* number of lwps for the process */ + int uid; /* current uid */ + long ppid; /* parent pid */ + int bindpset; /* processor set binding */ + char fname[PRFNSZ]; /* last components of exec'd pathname */ + char args[PRARGSZ]; /* initial part of arg list */ + ulong lwp_class_ptr; /* head of linked list of lwp_class_ptrs */ + + proc$() { + ulong MAX_PID; + ulong_t pp; /* pointer to malloc for raw proc info */ + ulong_t pp_tmp; /* temp pointer to malloc for raw proc info */ + ulong_t pp_ret; /* temp pointer to malloc for raw proc info */ + /* chained using nextpid */ + ulong_t pp_tree; + raw_proc_info_t rpi; + raw_proc_info_t t_rpi; + prusage_t ou; /* old and new usage data */ +#define NU nu[0] + prusage_t nu[1]; /* array of one for read and ioctl */ +#define PS ps[0] + psinfo_t ps[1]; /* format changes when read used */ + pr_header_t prh; + prusage_t plwp; + ulong pnu; + ulong pps; + int i; + dirent_t directory_data; + ulong directory_pointer; + ulong directory_entry; + ulong_t tag; + int process_number; /* current link in chain */ + int first_process; /* fixed first link in search chain */ + int previous_process; /* last one used to build chain */ + int next_process; /* next pid */ + int broken_chain; /* flag that chain changed this time */ + int cleaning_chain; /* flag that we are in cleanup mode */ + int pfd; + int lfd; /* file descriptor for /prod/PID/lusage */ + char procname[64]; + char lwpname[64]; /* String for /prod/PID/lusage */ + long gen; /* number of generations of update */ + int err; + int new_entry; + ulong tmp; + double dtmp; + timeval_t tmp_tval[1]; + int pg_to_kb; + + /* lwp working storage */ + prusage_t lwp_info; + pointer_t lwp_t_ptr; + pointer_t olwp_t_ptr; + lwp_prusage lwp_t_struct; + lwp_prusage olwp_t_struct; + lwp_pr_info lwp_t_class; + long lwp_t_class_ptr; + int ircw; +/* ********************************************************** */ + + if (action$ == PROC_ACTION_INIT) { + action$ = PROC_ACTION_NEXT_INDEX; + /* open the directory containing the process data */ + directory_pointer = opendir("/proc"); + index$ = -1; + off$ = 0 ; + gen = -1; + wantlwp$ = 0; + first_process=-1; + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + pg_to_kb = sysconf(_SC_PAGESIZE) / 1024; + pp_tree= int2int_init(); + if (pnu == 0 || pps == 0) { + pnu = malloc(sizeof(nu)); + pps = malloc(sizeof(ps)); + } + /* printf("returning from init \n"); */ + return; + } + + /* printf("index = %d PID = %d \n",index$, pid$); */ + + if (index$ == -1) { /* update the data from /proc */ + /* printf("update the data from /proc \n"); */ + /* debug_on(); */ + /* read the first entry in the directory */ + rewinddir(directory_pointer); + directory_entry = readdir(directory_pointer); /* read . */ + directory_entry = readdir(directory_pointer); /* read .. */ + directory_entry = readdir(directory_pointer); + MAX_PID=0; + nproc = 0; + newproc = 0 ; + deadproc = 0 ; + gen++; + previous_process = -1; + broken_chain = 0; + cleaning_chain = 0; + for (; directory_entry != NULL; ) { + directory_data = *((dirent_t *) directory_entry); + /* get the process number and open the data file */ + /* only look at specified process */ + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + directory_entry = NULL; + } + else { + process_number = atoi(directory_data.d_name); + /* printf("looking at %d \n" , process_number ); */ } - } - if (action$ == PROC_ACTION_PID) { - directory_entry = NULL; - } else { - directory_entry = readdir(directory_pointer); - } - continue; - } else { // good pfd - -// *************************************************************** - - if ( wantlwp$ == 1 ) { - // read the lwp info - lwpname = sprintf("/proc/%d/lusage", process_number); - lfd = open(lwpname, O_RDONLY, 0); - if ( lfd > 0 ) { - lwp_t_ptr = malloc(sizeof(prh)); - err = read(lfd, lwp_t_ptr, sizeof(prh)); - prh = *((pr_header_t *) lwp_t_ptr); - free(lwp_t_ptr); - if (err <= 0) { - printf("Error reading pr_header %s error code = %d \n", - lwpname, err); - } else { // good read of pr_head - // if there is an old lwp linked list free it - lwp_t_ptr = rpi.olwp ; - while ( lwp_t_ptr != NULL ) { - lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); - free(lwp_t_ptr); - lwp_t_ptr = lwp_t_struct.next_lwp_pru ; +#if MINOR_VERSION < 60 + printf(" OS Version < 2.6 not supported \n "); + exit(1); +#else + procname = sprintf("/proc/%d/usage", process_number); +#endif + pfd = open(procname, O_RDONLY, 0); + /* file cannot be accessed if pfd = -1; ignore this process */ + /* may be that there is no permission or just died */ + if (pfd != -1) { /* start of good pfd */ + if ( process_number > MAX_PID ) { + MAX_PID = process_number ; + } + tag = process_number; + pp_tmp = NULL ; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret != NULL) { + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + /* Process Found */ + } + if (pp_tmp == NULL) { + /* load the tree , new process */ + pp = malloc(sizeof(rpi)); + memset(pp, 0, sizeof(rpi)); + new_entry = 1; + broken_chain = 1; + pp_ret= int2int_put(pp_tree, tag, pp); + if ( pp_ret < 0 ) { + printf(" Error unable to insert into tree %d, %d , %x\n", + pp_ret , tag, pp); + exit(1); + } + pp_ret = int2int_get(pp_tree, tag); + pp_tmp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp != pp_tmp) { + printf(" Error pointers do not match %x, %x \n", + pp, pp_tmp); + exit(1); + } + } else { + new_entry = 0; + /* Process Found */ + } + + /* get the existing or blank data */ + tag = process_number; + pp_ret = int2int_get(pp_tree, tag); + if ( pp_ret== NULL) { + printf(" Error pointer not found for process_number %d\n", + tag); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid2 \n", process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); + + /* read usage info directly */ + /* 2.6 specific, can read usage and psinfo without needing + ownership or permissions on /proc entry but can't read + directly into SE structure so go via malloc buffers */ + err = read(pfd, pnu, sizeof(nu)); + close(pfd); + /* turn on msacct */ + procname = sprintf("/proc/%d/ctl", process_number); + pfd = open(procname, O_WRONLY, 0); + if (pfd != -1) { + if ( off$ == 0 ) { + write(pfd, &msaccton, sizeof(msaccton)); + } else { + printf("%d ms accounting off \n", process_number ); + write(pfd, &msacctoff, sizeof(msaccton)); } - rpi.olwp = rpi.nlwp; - rpi.nlwp = NULL; - // create new lwp linked list - for (ircw=0; ircw 0 ) { + lwp_t_ptr = malloc(sizeof(prh)); + err = read(lfd, lwp_t_ptr, sizeof(prh)); + prh = *((pr_header_t *) lwp_t_ptr); + free(lwp_t_ptr); + if (err <= 0){ + printf("Error reading pr_header %s error code = %d \n", lwpname, err); } + else { /* good read of pr_head */ + /* printf (" size of lwp_prusage = %d, size from pr header = %d \n", sizeof(lwp_info), prh.size_of_entries ); */ + /* if there is an old lwp linked list free it */ + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); free(lwp_t_ptr); - lwp_t_ptr=malloc(sizeof(lwp_t_struct)); - memset(lwp_t_ptr, NULL, sizeof(lwp_t_struct)); - struct_empty(lwp_info, lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + rpi.olwp = rpi.nlwp; + rpi.nlwp = NULL; + /* create new lwp linked list */ + for (ircw=0; ircw lasttime) { + newproc++; + if (new_entry == 0) { + /* leftover from an old process at same pid */ + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; /* dump old rp, and overwrite new */ + } +/* ***************** delete old lwp info ********************* */ + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + rpi.olwp = NULL; + while ( lwp_t_ptr != NULL ) { lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); - lwp_t_struct.next_lwp_pru = rpi.nlwp; - struct_empty(lwp_t_struct, lwp_t_ptr); - rpi.nlwp = lwp_t_ptr; - } else { free(lwp_t_ptr); - } + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; } - } // end for - - close(lfd); - - } // end else on bad pr header read - } // good open on lfd - } // end of wantlwp -// ********** lwp info read ************************************** - } // good read on pfd - - if (new_entry == 1 ) { - rpi.nextpid = first_process; - first_process = process_number; - } - - // check to see if we are still dealing with the same process - // we had before, and update and - if (new_entry == 1 || timestruc(PS.pr_start) > lasttime) { - newproc++; - if (new_entry == 0) { - // leftover from an old process at same pid - if (rpi.orp != NULL) { - free(rpi.orp); - rpi.orp = NULL; // dump old rp, and overwrite new - } -// ***************** delete old lwp info ********************* - if ( wantlwp$ == 1 ) { - lwp_t_ptr = rpi.olwp ; - rpi.olwp = NULL; - while ( lwp_t_ptr != NULL ) { - lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); - free(lwp_t_ptr); - lwp_t_ptr = lwp_t_struct.next_lwp_pru ; - } - } -// ***************** end delete old lwp info ********************* - } - // static psinfo needs updating - rpi.pr_uid = PS.pr_uid; - rpi.pr_ppid = PS.pr_ppid; - rpi.pr_bindpset = PS.pr_lwp.pr_bindpset; - rpi.pr_clname = PS.pr_lwp.pr_clname; - rpi.pr_fname = PS.pr_fname; - rpi.pr_psargs = PS.pr_psargs; - } - // update usage data - tmp = rpi.orp; // hang on to malloced data - rpi.orp = rpi.nrp; // switch new to old - if (tmp == NULL) { - rpi.nrp = malloc(sizeof(ou)); - } else { - rpi.nrp = tmp; - } - struct_empty(NU, rpi.nrp); // save whole block - // update dynamic psinfo data - rpi.pr_oldsize = rpi.pr_size; - rpi.pr_size = PS.pr_size; - rpi.pr_rssize = PS.pr_rssize; - rpi.pr_pri = PS.pr_lwp.pr_pri; - rpi.pr_nice = PS.pr_lwp.pr_nice; - rpi.pr_sname = PS.pr_lwp.pr_sname; - rpi.pr_flag = PS.pr_flag; - rpi.o_pr_time = rpi.n_pr_time; - rpi.n_pr_time = PS.pr_time; - rpi.o_pr_ctime = rpi.n_pr_ctime; - rpi.n_pr_ctime = PS.pr_ctime; - rpi.lwp_count = PS.pr_nlwp; - rpi.gencnt = gen; - struct_empty(rpi, pp); - nproc++; - // printf("processed %d \n" , process_number ); - } // end of good pfd - // step through the files in the directory ... - if (action$ == PROC_ACTION_PID) { - directory_entry = NULL; - } else { - directory_entry = readdir(directory_pointer); - } - } // end of directory -// ************************************************************** - // go through list and remove deadwood - // printf("first process_number %d \n",first_process); - process_number = first_process; - next_process = -1; - previous_process = -1; - while ( process_number > 0 ) { - // printf("processing %d \n",process_number); - if (process_number > 0 ) { - pp_ret = int2int_get(pp_tree, process_number); - if ( pp_ret == NULL) { - printf("unable to get process_number %d \n", process_number); - exit(1); - } - pp = ((ulong_t) *((ulong_t *) pp_ret)); - if ( pp == NULL) { - printf("process_number %d invalid4 \n",process_number); - exit(1); - } - rpi = *((raw_proc_info_t *) pp); // rpi <- pp - next_process = rpi.nextpid; - // printf("next process %d \n",next_process); - // unhook dead processes - if (rpi.gencnt != gen) { - deadproc++; - if (rpi.orp != NULL) { - free(rpi.orp); - rpi.orp = NULL; - } - if (rpi.nrp != NULL) { - free(rpi.nrp); - rpi.nrp = NULL; - } - if ( wantlwp$ == 1 ) { - lwp_t_ptr = rpi.olwp ; - while ( lwp_t_ptr != NULL ) { - lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); - free(lwp_t_ptr); - lwp_t_ptr = lwp_t_struct.next_lwp_pru ; - } - lwp_t_ptr = t_rpi.nlwp ; - while ( lwp_t_ptr != NULL ) { - lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); - free(lwp_t_ptr); - lwp_t_ptr = lwp_t_struct.next_lwp_pru ; - } - } - free(pp); - pp_ret = int2int_put(pp_tree, process_number , NULL); - if ( pp_ret < 0 ) { - printf("unable to free process_number \n"); - exit(1); - } - if ( previous_process > 0 ) { // there was a previous process - pp_tmp = int2int_get(pp_tree, previous_process); - if ( pp_tmp == NULL) { - printf("unable to get process_number %d \n", - previous_process); - exit(1); - } - pp = ((ulong_t) *((ulong_t *) pp_tmp)); - if ( pp == NULL) { - printf("process_number %d invalid5 \n", - previous_process); - exit(1); - } - rpi = *((raw_proc_info_t *) pp); // rpi <- pp - // printf("previous process %d \n",previous_process); - rpi.nextpid = next_process; - struct_empty(rpi, pp); - } else { - first_process = next_process; - } - } else { - // update previous process ptr - previous_process = process_number; - } - } - process_number = next_process; - } - // printf(" end of deadwood removal \n"); - gettimeofday(tmp_tval,0); - lasttime = timeval(tmp_tval[0]); - process_number = first_process; - index$ = -1; - } - // printf("done updating \n"); - // printf("MAX_PID = %d \n", MAX_PID); -// ****************************** end of update section ******************* - - if (action$ == PROC_ACTION_NEXT_INDEX ) { - // printf("PROC_ACTION_NEXT_INDEX \n"); - if (index$ == -1) { - process_number = first_process; - } else { - process_number = rpi.nextpid; - } - if (process_number < 0 || process_number > MAX_PID) { - // ran out of data - process_number = -1; - index$ = -1; - pid$ = -1; - // printf(" thats all there is \n"); - return; - } - index$++; - } - - if (action$ == PROC_ACTION_NEXT_PID) { - // printf("PROC_ACTION_NEXT_PID \n"); - if (index$ == -1) { - process_number = 0; - } else { - process_number++; - } - index$++; - // look for the next data - pp = NULL; - pp_ret=int2int_get(pp_tree,process_number); - if ( pp_ret != NULL ) { - pp = ((ulong_t) *((ulong_t *) pp_ret)); - } - while (process_number < MAX_PID && pp == NULL) { - process_number++; - pp = NULL; - pp_ret=int2int_get(pp_tree,process_number); - if ( pp_ret != NULL ) { - pp = ((ulong_t) *((ulong_t *) pp_ret)); - } - } - if (process_number < 0 || process_number > MAX_PID) { - // ran out of data - process_number = -1; - index$ = -1; - pid$ = -1; - // printf(" ran out of data NEXT PID \n"); - return; - } - } - - if (action$ == PROC_ACTION_PID) { - process_number = pid$; - index$ = 0; - } - - // common code to update class once process has been chosen - - pp_ret=int2int_get(pp_tree,process_number); - pp = NULL; - if (pp_ret != NULL) { - pp = ((ulong_t) *((ulong_t *) pp_ret)); - } - if ( pp != NULL) { - rpi = *((raw_proc_info_t *) pp); - // make sure that all class data is updated - // index$ is already set - pid$ = process_number; - uid = rpi.pr_uid; - // nproc, , are already set - missedproc = rpi.nextpid; // for debug until fork counting - - // nrp will always be set - NU = *((prusage_t *) rpi.nrp); - creation = timestruc(NU.pr_create); - timestamp = timestruc(NU.pr_tstamp); - termination = 0.0; // set later if process is dead - elapsed = timestruc(NU.pr_rtime); - total_user = timestruc(NU.pr_utime); - total_system = timestruc(NU.pr_stime); - total_child = timestruc(rpi.n_pr_ctime); - total_sampled_cpu = timestruc(rpi.n_pr_time); - flags = rpi.pr_flag; + } +/* ***************** end delete old lwp info ********************* */ + } + /* static psinfo needs updating */ + rpi.pr_uid = PS.pr_uid; + rpi.pr_ppid = PS.pr_ppid; + rpi.pr_bindpset = PS.pr_lwp.pr_bindpset; + rpi.pr_clname = PS.pr_lwp.pr_clname; + rpi.pr_fname = PS.pr_fname; + rpi.pr_psargs = PS.pr_psargs; + } + /* update usage data */ + tmp = rpi.orp; /* hang on to malloced data */ + rpi.orp = rpi.nrp; /* switch new to old */ + if (tmp == NULL) { + rpi.nrp = malloc(sizeof(ou)); + } else { + rpi.nrp = tmp; + } + struct_empty(NU, rpi.nrp); /* save whole block */ + /* update dynamic psinfo data */ + rpi.pr_oldsize = rpi.pr_size; + rpi.pr_size = PS.pr_size; + rpi.pr_rssize = PS.pr_rssize; + rpi.pr_pri = PS.pr_lwp.pr_pri; + rpi.pr_nice = PS.pr_lwp.pr_nice; + rpi.pr_sname = PS.pr_lwp.pr_sname; + rpi.pr_flag = PS.pr_flag; + rpi.o_pr_time = rpi.n_pr_time; + rpi.n_pr_time = PS.pr_time; + rpi.o_pr_ctime = rpi.n_pr_ctime; + rpi.n_pr_ctime = PS.pr_ctime; + rpi.gencnt = gen; + struct_empty(rpi,pp); + nproc++; + /* printf("processed %d \n" , process_number ); */ + } /* end of good pfd */ + /* step through the files in the directory ... */ + if (action$ == PROC_ACTION_PID) { + directory_entry = NULL; + } + else { + directory_entry = readdir(directory_pointer); + } + } /* end of directory*/ +/* ************************************************************** */ + /* go through list and remove deadwood */ + /* printf("first process_number %d \n",first_process); */ + process_number = first_process; + next_process = -1; + previous_process = -1; + while ( process_number > 0 ) { + /* printf("processing %d \n",process_number); */ + if (process_number > 0 ) { + pp_ret = int2int_get(pp_tree, process_number); + if ( pp_ret == NULL) { + printf("unable to get process_number %d \n", process_number); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_ret)); + if ( pp == NULL) { + printf("process_number %d invalid4 \n",process_number); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + next_process = rpi.nextpid; + /* printf("next process %d \n",next_process); */ + /* unhook dead processes */ + if (rpi.gencnt != gen) { + deadproc++; + /* printf("process_number %d being deleted \n",process_number); */ + if (rpi.orp != NULL) { + free(rpi.orp); + rpi.orp = NULL; + } + if (rpi.nrp != NULL) { + free(rpi.nrp); + rpi.nrp = NULL; + } + if ( wantlwp$ == 1 ) { + lwp_t_ptr = rpi.olwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + lwp_t_ptr = t_rpi.nlwp ; + while ( lwp_t_ptr != NULL ) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } + } + free(pp); + pp_ret = int2int_put(pp_tree, process_number , NULL); + if ( pp_ret < 0 ) { + printf("unable to free process_number \n"); + exit(1); + } + if ( previous_process > 0 ) { /* there was a previous process */ + pp_tmp = int2int_get(pp_tree, previous_process); + if ( pp_tmp == NULL) { + printf("unable to get process_number %d \n", previous_process); + exit(1); + } + pp = ((ulong_t) *((ulong_t *) pp_tmp)); + if ( pp == NULL) { + printf("process_number %d invalid5 \n",previous_process); + exit(1); + } + rpi = *((raw_proc_info_t *) pp); // rpi <- pp + /* printf("previous process %d \n",previous_process); */ + rpi.nextpid = next_process; + struct_empty(rpi, pp); + } else { + first_process = next_process; + } + } else { + /* update previous process ptr */ + previous_process = process_number; + } + } + process_number = next_process; + } + /* printf(" end of deadwood removal \n"); */ + gettimeofday(tmp_tval,0); + lasttime = timeval(tmp_tval[0]); + process_number = first_process; + index$ = -1; + } + /* printf("done updating \n"); */ + /* printf("MAX_PID = %d \n", MAX_PID); */ +/* ****************************** end of update section ******************* */ + + if (action$ == PROC_ACTION_NEXT_INDEX ) { + /* printf("PROC_ACTION_NEXT_INDEX \n"); */ + if (index$ == -1) { + process_number = first_process; + } else { + process_number = rpi.nextpid; + } + if (process_number < 0 || process_number > MAX_PID) { + /* ran out of data */ + process_number = -1; + index$ = -1; + pid$ = -1; + /* printf(" thats all there is \n"); */ + return; + } + index$++; + } + + if (action$ == PROC_ACTION_NEXT_PID) { + /* printf("PROC_ACTION_NEXT_PID \n"); */ + if (index$ == -1) { + process_number = 0; + } else { + process_number++; + } + index$++; + /* look for the next data */ + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + while (process_number < MAX_PID && pp == NULL) { + process_number++; + pp = NULL; + pp_ret=int2int_get(pp_tree,process_number); + if ( pp_ret != NULL ) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + } + if (process_number < 0 || process_number > MAX_PID) { + /* ran out of data */ + process_number = -1; + index$ = -1; + pid$ = -1; + /* printf(" ran out of data NEXT PID \n"); */ + return; + } + } + + if (action$ == PROC_ACTION_PID) { + process_number = pid$; + index$ = 0; + } + + /* common code to update class once process has been chosen */ + /* printf("process number = %d \n", process_number); */ + /* printf("retreiving process_number %d , PID$ %d \n",process_number, pid$); */ + pp_ret=int2int_get(pp_tree,process_number); + pp = NULL; + if (pp_ret != NULL) { + pp = ((ulong_t) *((ulong_t *) pp_ret)); + } + if ( pp != NULL) { + rpi = *((raw_proc_info_t *) pp); + /* make sure that all class data is updated */ + /* index$ is already set */ + pid$ = process_number; + uid = rpi.pr_uid; + /* nproc, , are already set */ + missedproc = rpi.nextpid; /* for debug until fork counting */ + + /* nrp will always be set */ + NU = *((prusage_t *) rpi.nrp); + creation = timestruc(NU.pr_create); + timestamp = timestruc(NU.pr_tstamp); + termination = 0.0; /* set later if process is dead */ + elapsed = timestruc(NU.pr_rtime); + total_user = timestruc(NU.pr_utime); + total_system = timestruc(NU.pr_stime); + total_child = timestruc(rpi.n_pr_ctime); + total_sampled_cpu = timestruc(rpi.n_pr_time); + flags = rpi.pr_flag; #ifdef PDEBUG - msprint(NU, pid$, rpi.pr_fname, rpi.pr_psargs); + msprint(NU, pid$, fname, args); #endif - if (rpi.orp != NULL) { - ou = *((prusage_t *) rpi.orp); - interval = timestamp - timestruc(ou.pr_tstamp); - // interval should never be zero - if (interval == 0.0) { - printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); - msprint(ou, pid$, fname, args); - interval = 1.0; - } - user_time = total_user - timestruc(ou.pr_utime); - system_time = total_system - timestruc(ou.pr_stime); - sampled_cpu = total_sampled_cpu - timestruc(rpi.o_pr_time); - trap_time = timestruc(NU.pr_ttime) - timestruc(ou.pr_ttime); - child_time = total_child - timestruc(rpi.o_pr_ctime); - text_pf_time = timestruc(NU.pr_tftime) - timestruc(ou.pr_tftime); - data_pf_time = timestruc(NU.pr_dftime) - timestruc(ou.pr_dftime); - kernel_pf_time = timestruc(NU.pr_kftime) - timestruc(ou.pr_kftime); - user_lock_time = timestruc(NU.pr_ltime) - timestruc(ou.pr_ltime); - sleep_time = timestruc(NU.pr_slptime) - timestruc(ou.pr_slptime); - cpu_wait_time = timestruc(NU.pr_wtime) - timestruc(ou.pr_wtime); - stoptime = timestruc(NU.pr_stoptime) - timestruc(ou.pr_stoptime); - syscalls = NU.pr_sysc - ou.pr_sysc; - inblocks = NU.pr_inblk - ou.pr_inblk; - outblocks = NU.pr_oublk - ou.pr_oublk; - maj_faults = NU.pr_majf - ou.pr_majf; - min_faults = NU.pr_minf - ou.pr_minf; - messages = (NU.pr_msnd + NU.pr_mrcv) - (ou.pr_msnd + ou.pr_mrcv); - signals = NU.pr_sigs - ou.pr_sigs; - vcontexts = NU.pr_vctx - ou.pr_vctx; - icontexts = NU.pr_ictx - ou.pr_ictx; - charios = NU.pr_ioch - ou.pr_ioch; - } else { - // new process will only have rpi.nrp set - interval = timestamp - creation; // elapsed time so far - if (interval == 0.0) { - printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); - msprint(NU, pid$, fname, args); - interval = 1.0; - } - user_time = total_user; - system_time = total_system; - sampled_cpu = total_sampled_cpu; - trap_time = timestruc(NU.pr_ttime); - child_time = total_child; - text_pf_time = timestruc(NU.pr_tftime); - data_pf_time = timestruc(NU.pr_dftime); - kernel_pf_time = timestruc(NU.pr_kftime); - user_lock_time = timestruc(NU.pr_ltime); - sleep_time = timestruc(NU.pr_slptime); - cpu_wait_time = timestruc(NU.pr_wtime); - stoptime = timestruc(NU.pr_stoptime); - syscalls = NU.pr_sysc; - inblocks = NU.pr_inblk; - outblocks = NU.pr_oublk; - maj_faults = NU.pr_majf; - min_faults = NU.pr_minf; - messages = NU.pr_msnd + NU.pr_mrcv; - signals = NU.pr_sigs; - vcontexts = NU.pr_vctx; - icontexts = NU.pr_ictx; - charios = NU.pr_ioch; - } - vmem_size = rpi.pr_size; - vmem_delta = rpi.pr_size - rpi.pr_oldsize; - rmem_size = rpi.pr_rssize; - total_swaps = NU.pr_nswap; - priority = rpi.pr_pri; - niceness = rpi.pr_nice; - sched_class = rpi.pr_clname; - lwp_max = NU.pr_count; - lwp_count = rpi.lwp_count; - ppid = rpi.pr_ppid; - bindpset = rpi.pr_bindpset; - fname = rpi.pr_fname; - if (fname == "" && rpi.pr_sname == 'Z') { - fname = "Zombie"; - bindpset = -1; // no pset, but Zomb defaults to 0 - } - args = rpi.pr_psargs; - // bug in sched pid 0 gives 100% system time - if (pid$ == 0) { - total_system = 0.0; - system_time = 0.0; - } + if (rpi.orp != NULL) { + ou = *((prusage_t *) rpi.orp); + interval = timestamp - timestruc(ou.pr_tstamp); + /* interval should never be zero */ + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(ou, pid$, fname, args); + interval = 1.0; + } + user_time = total_user - timestruc(ou.pr_utime); + system_time = total_system - timestruc(ou.pr_stime); + sampled_cpu = total_sampled_cpu - timestruc(rpi.o_pr_time); + trap_time = timestruc(NU.pr_ttime) - timestruc(ou.pr_ttime); + child_time = total_child - timestruc(rpi.o_pr_ctime); + text_pf_time = timestruc(NU.pr_tftime) - timestruc(ou.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime) - timestruc(ou.pr_dftime); + kernel_pf_time = timestruc(NU.pr_kftime) - timestruc(ou.pr_kftime); + user_lock_time = timestruc(NU.pr_ltime) - timestruc(ou.pr_ltime); + sleep_time = timestruc(NU.pr_slptime) - timestruc(ou.pr_slptime); + cpu_wait_time = timestruc(NU.pr_wtime) - timestruc(ou.pr_wtime); + stoptime = timestruc(NU.pr_stoptime) - timestruc(ou.pr_stoptime); + syscalls = NU.pr_sysc - ou.pr_sysc; + inblocks = NU.pr_inblk - ou.pr_inblk; + outblocks = NU.pr_oublk - ou.pr_oublk; + maj_faults = NU.pr_majf - ou.pr_majf; + min_faults = NU.pr_minf - ou.pr_minf; + messages = (NU.pr_msnd + NU.pr_mrcv) - (ou.pr_msnd + ou.pr_mrcv); + signals = NU.pr_sigs - ou.pr_sigs; + vcontexts = NU.pr_vctx - ou.pr_vctx; + icontexts = NU.pr_ictx - ou.pr_ictx; + charios = NU.pr_ioch - ou.pr_ioch; + } else { + /* new process will only have rpi.nrp set */ + interval = timestamp - creation; /* elapsed time so far */ + if (interval == 0.0) { + printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname); + msprint(NU, pid$, fname, args); + interval = 1.0; + } + user_time = total_user; + system_time = total_system; + sampled_cpu = total_sampled_cpu; + trap_time = timestruc(NU.pr_ttime); + child_time = total_child; + text_pf_time = timestruc(NU.pr_tftime); + data_pf_time = timestruc(NU.pr_dftime); + user_lock_time = timestruc(NU.pr_ltime); + stoptime = timestruc(NU.pr_stoptime); + inblocks = NU.pr_inblk; + outblocks = NU.pr_oublk; + maj_faults = NU.pr_majf; + min_faults = NU.pr_minf; + messages = NU.pr_msnd + NU.pr_mrcv; + vcontexts = NU.pr_vctx; + icontexts = NU.pr_ictx; + charios = NU.pr_ioch; + } + vmem_size = rpi.pr_size; + vmem_delta = rpi.pr_size - rpi.pr_oldsize; + rmem_size = rpi.pr_rssize; + total_swaps = NU.pr_nswap; + priority = rpi.pr_pri; + niceness = rpi.pr_nice; + sched_class = rpi.pr_clname; + lwp_count = NU.pr_count; + ppid = rpi.pr_ppid; + bindpset = rpi.pr_bindpset; + fname = rpi.pr_fname; + if (fname == "" && rpi.pr_sname == 'Z') { + fname = "Zombie"; + bindpset = -1; /* no pset, but Zomb defaults to 0 */ + } + args = rpi.pr_psargs; + /* bug in sched pid 0 gives 100% system time */ + if (pid$ == 0) { + total_system = 0.0; + system_time = 0.0; + } #ifdef PDEBUG - printf("interval %.5f\n", interval); + printf("interval %.5f\n", interval); #endif -// ******************************************************* - if ( wantlwp$ == 1 ) { - // process lwp info - lwp_t_ptr = lwp_class_ptr; - lwp_class_ptr = NULL; - // if there is an old lwp class linked list free it - while ( lwp_t_ptr != NULL ) { - lwp_t_class = *((lwp_pr_info *) lwp_t_ptr); - free(lwp_t_ptr); - lwp_t_ptr = lwp_t_class.next_class ; - } - // Process lwp information - if ( rpi.nlwp != NULL ) { - lwp_t_ptr = rpi.nlwp ; - while ( lwp_t_ptr != NULL) { - lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); - lwp_t_class.lwp_id = lwp_t_struct.lwp_pru.pr_lwpid; - lwp_t_class.timestamp = timestruc(lwp_t_struct.lwp_pru.pr_tstamp); - lwp_t_class.creation = timestruc(lwp_t_struct.lwp_pru.pr_create); - lwp_t_class.termination = timestruc(lwp_t_struct.lwp_pru.pr_term); - lwp_t_class.user_time = timestruc(lwp_t_struct.lwp_pru.pr_utime); - lwp_t_class.system_time = timestruc(lwp_t_struct.lwp_pru.pr_stime) + timestruc(lwp_t_struct.lwp_pru.pr_ttime); - lwp_t_class.text_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_tftime) ; - lwp_t_class.data_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_dftime) ; - lwp_t_class.kernel_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_kftime) ; - lwp_t_class.user_lock_time = timestruc(lwp_t_struct.lwp_pru.pr_ltime) ; - lwp_t_class.sleep_time = timestruc(lwp_t_struct.lwp_pru.pr_slptime) ; - lwp_t_class.cpu_wait_time = timestruc(lwp_t_struct.lwp_pru.pr_wtime) ; - lwp_t_class.stoptime = timestruc(lwp_t_struct.lwp_pru.pr_stoptime) ; - lwp_t_class.min_faults = lwp_t_struct.lwp_pru.pr_minf ; - lwp_t_class.maj_faults = lwp_t_struct.lwp_pru.pr_majf ; - lwp_t_class.total_swaps = lwp_t_struct.lwp_pru.pr_nswap; - lwp_t_class.inblocks = lwp_t_struct.lwp_pru.pr_inblk ; - lwp_t_class.outblocks = lwp_t_struct.lwp_pru.pr_oublk ; - lwp_t_class.messages = lwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; - lwp_t_class.signals = lwp_t_struct.lwp_pru.pr_sigs; - lwp_t_class.vcontexts = lwp_t_struct.lwp_pru.pr_vctx; - lwp_t_class.icontexts = lwp_t_struct.lwp_pru.pr_ictx; - lwp_t_class.syscalls = lwp_t_struct.lwp_pru.pr_sysc; - lwp_t_class.charios = lwp_t_struct.lwp_pru.pr_ioch; - - olwp_t_ptr = rpi.olwp; - while ( olwp_t_ptr != NULL ) { - olwp_t_struct = *((lwp_prusage *) olwp_t_ptr); - if ( olwp_t_struct.lwp_pru.pr_lwpid == - lwp_t_struct.lwp_pru.pr_lwpid) { - break; +/* ******************************************************* */ + if ( wantlwp$ == 1 ) { + /* process lwp info */ + lwp_t_ptr = lwp_class_ptr; + lwp_class_ptr = NULL; + /* if there is an old lwp class linked list free it */ + while ( lwp_t_ptr != NULL ) { + lwp_t_class = *((lwp_pr_info *) lwp_t_ptr); + free(lwp_t_ptr); + lwp_t_ptr = lwp_t_class.next_class ; } - olwp_t_ptr = olwp_t_struct.next_lwp_pru ; - } - if ( olwp_t_ptr != NULL) { - lwp_t_class.user_time = lwp_t_class.user_time - timestruc(olwp_t_struct.lwp_pru.pr_utime); - lwp_t_class.system_time = lwp_t_class.system_time - timestruc(olwp_t_struct.lwp_pru.pr_stime) - timestruc(olwp_t_struct.lwp_pru.pr_ttime); - lwp_t_class.text_pf_time = lwp_t_class.text_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_tftime) ; - lwp_t_class.data_pf_time = lwp_t_class.data_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_dftime) ; - lwp_t_class.kernel_pf_time = lwp_t_class.kernel_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_kftime) ; - lwp_t_class.user_lock_time = lwp_t_class.user_lock_time - timestruc(olwp_t_struct.lwp_pru.pr_ltime) ; - lwp_t_class.sleep_time = lwp_t_class.sleep_time - timestruc(olwp_t_struct.lwp_pru.pr_slptime) ; - lwp_t_class.cpu_wait_time = lwp_t_class.cpu_wait_time - timestruc(olwp_t_struct.lwp_pru.pr_wtime) ; - lwp_t_class.stoptime = lwp_t_class.stoptime - timestruc(olwp_t_struct.lwp_pru.pr_stoptime) ; - lwp_t_class.min_faults = lwp_t_class.min_faults - olwp_t_struct.lwp_pru.pr_minf ; - lwp_t_class.maj_faults = lwp_t_class.maj_faults - olwp_t_struct.lwp_pru.pr_majf ; - lwp_t_class.total_swaps = lwp_t_class.total_swaps - olwp_t_struct.lwp_pru.pr_nswap; - lwp_t_class.inblocks = lwp_t_class.inblocks - olwp_t_struct.lwp_pru.pr_inblk ; - lwp_t_class.outblocks = lwp_t_class.outblocks - olwp_t_struct.lwp_pru.pr_oublk ; - lwp_t_class.messages = lwp_t_class.messages - olwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; - lwp_t_class.signals = lwp_t_class.signals - olwp_t_struct.lwp_pru.pr_sigs; - lwp_t_class.vcontexts = lwp_t_class.vcontexts - olwp_t_struct.lwp_pru.pr_vctx; - lwp_t_class.icontexts = lwp_t_class.icontexts - olwp_t_struct.lwp_pru.pr_ictx; - lwp_t_class.syscalls = lwp_t_class.syscalls - olwp_t_struct.lwp_pru.pr_sysc; - lwp_t_class.charios = lwp_t_class.charios - olwp_t_struct.lwp_pru.pr_ioch; - - } // end of if old pointer - lwp_t_class_ptr = malloc(sizeof(lwp_t_class)); - memset(lwp_t_class_ptr, NULL, sizeof(lwp_t_class)); - lwp_t_class.next_class = lwp_class_ptr; - lwp_class_ptr = lwp_t_class_ptr; - struct_empty(lwp_t_class, lwp_t_class_ptr); - lwp_t_ptr = lwp_t_struct.next_lwp_pru ; - } // end of while - } // end of if we have lwps - } // end of we want lwps - } else { // End if valid pp - process_number = -1; - index$ = -1; - pid$ = -1; - } - } + /* Process lwp information */ + if ( rpi.nlwp != NULL ) { + lwp_t_ptr = rpi.nlwp ; + while ( lwp_t_ptr != NULL) { + lwp_t_struct = *((lwp_prusage *) lwp_t_ptr); + lwp_t_class.lwp_id = lwp_t_struct.lwp_pru.pr_lwpid; + lwp_t_class.timestamp = timestruc(lwp_t_struct.lwp_pru.pr_tstamp); + lwp_t_class.creation = timestruc(lwp_t_struct.lwp_pru.pr_create); + lwp_t_class.termination = timestruc(lwp_t_struct.lwp_pru.pr_term); + lwp_t_class.user_time = timestruc(lwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = timestruc(lwp_t_struct.lwp_pru.pr_stime) + timestruc(lwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = timestruc(lwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = timestruc(lwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = timestruc(lwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = timestruc(lwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_struct.lwp_pru.pr_ioch; + + olwp_t_ptr = rpi.olwp; + while ( olwp_t_ptr != NULL ) { + olwp_t_struct = *((lwp_prusage *) olwp_t_ptr); + if ( olwp_t_struct.lwp_pru.pr_lwpid == lwp_t_struct.lwp_pru.pr_lwpid) { + break; } + olwp_t_ptr = olwp_t_struct.next_lwp_pru ; + } + if ( olwp_t_ptr != NULL) { + lwp_t_class.user_time = lwp_t_class.user_time - timestruc(olwp_t_struct.lwp_pru.pr_utime); + lwp_t_class.system_time = lwp_t_class.system_time - timestruc(olwp_t_struct.lwp_pru.pr_stime) - timestruc(olwp_t_struct.lwp_pru.pr_ttime); + lwp_t_class.text_pf_time = lwp_t_class.text_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_tftime) ; + lwp_t_class.data_pf_time = lwp_t_class.data_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_dftime) ; + lwp_t_class.kernel_pf_time = lwp_t_class.kernel_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_kftime) ; + lwp_t_class.user_lock_time = lwp_t_class.user_lock_time - timestruc(olwp_t_struct.lwp_pru.pr_ltime) ; + lwp_t_class.sleep_time = lwp_t_class.sleep_time - timestruc(olwp_t_struct.lwp_pru.pr_slptime) ; + lwp_t_class.cpu_wait_time = lwp_t_class.cpu_wait_time - timestruc(olwp_t_struct.lwp_pru.pr_wtime) ; + lwp_t_class.stoptime = lwp_t_class.stoptime - timestruc(olwp_t_struct.lwp_pru.pr_stoptime) ; + lwp_t_class.min_faults = lwp_t_class.min_faults - olwp_t_struct.lwp_pru.pr_minf ; + lwp_t_class.maj_faults = lwp_t_class.maj_faults - olwp_t_struct.lwp_pru.pr_majf ; + lwp_t_class.total_swaps = lwp_t_class.total_swaps - olwp_t_struct.lwp_pru.pr_nswap; + lwp_t_class.inblocks = lwp_t_class.inblocks - olwp_t_struct.lwp_pru.pr_inblk ; + lwp_t_class.outblocks = lwp_t_class.outblocks - olwp_t_struct.lwp_pru.pr_oublk ; + lwp_t_class.messages = lwp_t_class.messages - olwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv; + lwp_t_class.signals = lwp_t_class.signals - olwp_t_struct.lwp_pru.pr_sigs; + lwp_t_class.vcontexts = lwp_t_class.vcontexts - olwp_t_struct.lwp_pru.pr_vctx; + lwp_t_class.icontexts = lwp_t_class.icontexts - olwp_t_struct.lwp_pru.pr_ictx; + lwp_t_class.syscalls = lwp_t_class.syscalls - olwp_t_struct.lwp_pru.pr_sysc; + lwp_t_class.charios = lwp_t_class.charios - olwp_t_struct.lwp_pru.pr_ioch; + + } /* end of if old pointer */ + lwp_t_class_ptr = malloc(sizeof(lwp_t_class)); + memset(lwp_t_class_ptr, NULL, sizeof(lwp_t_class)); + lwp_t_class.next_class = lwp_class_ptr; + lwp_class_ptr = lwp_t_class_ptr; + struct_empty(lwp_t_class, lwp_t_class_ptr); + lwp_t_ptr = lwp_t_struct.next_lwp_pru ; + } /* end of while */ +} /* end of if we have lwps */ +}/* end of we want lwps */ +/* End if valid pp */ +}else { + process_number = -1; + index$ = -1; + pid$ = -1; + /* printf(" ran out of data NEXT PID \n"); */ + } +} }; - -#endif + + From dmberezin at hotmail.com Fri Nov 19 07:12:47 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Fri, 19 Nov 2004 07:12:47 -0800 Subject: [Orca-checkins] r406 - trunk/orca/lib/SE/3.2.1 Message-ID: <200411191512.iAJFClmP028368@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Fri Nov 19 07:10:42 2004 New Revision: 406 Modified: trunk/orca/lib/SE/3.2.1/orca_process_class.se Log: Fix a thread counting bug in orca_process_class.se version 3.2.1 * lib/SE/3.2.1/orca_process_class.se Apply a fix from revision 404 to this version of orca_process_class.se: Fix a bug where highest thread id was reported as current number of threads. Support both current thread count and contributing thread count. Add lwp_max variable. Modified: trunk/orca/lib/SE/3.2.1/orca_process_class.se ============================================================================== --- trunk/orca/lib/SE/3.2.1/orca_process_class.se (original) +++ trunk/orca/lib/SE/3.2.1/orca_process_class.se Fri Nov 19 07:10:42 2004 @@ -211,6 +211,7 @@ ulong icontexts; /* in-ditto */ ulong charios; /* characters in and out/interval */ ulong lwp_count; /* number of lwps for the process */ + ulong lwp_max; /* number of contributing lwps for the process */ int uid; /* current uid */ long ppid; /* parent pid */ int bindpset; /* processor set binding */ @@ -537,6 +538,7 @@ rpi.n_pr_time = PS.pr_time; rpi.o_pr_ctime = rpi.n_pr_ctime; rpi.n_pr_ctime = PS.pr_ctime; + rpi.lwp_count = PS.pr_nlwp; rpi.gencnt = gen; struct_empty(rpi,pp); nproc++; @@ -789,7 +791,8 @@ priority = rpi.pr_pri; niceness = rpi.pr_nice; sched_class = rpi.pr_clname; - lwp_count = NU.pr_count; + lwp_max = NU.pr_count; + lwp_count = rpi.lwp_count; ppid = rpi.pr_ppid; bindpset = rpi.pr_bindpset; fname = rpi.pr_fname; From dmberezin at hotmail.com Fri Nov 19 07:20:38 2004 From: dmberezin at hotmail.com (dmberezin at hotmail.com) Date: Fri, 19 Nov 2004 07:20:38 -0800 Subject: [Orca-checkins] r407 - in trunk/orca/lib/SE: 3.2.1 3.3 Message-ID: <200411191520.iAJFKcgr028637@gw.orcaware.com> Author: dmberezin at hotmail.com Date: Fri Nov 19 07:18:44 2004 New Revision: 407 Added: trunk/orca/lib/SE/3.2.1/tapeinfo.se trunk/orca/lib/SE/3.3/tapeinfo.se Log: Add a copy of tapeinfo.se to all versions of SE Toolkit * lib/SE/3.2.1/tapeinfo.se * lib/SE/3.3/tapeinfo.se Add a copy of tapeinfo.se from lib/SE/3.3.1 to these versions. Tapeinfo.se is based on diskinfo.se. The version of diskinfo.se is the same in SE Toolkit versions 3.2.1, 3.3, and 3.3.1. Added: trunk/orca/lib/SE/3.2.1/tapeinfo.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.2.1/tapeinfo.se Fri Nov 19 07:18:44 2004 @@ -0,0 +1,277 @@ +// +// Copyright (c) 1993-2001 by Richard Pettit. All rights reserved. +// +// Some of this work was derived from include files containing the following +// copyrights. +// +// Copyright (c) 1986-1994 by Sun Microsystems, Inc. +// Copyright (c) 1983-1989 by AT&T +// Copyright (c) 1980-1993 by The Regents of the University of California. +// +// The work as a whole represents unique intellectual property and is +// copyright by Richard Pettit as shown on the first line. +// + +#ifndef _TAPEINFO_SE_ +#define _TAPEINFO_SE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PATH_TO_INST "/etc/path_to_inst" + +// sterr is not defined in kstat.se, so define here +kstat struct "sterr:" ks_sterr { + int number$; // linear counter + string name$; // name of error + int instance$; // instance number + + uint64_t "Soft Errors"; + uint64_t "Hard Errors"; + uint64_t "Transport Errors"; + string Vendor; + string Product; + string Revision; + string "Serial No"; +}; + +struct tape_info_t { + string short_name; + string long_name; + ks_sterr errors; +}; + +// this is a global array to keep similarity with diskinfo.se +// use functions provided below as access methods + +tape_info_t GLOBAL_tape_info[]; +int GLOBAL_tapeinfo_size = 1; +ulong_t GLOBAL_tapeinfo_short_tree; +ulong_t GLOBAL_tapeinfo_long_tree; + +int tapeinfo_inst_initialized; // set when data exists + +ks_sterr +find_tape_error(string name) +{ + ks_sterr sterr; + string short_name; + + if (name =~ "^st.*") { + sterr.number$ = 0; + for(refresh$(sterr); sterr.number$ != -1; sterr.number$++,refresh$(sterr)) { + short_name = sterr.name$; + strtok(short_name, ","); + if (short_name == name) { + break; + } + } + return sterr; + } +} + +int +setup_tapeinfo_inst() // return 1 if OK, 0 if not +{ + char buf[BUFSIZ]; + char points_at[MAXNAMELEN]; + string p; + string full; + string path; + string tape_dirs[2] = { "/dev/rmt", nil }; + int count = 0; + int i; + int n; + ulong ld; + ulong dirp; + ulong input; + dirent_t dp; + ulong_t path_tree; + ulong_t np; + + if (tapeinfo_inst_initialized == 1) { + return 1; + } + + path_tree = str2int_init(); + if (path_tree == 0) { + return 0; + } + + // load up the tree with the paths and quit traversing path_to_inst + input = fopen(PATH_TO_INST, "r"); + if (input == 0) { + avlfree(path_tree); + return 0; + } + while (fgets(buf, sizeof(buf), input) != nil) { + if ((buf[0] != '#') && (buf[0] != '\n')) { + p = strtok(buf, " "); + n = atoi(strtok(nil, " ")); + path = strtok(p, "\""); + + if (str2int_put(path_tree, path, n) == -1) { + fclose(input); + avlfree(path_tree); + return 0; + } + } + } + fclose(input); + + // create the global tape info array + GLOBAL_tape_info = new tape_info_t[GLOBAL_tapeinfo_size]; + + // scan /dev/rmt and insert tape entries + for (i=0; tape_dirs[i] != nil; i++) { + dirp = opendir(tape_dirs[i]); + if (dirp == 0) { + if (i > 0) { + // first is /dev/rmt + break; + } + avlfree(path_tree); + return 0; + } + + for (ld = readdir(dirp); ld != 0; ld = readdir(dirp)) { + // grow the array if needed + if (count == GLOBAL_tapeinfo_size) { + GLOBAL_tapeinfo_size += 1; + GLOBAL_tape_info = renew GLOBAL_tape_info[GLOBAL_tapeinfo_size]; + } + dp = *((dirent_t *) ld); + + // skip . and .. + if (dp.d_name == "." || dp.d_name == "..") { + continue; + } + + // skip everything but raw devices + if ( isdigit(dp.d_name[strlen(dp.d_name)-1]) == 0 ) { + continue; + } + + // read the link + full = sprintf("%s/%s", tape_dirs[i], dp.d_name); + + n = readlink(full, points_at, sizeof(points_at)); + if (n == -1) { + closedir(dirp); + avlfree(path_tree); + return 0; + } + points_at[n] = '\0'; + + // chop off the :a at the end + strcpy(strrchr(points_at, ':'), ""); + + // hack off ../../devices from the start + sscanf(points_at, "../../devices%s", &points_at); + + // hack off /dev/ from the start + // long name is the rmt/ + sscanf(full, "/dev/%s", &buf); + GLOBAL_tape_info[count].long_name = buf; + + GLOBAL_tape_info[count].short_name = nil; + + // construct the short name + if ((np = str2int_get(path_tree, points_at)) != 0) { + n = ((int) *((ulong_t *) np)); + p = strrchr(points_at, '/'); + p = strtok(p, "/"); + p = strtok(p, "@"); + GLOBAL_tape_info[count].short_name = sprintf("%s%d", p, n); + } + + // hard luck, can't find this device + if (GLOBAL_tape_info[count].short_name == nil) { + continue; + } + + // squirrel this away while we're at it + GLOBAL_tape_info[count].errors = + find_tape_error(GLOBAL_tape_info[count].short_name); + + count++; + } + closedir(dirp); + } + + // tree the names for fast lookup + GLOBAL_tapeinfo_short_tree = str2int_init(); + GLOBAL_tapeinfo_long_tree = str2int_init(); + if ((GLOBAL_tapeinfo_short_tree == 0) || (GLOBAL_tapeinfo_long_tree == 0)) { + return 0; + } + for(i=0; i= 0 && i < GLOBAL_tapeinfo_size) { + return GLOBAL_tape_info[i]; + } else { + no_info.short_name = name; + no_info.long_name = name; + return no_info; + } +} + +#endif Added: trunk/orca/lib/SE/3.3/tapeinfo.se ============================================================================== --- (empty file) +++ trunk/orca/lib/SE/3.3/tapeinfo.se Fri Nov 19 07:18:44 2004 @@ -0,0 +1,277 @@ +// +// Copyright (c) 1993-2001 by Richard Pettit. All rights reserved. +// +// Some of this work was derived from include files containing the following +// copyrights. +// +// Copyright (c) 1986-1994 by Sun Microsystems, Inc. +// Copyright (c) 1983-1989 by AT&T +// Copyright (c) 1980-1993 by The Regents of the University of California. +// +// The work as a whole represents unique intellectual property and is +// copyright by Richard Pettit as shown on the first line. +// + +#ifndef _TAPEINFO_SE_ +#define _TAPEINFO_SE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PATH_TO_INST "/etc/path_to_inst" + +// sterr is not defined in kstat.se, so define here +kstat struct "sterr:" ks_sterr { + int number$; // linear counter + string name$; // name of error + int instance$; // instance number + + uint64_t "Soft Errors"; + uint64_t "Hard Errors"; + uint64_t "Transport Errors"; + string Vendor; + string Product; + string Revision; + string "Serial No"; +}; + +struct tape_info_t { + string short_name; + string long_name; + ks_sterr errors; +}; + +// this is a global array to keep similarity with diskinfo.se +// use functions provided below as access methods + +tape_info_t GLOBAL_tape_info[]; +int GLOBAL_tapeinfo_size = 1; +ulong_t GLOBAL_tapeinfo_short_tree; +ulong_t GLOBAL_tapeinfo_long_tree; + +int tapeinfo_inst_initialized; // set when data exists + +ks_sterr +find_tape_error(string name) +{ + ks_sterr sterr; + string short_name; + + if (name =~ "^st.*") { + sterr.number$ = 0; + for(refresh$(sterr); sterr.number$ != -1; sterr.number$++,refresh$(sterr)) { + short_name = sterr.name$; + strtok(short_name, ","); + if (short_name == name) { + break; + } + } + return sterr; + } +} + +int +setup_tapeinfo_inst() // return 1 if OK, 0 if not +{ + char buf[BUFSIZ]; + char points_at[MAXNAMELEN]; + string p; + string full; + string path; + string tape_dirs[2] = { "/dev/rmt", nil }; + int count = 0; + int i; + int n; + ulong ld; + ulong dirp; + ulong input; + dirent_t dp; + ulong_t path_tree; + ulong_t np; + + if (tapeinfo_inst_initialized == 1) { + return 1; + } + + path_tree = str2int_init(); + if (path_tree == 0) { + return 0; + } + + // load up the tree with the paths and quit traversing path_to_inst + input = fopen(PATH_TO_INST, "r"); + if (input == 0) { + avlfree(path_tree); + return 0; + } + while (fgets(buf, sizeof(buf), input) != nil) { + if ((buf[0] != '#') && (buf[0] != '\n')) { + p = strtok(buf, " "); + n = atoi(strtok(nil, " ")); + path = strtok(p, "\""); + + if (str2int_put(path_tree, path, n) == -1) { + fclose(input); + avlfree(path_tree); + return 0; + } + } + } + fclose(input); + + // create the global tape info array + GLOBAL_tape_info = new tape_info_t[GLOBAL_tapeinfo_size]; + + // scan /dev/rmt and insert tape entries + for (i=0; tape_dirs[i] != nil; i++) { + dirp = opendir(tape_dirs[i]); + if (dirp == 0) { + if (i > 0) { + // first is /dev/rmt + break; + } + avlfree(path_tree); + return 0; + } + + for (ld = readdir(dirp); ld != 0; ld = readdir(dirp)) { + // grow the array if needed + if (count == GLOBAL_tapeinfo_size) { + GLOBAL_tapeinfo_size += 1; + GLOBAL_tape_info = renew GLOBAL_tape_info[GLOBAL_tapeinfo_size]; + } + dp = *((dirent_t *) ld); + + // skip . and .. + if (dp.d_name == "." || dp.d_name == "..") { + continue; + } + + // skip everything but raw devices + if ( isdigit(dp.d_name[strlen(dp.d_name)-1]) == 0 ) { + continue; + } + + // read the link + full = sprintf("%s/%s", tape_dirs[i], dp.d_name); + + n = readlink(full, points_at, sizeof(points_at)); + if (n == -1) { + closedir(dirp); + avlfree(path_tree); + return 0; + } + points_at[n] = '\0'; + + // chop off the :a at the end + strcpy(strrchr(points_at, ':'), ""); + + // hack off ../../devices from the start + sscanf(points_at, "../../devices%s", &points_at); + + // hack off /dev/ from the start + // long name is the rmt/ + sscanf(full, "/dev/%s", &buf); + GLOBAL_tape_info[count].long_name = buf; + + GLOBAL_tape_info[count].short_name = nil; + + // construct the short name + if ((np = str2int_get(path_tree, points_at)) != 0) { + n = ((int) *((ulong_t *) np)); + p = strrchr(points_at, '/'); + p = strtok(p, "/"); + p = strtok(p, "@"); + GLOBAL_tape_info[count].short_name = sprintf("%s%d", p, n); + } + + // hard luck, can't find this device + if (GLOBAL_tape_info[count].short_name == nil) { + continue; + } + + // squirrel this away while we're at it + GLOBAL_tape_info[count].errors = + find_tape_error(GLOBAL_tape_info[count].short_name); + + count++; + } + closedir(dirp); + } + + // tree the names for fast lookup + GLOBAL_tapeinfo_short_tree = str2int_init(); + GLOBAL_tapeinfo_long_tree = str2int_init(); + if ((GLOBAL_tapeinfo_short_tree == 0) || (GLOBAL_tapeinfo_long_tree == 0)) { + return 0; + } + for(i=0; i= 0 && i < GLOBAL_tapeinfo_size) { + return GLOBAL_tape_info[i]; + } else { + no_info.short_name = name; + no_info.long_name = name; + return no_info; + } +} + +#endif