--- asmon/asmon.c.orig Sun Jun 27 15:38:26 1999 +++ asmon/asmon.c Mon Sep 27 19:58:05 1999 @@ -21,6 +21,19 @@ #include "asmon-master.xpm" #include "asmon-mask.xbm" +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + #ifdef __solaris__ #include #endif @@ -47,6 +60,39 @@ #define B_RED (1) #define B_GREEN (2) +#ifdef __FreeBSD__ +kvm_t *kd; + +#define SVAR(var) __STRING(var) /* to force expansion */ +#define KGET(idx, var) \ + KGET1(idx, &var, sizeof(var), SVAR(var)) +#define KGET1(idx, p, s, msg) \ + KGET2(nl[idx].n_value, p, s, msg) +#define KGET2(addr, p, s, msg) \ + if (kvm_read(kd, (u_long)(addr), p, s) != s) \ + warnx("cannot read %s: %s", msg, kvm_geterr(kd)) + +struct nlist nl[] = { +#define VM_SWAPLIST 0 + { "_swaplist" },/* list of free swap areas */ +#define VM_SWDEVT 1 + { "_swdevt" }, /* list of swap devices and sizes */ +#define VM_NSWAP 2 + { "_nswap" }, /* size of largest swap device */ +#define VM_NSWDEV 3 + { "_nswdev" }, /* number of swap devices */ +#define VM_DMMAX 4 + { "_dmmax" }, /* maximum size of a swap block */ +#define X_CNT 5 + { "_cnt" }, +#define X_BUFSPACE 6 + { "_bufspace" }, /* K in buffer cache */ +#define X_CP_TIME 7 + { "_cp_time" }, + { "" } +}; +#endif + /* Evil globals I haven't removed yet */ long last_pageins=0, last_pageouts=0; long last_swapins=0, last_swapouts=0; @@ -77,6 +123,11 @@ float DrawMemSwap(float total, int allmem); #endif +#ifdef __FreeBSD__ +void open_kvm(void); +void close_kvm(void); +#endif + int main(int argc, char *argv[]) { FILE *fp; @@ -151,7 +202,17 @@ #endif /* Open 64x64 window */ openXwindow(argc, argv, asmon_master_xpm, asmon_mask_bits, asmon_mask_width, asmon_mask_height); + +#ifdef __FreeBSD__ + open_kvm(); +#endif + asmon_routine(Xpid, allmem); + +#ifdef __FreeBSD__ + close_kvm(); +#endif + return(0); } @@ -160,7 +221,11 @@ void usage(void) { fprintf(stderr, "\nasmon %s - by Brad Hall (brad@rio.dhs.org)\n\t\toriginally based on Timecop's wmcpu\n\n", ASMON_VERSION); fprintf(stderr, "The top bar: left is the CPU usage, right is the load average\n"); +#ifdef __FreeBSD__ + fprintf(stderr, "The middle bar: left memory usage devided by ticks into active, inactive,\n\t\twired, cached + buffers, respectively, and the number\n\t\tof megs used\n"); +#else fprintf(stderr, "The middle bar: left memory usage devided by ticks into shared, buffers, and\n\t\t cached, respectively, and the number of megs used\n"); +#endif fprintf(stderr, "The lower bar: the left swap usage and the number of megs swappedd avg\n"); fprintf(stderr, "The bottom: the left is a set of LED's marking page's and swap's, the right is\n\t\t a bar representing the amount of memory that the X server \n\t\t is taking up, and the exact megs\n\n usage:\n"); fprintf(stderr, "\t-display \n"); @@ -168,8 +233,13 @@ fprintf(stderr, "\t-v\tprint the version number\n"); #ifndef __solaris__ fprintf(stderr, "\t-u\tforce asmon to show uptime, rather than X mem use\n"); +#else +#ifdef __FreeBSD__ + fprintf(stderr, "\t-m\tmake asmon show only active mem\n"); +#else fprintf(stderr, "\t-m\tmake asmon show only shared mem, like most other mem meters\n"); #endif +#endif #ifdef EXEC_ON_CLICK fprintf(stderr, "\t-e cmd\texecute 'cmd' on mouse click\n"); #endif @@ -323,12 +393,13 @@ /* CPU Usage Meter */ void DrawCPU(void) { - FILE *fp; static float cpustat[4]; /* remember the statistics read last time */ float fields[4], info[4], cputotal=0.0; long pageins=0, pageouts=0, swapins=0, swapouts=0; - char buf[128]; int i; +#ifndef __FreeBSD__ + char buf[128]; + FILE *fp; if( (fp = fopen("/proc/stat", "r")) != NULL) { @@ -345,7 +416,15 @@ sscanf(buf, "swap %ld %ld", &swapins, &swapouts); } fclose(fp); - +#else + { + long cputime[4]; + struct vmmeter sum; + + kvm_read(kd, nl[X_CP_TIME].n_value, &cputime, sizeof(cputime)); + for(i = 0; i < 4; i++) + info[i] = (float)cputime[i]; +#endif // Calculate CPU stuff for(i = 0; i < 4; i++) { @@ -365,6 +444,13 @@ } // Page In/Out +#ifdef __FreeBSD__ + KGET(X_CNT, sum); + pageins = sum.v_vnodepgsin; + pageouts = sum.v_vnodepgsout; + swapins = sum.v_swappgsin; + swapouts = sum.v_swappgsout; +#endif if (pageins > last_pageins) { DrawLite(B_RED, 5, 48); @@ -414,12 +500,19 @@ #ifdef __solaris__ if (getLoad(&ftmp) != -1) { -#else +#else +#ifndef __FreeBSD__ FILE *fp; if( (fp = fopen("/proc/loadavg", "r")) != NULL) { fscanf(fp, "%f", &ftmp); fclose(fp); +#else + { + double avg[1]; + getloadavg(avg, 1); + ftmp = (float)avg[0]; +#endif #endif if(oldv != ftmp) { @@ -540,6 +633,7 @@ /* Mem/Swap Meter */ float DrawMemSwap(float total, int allmem) { +#ifndef __FreeBSD__ FILE *fp; if( (fp = fopen("/proc/meminfo", "r")) != NULL) { @@ -553,6 +647,112 @@ fgets(junk, 80, fp); fscanf(fp, "Mem: %f %f %f %f %f %f\nSwap: %f %f %f", &total, &used, &freeM, &shared, &buffers, &cached, &swaptotal, &swapused, &swapfreeM); fclose(fp); +#else + { + static float stotal=0.0, sshared=0.0, sbuffers=0.0, scached=0.0; + float used, active, inactive, wired, buffers, cached, swaptotal, + swapused, shared; + unsigned long MEMactive,MEMinactive,MEMwired,MEMbuff,MEMcach, MEMswap; + int tempy, tempa; + int nswap, nswdev, dmmax; + int i, avail, nfree, kmemused, bufspace = 0; + struct swdevt *sw; + long *perdev; + struct vmmeter sum; + struct rlist head; + struct rlisthdr swaplist; + struct rlist *swapptr; + u_long ptr; + + KGET(VM_NSWAP, nswap); + KGET(VM_NSWDEV, nswdev); + KGET(VM_DMMAX, dmmax); + KGET1(VM_SWAPLIST, &swaplist, sizeof swaplist, "swaplist"); + if ((sw = (struct swdevt*)malloc(nswdev * sizeof(*sw))) == NULL || + (perdev = (long *)malloc(nswdev * sizeof(*perdev))) == NULL) + errx(1, "malloc"); + KGET1(VM_SWDEVT, &ptr, sizeof ptr, "swdevt"); + KGET2(ptr, sw, nswdev * sizeof(*sw), "*swdevt"); + + /* Count up swap space. */ + nfree = 0; + memset(perdev, 0, nswdev * sizeof(*perdev)); + swapptr = swaplist.rlh_list; + while (swapptr) { + int top, bottom, next_block; + + KGET2(swapptr, &head, sizeof(struct rlist), "swapptr"); + + top = head.rl_end; + bottom = head.rl_start; + + nfree += top - bottom + 1; + + /* + * Swap space is split up among the configured disks. + * + * For interleaved swap devices, the first dmmax blocks + * of swap space some from the first disk, the next dmmax + * blocks from the next, and so on up to nswap blocks. + * + * The list of free space joins adjacent free blocks, + * ignoring device boundries. If we want to keep track + * of this information per device, we'll just have to + * extract it ourselves. + */ + while (top / dmmax != bottom / dmmax) { + next_block = ((bottom + dmmax) / dmmax); + perdev[(bottom / dmmax) % nswdev] += + next_block * dmmax - bottom; + bottom = next_block * dmmax; + } + perdev[(bottom / dmmax) % nswdev] += + top - bottom + 1; + + swapptr = head.rl_next; + } + + avail = 0; + for (i = 0; i < nswdev; i++) { + int xsize, xfree; + + /* + * Don't report statistics for partitions which have not + * yet been activated via swapon(8). + */ + if (!(sw[i].sw_flags & SW_FREED)) + continue; + + /* The first dmmax is never allocated to avoid trashing of + * disklabels + */ + xsize = sw[i].sw_nblks - dmmax; + xfree = perdev[i]; + kmemused = xsize - xfree; + avail += xsize; + } + + /* + * If only one partition has been set up via swapon(8), we don't + * need to bother with totals. + */ + kmemused = avail - nfree; + KGET(X_CNT, sum); + KGET(X_BUFSPACE, bufspace); + free(sw); + free(perdev); + + total = sum.v_page_size * sum.v_page_count; + cached = sum.v_page_size * sum.v_cache_count; + used = sum.v_page_size * (sum.v_page_count - sum.v_free_count); + buffers = bufspace; + active = sum.v_page_size * sum.v_active_count; + inactive = sum.v_page_size * sum.v_inactive_count; + wired = sum.v_page_size * sum.v_wire_count; + + swaptotal = avail * 512; + swapused = kmemused * 512; +#endif if ( allmem == 1) { /* All mem areas */ @@ -561,11 +761,23 @@ stotal = total; sshared = shared; sbuffers = buffers; scached = cached; if ( (total/101048576) >= 1) { +#ifdef __FreeBSD__ + MEMactive=(active/total)*27; + MEMinactive=(inactive/total)*27; + MEMwired=(wired/total)*27; +#else MEMshar=(shared/total)*27; +#endif MEMbuff=(buffers/total)*27; MEMcach=(cached/total)*27; } else { +#ifdef __FreeBSD__ + MEMactive=(active/total)*33; + MEMinactive=(inactive/total)*33; + MEMwired=(wired/total)*33; +#else MEMshar=(shared/total)*33; +#endif MEMbuff=(buffers/total)*33; MEMcach=(cached/total)*33; } @@ -579,9 +791,15 @@ copyXPMArea(3,75,((used/total)*34),9,5,19); } // Separators +#ifdef __FreeBSD__ + copyXPMArea(15,105,1,9,5+MEMactive,19); + copyXPMArea(15,105,1,9,6+MEMactive+MEMinactive,19); + copyXPMArea(15,105,1,9,7+MEMactive+MEMinactive+MEMwired,19); +#else copyXPMArea(15,105,1,9,5+MEMshar,19); copyXPMArea(15,105,1,9,7+MEMshar+MEMbuff,19); copyXPMArea(15,105,(36-(used/total)*34),9,(5+(used/total)*34),19); +#endif // Numbers tempa=used/1048576; tempy=tempa%10; @@ -601,6 +819,16 @@ if(stotal != total || sshared != shared) { stotal = total; sshared = shared; sbuffers = buffers; scached = cached; +#ifdef __FreeBSD__ + if ( (total/101048576) >= 1) { + MEMactive=(active/total)*27; + } else { + MEMactive=(active/total)*35; + } + // Bar + copyXPMArea(3,75,MEMactive,9,5,19); + copyXPMArea(3,102,(36-(active/total)*36),9,(5+(active/total)*36),19) ; +#else if ( (total/101048576) >= 1) { MEMshar=(shared/total)*27; } else { @@ -609,8 +837,13 @@ // Bar copyXPMArea(3,75,MEMshar,9,5,19); copyXPMArea(15,105,(36-(shared/total)*36),9,(5+(shared/total)*36),19); +#endif // Numbers +#ifdef __FreeBSD__ + tempa=active/1048576; +#else tempa=shared/1048576; +#endif tempy=tempa%10; copyXPMArea(3+(tempy*6),66,6,9,50,19); tempy=(tempa/10)%10; @@ -662,10 +895,11 @@ /* X Mem Usage */ void DrawXmem(int Xpid, float total) { - FILE *fp; - char buf[128], XFileName[256]; float ratio; long old_Xsize=-1, Xsize=0; +#ifndef __FreeBSD__ + FILE *fp; + char buf[128], XFileName[256]; sprintf(XFileName, "/proc/%d/status", Xpid); @@ -676,6 +910,15 @@ if (strstr(buf, "VmSize")) sscanf(buf, "VmSize: %ld", &Xsize); } +#else + { + struct kinfo_proc *kproc; + int kcnt; + + kproc = kvm_getprocs(kd, KERN_PROC_PID, Xpid, &kcnt); + + Xsize = kproc->kp_eproc.e_vm.vm_map.size / 1024; +#endif if(old_Xsize!=Xsize) { int tempy, tempa; @@ -692,7 +935,9 @@ copyXPMArea(3,84,((ratio)*22),11,18,47); copyXPMArea(15,105,(23-((ratio)*22)),11,(18+(ratio*22)),47); } +#ifndef __FreeBSD__ fclose(fp); +#endif } } @@ -713,10 +958,28 @@ pUtmp = getutid(&idUtmp); upt = (time(0) - pUtmp->ut_time); #else +#ifndef __FreeBSD__ FILE *fp; if( (fp = fopen("/proc/uptime", "r")) != NULL) fscanf(fp, "%d",&upt); fclose(fp); +#else + int mib[2]; + struct timeval boottime; + size_t bt_size; + + bt_size = sizeof(boottime); + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + + if (sysctl(mib, 2, &boottime, &bt_size, NULL, 0) != -1 && + boottime.tv_sec != 0) { + upt = time(NULL) - boottime.tv_sec; + upt += 30; /* top(1) does this ???? */ + } else { + upt = 0; + } +#endif #endif mins=(upt/60)%60; hours=(upt/3600)%24; @@ -777,6 +1040,31 @@ break; } +} + +void +open_kvm() +{ + if (kd == 0) { + kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, 0); + if (kd != NULL) { + if (kvm_nlist(kd, nl) < 0) { + errx(1, "kvm_nlist: %s", kvm_geterr(kd)); + } + if (nl[0].n_type == 0) { + errx(1, "no namelist"); + } + } else { + warnx("kvm not available"); + } + } +} + +void +close_kvm() +{ + kvm_close(kd); + kd = NULL; } /* EOF */