caddr_t get_process_info(struct system_info * si, struct process_select * sel, int x, char *conninfo) { register int i; register int total_procs; register int active_procs; register struct macos_proc **prefp; register struct macos_proc *pp; register struct kinfo_proc *pp2; /* * these are copied out of sel for speed */ int show_idle; int show_system; int show_uid; int show_command; /* begin mucking */ /* kproc_list = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); */ PGconn *pgconn; PGresult *pgresult = NULL; nproc = 0; pgconn = connect_to_db(conninfo); if (pgconn != NULL) { pgresult = pg_processes(pgconn); nproc = PQntuples(pgresult); pbase = (struct kinfo_proc *) malloc(sizeof(struct kinfo_proc *)); } PQfinish(pgconn); int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; size_t len = nproc; struct kinfo_proc *buffer; buffer = (struct kinfo_proc *) malloc( len * sizeof(struct kinfo_proc) ); for (i = 0; i < nproc ; i++) { size_t size = sizeof(struct kinfo_proc); mib[3] = atoi(PQgetvalue(pgresult, i, 0)); if (sysctl(mib, sizeof(mib)/sizeof(int), &buffer[i], &size, NULL, 0) == -1) { perror("sysctl atoi loop"); return "1"; } } kproc_list = buffer; len = nproc; /* end selena's messing about */ if (nproc > onproc) { proc_list = (struct macos_proc *) realloc(proc_list, sizeof(struct macos_proc) * nproc); proc_ref = (struct macos_proc **) realloc(proc_ref, sizeof(struct macos_proc *) * (onproc = nproc)); } if (proc_ref == NULL || proc_list == NULL || kproc_list == NULL) { puke("error: out of memory (%s)", strerror(errno)); return (NULL); } /* * now, our task is to build the array of information we need to function * correctly. This involves setting a pointer to each real kinfo_proc * structure returned by kvm_getprocs() in addition to getting the mach * information for each of those processes. */ for (pp2 = kproc_list, i = 0; i < nproc; pp2++, i++) { /* * first, we set the pointer to the reference in the kproc list. */ proc_list[i].kproc = pp2; /* * then, we load all of the task info for the process */ if (PP(pp2, p_stat) != SZOMB) { load_thread_info(&proc_list[i]); } } /* get a pointer to the states summary array */ si->procstates = process_states; /* set up flags which define what we are going to select */ show_idle = sel->idle; show_uid = sel->uid != -1; show_command = sel->command != NULL; show_fullcmd = sel->fullcmd; /* count up process states and get pointers to interesting procs */ total_procs = 0; active_procs = 0; memset((char *) process_states, 0, sizeof(process_states)); prefp = proc_ref; for (pp = proc_list, i = 0; i < nproc; pp++, i++) { /* * Place pointers to each valid proc structure in proc_ref[]. Process * slots that are actually in use have a non-zero status field. * Processes with P_SYSTEM set are system processes---these get * ignored unless show_sysprocs is set. */ if (MPP(pp, p_stat) != 0 && (show_system || ((MPP(pp, p_flag) & P_SYSTEM) == 0))) { total_procs++; process_states[(unsigned char) MPP(pp, p_stat)]++; if ((MPP(pp, p_stat) != SZOMB) && (show_idle || (MPP(pp, p_pctcpu) != 0) || (MPP(pp, p_stat) == SRUN)) && (!show_uid || MEP(pp, e_pcred.p_ruid) == (uid_t) sel->uid)) { *prefp++ = pp; active_procs++; } } } /* * if requested, sort the "interesting" processes */ qsort((char *) proc_ref, active_procs, sizeof(struct macos_proc *), proc_compare); /* remember active and total counts */ si->p_total = total_procs; si->p_active = pref_len = active_procs; /* pass back a handle */ handle.next_proc = proc_ref; handle.remaining = active_procs; return ((caddr_t) & handle); }
caddr_t get_process_info(struct system_info *si, struct process_select *sel, int compare_index, char *conninfo) { int show_idle, show_system, show_threads, show_uid, show_cmd; int total_procs, active_procs; struct kinfo_proc2 **prefp, *pp; int mib[6]; size_t size; int i; PGconn *pgconn; PGresult *pgresult = NULL; size = (size_t) sizeof(struct kinfo_proc2); mib[0] = CTL_KERN; mib[1] = KERN_PROC2; mib[2] = KERN_PROC_PID; mib[4] = sizeof(struct kinfo_proc2); mib[5] = 1; nproc = 0; pgconn = connect_to_db(conninfo); if (pgconn != NULL) { pgresult = pg_processes(pgconn); nproc = PQntuples(pgresult); pbase = (struct kinfo_proc2 *) realloc(pbase, sizeof(struct kinfo_proc2 *) * nproc); } PQfinish(pgconn); if (nproc > onproc) pref = (struct kinfo_proc2 **)realloc(pref, sizeof(struct kinfo_proc2 *) * (onproc = nproc)); if (pref == NULL) { warnx("Out of memory."); quit(23); } /* get a pointer to the states summary array */ si->procstates = process_states; /* set up flags which define what we are going to select */ show_idle = sel->idle; show_uid = sel->uid != (uid_t)-1; show_cmd = sel->command != NULL; /* count up process states and get pointers to interesting procs */ total_procs = 0; active_procs = 0; memset((char *) process_states, 0, sizeof(process_states)); prefp = pref; i = 0; for (pp = pbase; pp < &pbase[nproc]; pp++) { mib[3] = atoi(PQgetvalue(pgresult, i, 0)); if (sysctl(mib, 6, &pbase[i++], &size, NULL, 0) != 0) { printf("\n\ndoh %d\n", errno); perror("\n\ndoh"); exit(1); } /* * Place pointers to each valid proc structure in pref[]. * Process slots that are actually in use have a non-zero * status field. Processes with P_SYSTEM set are system * processes---these get ignored unless show_system is set. */ if (pp->p_stat != 0 && (show_system || (pp->p_flag & P_SYSTEM) == 0) && (show_threads || (pp->p_flag & P_THREAD) == 0)) { total_procs++; process_states[(unsigned char) pp->p_stat]++; if (pp->p_stat != SZOMB && (show_idle || pp->p_pctcpu != 0 || pp->p_stat == SRUN) && (!show_uid || pp->p_ruid == sel->uid) && (!show_cmd || strstr(pp->p_comm, sel->command))) { *prefp++ = pp; active_procs++; } } } /* if requested, sort the "interesting" processes */ if (compare_index != NULL) qsort((char *) pref, active_procs, sizeof(struct kinfo_proc2 *), proc_compares[compare_index]); /* remember active and total counts */ si->p_total = total_procs; si->p_active = pref_len = active_procs; /* pass back a handle */ handle.next_proc = pref; handle.remaining = active_procs; return ((caddr_t) & handle); }
caddr_t get_process_info(struct system_info * si, struct process_select * sel, int compare_index, char *conninfo, int mode) { struct timeval thistime; double timediff, alpha, beta; struct top_proc *proc; pid_t pid; unsigned long now; unsigned long elapsed; int i; /* calculate the time difference since our last check */ gettimeofday(&thistime, 0); if (lasttime.tv_sec) { timediff = ((thistime.tv_sec - lasttime.tv_sec) + (thistime.tv_usec - lasttime.tv_usec) * 1e-6); } else { timediff = 0; } lasttime = thistime; /* round current time to a second */ now = (unsigned long) thistime.tv_sec; if (thistime.tv_usec >= 500000) { now++; } /* calculate constants for the exponental average */ if (timediff > 0.0 && timediff < 30.0) { alpha = 0.5 * (timediff / 30.0); beta = 1.0 - alpha; } else { alpha = beta = 0.5; } timediff *= HZ; /* convert to ticks */ /* mark all hash table entries as not seen */ for (i = 0; i < HASH_SIZE; ++i) { for (proc = ptable[i]; proc; proc = proc->next) { proc->state = 0; } } /* read the process information */ { int total_procs = 0; struct top_proc **active; int show_idle = sel->idle; int show_uid = sel->uid != -1; int i; int rows; PGconn *pgconn; PGresult *pgresult = NULL; memset(process_states, 0, sizeof(process_states)); pgconn = connect_to_db(conninfo); if (pgconn != NULL) { pgresult = pg_processes(pgconn); rows = PQntuples(pgresult); } else { rows = 0; } for (i = 0; i < rows; i++) { char *procpid = PQgetvalue(pgresult, i, 0); struct top_proc *pp; unsigned long otime; pid = atoi(procpid); /* look up hash table entry */ proc = pp = ptable[HASH(pid)]; while (proc && proc->pid != pid) { proc = proc->next; } /* if we came up empty, create a new entry */ if (proc == NULL) { proc = new_proc(); proc->pid = pid; proc->next = pp; ptable[HASH(pid)] = proc; proc->time = 0; proc->wcpu = 0; } otime = proc->time; read_one_proc_stat(pid, proc, sel); if (sel->fullcmd == 2) update_procname(proc, PQgetvalue(pgresult, i, 1)); if (proc->state == 0) continue; total_procs++; process_states[proc->state]++; if (timediff > 0.0) { if ((proc->pcpu = (proc->time - otime) / timediff) < 0.0001) { proc->pcpu = 0; } proc->wcpu = proc->pcpu * alpha + proc->wcpu * beta; } else if ((elapsed = (now - boottime) * HZ - proc->start_time) > 0) { /* * What's with the noop statement? if ((proc->pcpu = * (double)proc->time / (double)elapsed) < 0.0001) { * proc->pcpu; } */ proc->wcpu = proc->pcpu; } else { proc->wcpu = proc->pcpu = 0.0; } } if (pgresult != NULL) PQclear(pgresult); PQfinish(pgconn); /* make sure we have enough slots for the active procs */ if (activesize < total_procs) { pactive = (struct top_proc **) realloc(pactive, sizeof(struct top_proc *) * total_procs); activesize = total_procs; } /* set up the active procs and flush dead entries */ active = pactive; for (i = 0; i < HASH_SIZE; i++) { struct top_proc *last; struct top_proc *ptmp; last = NULL; proc = ptable[i]; while (proc != NULL) { if (proc->state == 0) { ptmp = proc; if (last) { proc = last->next = proc->next; } else { proc = ptable[i] = proc->next; } free_proc(ptmp); } else { if ((show_idle || proc->state == 1 || proc->pcpu) && (!show_uid || proc->uid == sel->uid)) { *active++ = proc; last = proc; } proc = proc->next; } } } si->p_active = active - pactive; si->p_total = total_procs; si->procstates = process_states; } /* if requested, sort the "active" procs */ if (si->p_active) { if (mode == MODE_IO_STATS) { qsort(pactive, si->p_active, sizeof(struct top_proc *), io_compares[compare_index]); } else { qsort(pactive, si->p_active, sizeof(struct top_proc *), proc_compares[compare_index]); } } /* don't even pretend that the return value thing here isn't bogus */ nextactive = pactive; return (caddr_t) 0; }