static gboolean cpu_update(Monitor * c) { static struct cpu_stat previous_cpu_stat = { 0, 0, 0, 0 }; if ((c->stats != NULL) && (c->pixmap != NULL)) { /* Open statistics file and scan out CPU usage. */ struct cpu_stat cpu; FILE * stat = fopen("/proc/stat", "r"); if (stat == NULL) return TRUE; int fscanf_result = fscanf(stat, "cpu %lu %lu %lu %lu", &cpu.u, &cpu.n, &cpu.s, &cpu.i); fclose(stat); /* Ensure that fscanf succeeded. */ if (fscanf_result == 4) { /* Comcolors delta from previous statistics. */ struct cpu_stat cpu_delta; cpu_delta.u = cpu.u - previous_cpu_stat.u; cpu_delta.n = cpu.n - previous_cpu_stat.n; cpu_delta.s = cpu.s - previous_cpu_stat.s; cpu_delta.i = cpu.i - previous_cpu_stat.i; /* Copy current to previous. */ memcpy(&previous_cpu_stat, &cpu, sizeof(struct cpu_stat)); /* Comcolors user+nice+system as a fraction of total. * Introduce this sample to ring buffer, increment and wrap ring * buffer cursor. */ float cpu_uns = cpu_delta.u + cpu_delta.n + cpu_delta.s; c->stats[c->ring_cursor] = cpu_uns / (cpu_uns + cpu_delta.i); c->ring_cursor += 1; if (c->ring_cursor >= c->pixmap_width) c->ring_cursor = 0; /* Redraw with the new sample. */ redraw_pixmap(c); } } return TRUE; }
/****************************************************************************** * Basic events handlers * ******************************************************************************/ static gboolean configure_event(GtkWidget* widget, GdkEventConfigure* dummy, gpointer data) { (void) dummy; int new_pixmap_width, new_pixmap_height; new_pixmap_width = widget->allocation.width - BORDER_SIZE * 2; new_pixmap_height = widget->allocation.height - BORDER_SIZE *2; Monitor *m; m = (Monitor *) data; if (new_pixmap_width > 0 && new_pixmap_height > 0) { /* * If the stats buffer does not exist (first time we get inside this * function) or its size changed, reallocate the buffer and preserve * existing data. */ if (!m->stats || (new_pixmap_width != m->pixmap_width)) { stats_set *new_stats = g_new0(stats_set, new_pixmap_width); if (!new_stats) return TRUE; if (m->stats) { /* New allocation is larger. * Add new "oldest" samples of zero following the cursor*/ if (new_pixmap_width > m->pixmap_width) { /* Number of values between the ring cursor and the end of * the buffer */ int nvalues = m->pixmap_width - m->ring_cursor; memcpy(new_stats, m->stats, m->ring_cursor * sizeof (stats_set)); memcpy(new_stats + nvalues, m->stats + m->ring_cursor, nvalues * sizeof(stats_set)); } /* New allocation is smaller, but still larger than the ring * buffer cursor */ else if (m->ring_cursor <= new_pixmap_width) { /* Numver of values that can be stored between the end of * the new buffer and the ring cursor */ int nvalues = new_pixmap_width - m->ring_cursor; memcpy(new_stats, m->stats, m->ring_cursor * sizeof(stats_set)); memcpy(new_stats + m->ring_cursor, m->stats + m->pixmap_width - nvalues, nvalues * sizeof(stats_set)); } /* New allocation is smaller, and also smaller than the ring * buffer cursor. Discard all oldest samples following the ring * buffer cursor and additional samples at the beginning of the * buffer. */ else { memcpy(new_stats, m->stats + m->ring_cursor - new_pixmap_width, new_pixmap_width * sizeof(stats_set)); } g_free(m->stats); } m->stats = new_stats; } m->pixmap_width = new_pixmap_width; m->pixmap_height = new_pixmap_height; if (m->pixmap) cairo_surface_destroy(m->pixmap); m->pixmap = cairo_image_surface_create(CAIRO_FORMAT_RGB24, m->pixmap_width, m->pixmap_height); check_cairo_surface_status(&m->pixmap); redraw_pixmap(m); } return TRUE; }
/****************************************************************************** * RAM Monitor * ******************************************************************************/ static gboolean mem_update(Monitor * m) { ENTER; FILE *meminfo; int mem_total = 0; int mem_free = 0; int mem_buffers = 0; int mem_cached = 0; if (m->stats && m->pixmap) { meminfo = fopen("/proc/meminfo", "r"); if (!meminfo) RET(FALSE); if (fscanf(meminfo, "MemTotal: %d kB\n", &mem_total) != 1) { fclose (meminfo); RET(FALSE); } if (fscanf(meminfo, "MemFree: %d kB\n", &mem_free) != 1) { fclose (meminfo); RET(FALSE); } if (fscanf(meminfo, "Buffers: %d kB\n", &mem_buffers) != 1) { fclose (meminfo); RET(FALSE); } if (fscanf(meminfo, "Cached: %d kB\n", &mem_cached) != 1) { fclose (meminfo); RET(FALSE); } fclose(meminfo); m->total = mem_total; /* Adding stats to the buffer: * It is debatable if 'mem_buffers' counts as free or not. I'll go with * 'free', because it can be flushed fairly quickly, and generally * isn't necessary to keep in memory. * It is hard to draw the line, which caches should be counted as free, * and which not. Pagecaches, dentry, and inode caches are quickly * filled up again for almost any use case. Hence I would not count * them as 'free'. * 'mem_cached' definitely counts as 'free' because it is immediately * released should any application need it. */ m->stats[m->ring_cursor] = (mem_total - mem_buffers - mem_free - mem_cached) / (float)mem_total; m->ring_cursor++; if (m->ring_cursor >= m->pixmap_width) m->ring_cursor = 0; /* Redraw the pixmap, with the new sample */ redraw_pixmap (m); } RET(TRUE); }
/****************************************************************************** * RAM Monitor * ******************************************************************************/ static gboolean mem_update(Monitor * m) { ENTER; FILE *meminfo; char buf[80]; long int mem_total = 0; long int mem_free = 0; long int mem_buffers = 0; long int mem_cached = 0; unsigned int readmask = 0x8 | 0x4 | 0x2 | 0x1; if (!m->stats || !m->pixmap) RET(TRUE); meminfo = fopen("/proc/meminfo", "r"); if (!meminfo) { g_warning("monitors: Could not open /proc/meminfo: %d, %s", errno, strerror(errno)); RET(FALSE); } while (readmask && fgets(buf, sizeof(buf), meminfo)) { if (sscanf(buf, "MemTotal: %ld kB\n", &mem_total) == 1) { readmask ^= 0x1; continue; } if (sscanf(buf, "MemFree: %ld kB\n", &mem_free) == 1) { readmask ^= 0x2; continue; } if (sscanf(buf, "Buffers: %ld kB\n", &mem_buffers) == 1) { readmask ^= 0x4; continue; } if (sscanf(buf, "Cached: %ld kB\n", &mem_cached) == 1) { readmask ^= 0x8; continue; } } fclose(meminfo); if (readmask) { g_warning("monitors: Couldn't read all values from /proc/meminfo: " "readmask %x", readmask); RET(FALSE); } m->total = mem_total; /* Adding stats to the buffer: * It is debatable if 'mem_buffers' counts as free or not. I'll go with * 'free', because it can be flushed fairly quickly, and generally * isn't necessary to keep in memory. * It is hard to draw the line, which caches should be counted as free, * and which not. Pagecaches, dentry, and inode caches are quickly * filled up again for almost any use case. Hence I would not count * them as 'free'. * 'mem_cached' definitely counts as 'free' because it is immediately * released should any application need it. */ m->stats[m->ring_cursor] = (mem_total - mem_buffers - mem_free - mem_cached) / (float)mem_total; m->ring_cursor++; if (m->ring_cursor >= m->pixmap_width) m->ring_cursor = 0; /* Redraw the pixmap, with the new sample */ redraw_pixmap (m); RET(TRUE); }