2010-01-19 22:00:20 +01:00
|
|
|
/* Debugging dump procedures for the VM server. */
|
|
|
|
|
|
|
|
#include "inc.h"
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <minix/vm.h>
|
|
|
|
#include <timers.h>
|
2010-04-02 00:22:33 +02:00
|
|
|
#include "kernel/proc.h"
|
2010-01-19 22:00:20 +01:00
|
|
|
|
|
|
|
#define LINES 24
|
|
|
|
|
2010-07-27 20:46:08 +02:00
|
|
|
PRIVATE void print_region(struct vm_region_info *vri, int *n)
|
2010-01-19 22:00:20 +01:00
|
|
|
{
|
2010-07-27 20:46:08 +02:00
|
|
|
static int vri_count, vri_prev_set;
|
|
|
|
static struct vm_region_info vri_prev;
|
2010-01-19 22:00:20 +01:00
|
|
|
char c;
|
2010-07-27 20:46:08 +02:00
|
|
|
int is_repeat;
|
|
|
|
|
|
|
|
/* part of a contiguous identical run? */
|
|
|
|
is_repeat =
|
|
|
|
vri &&
|
|
|
|
vri_prev_set &&
|
|
|
|
vri->vri_seg == vri_prev.vri_seg &&
|
|
|
|
vri->vri_prot == vri_prev.vri_prot &&
|
|
|
|
vri->vri_flags == vri_prev.vri_flags &&
|
|
|
|
vri->vri_length == vri_prev.vri_length &&
|
|
|
|
vri->vri_addr == vri_prev.vri_addr + vri_prev.vri_length;
|
|
|
|
if (vri) {
|
|
|
|
vri_prev_set = 1;
|
|
|
|
vri_prev = *vri;
|
|
|
|
} else {
|
|
|
|
vri_prev_set = 0;
|
|
|
|
}
|
|
|
|
if (is_repeat) {
|
|
|
|
vri_count++;
|
|
|
|
return;
|
|
|
|
}
|
2010-01-19 22:00:20 +01:00
|
|
|
|
2010-07-27 20:46:08 +02:00
|
|
|
if (vri_count > 0) {
|
|
|
|
printf(" (contiguously repeated %d more times)\n", vri_count);
|
|
|
|
(*n)++;
|
|
|
|
vri_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NULL indicates the end of a list of mappings, nothing else to do */
|
|
|
|
if (!vri) return;
|
|
|
|
|
|
|
|
/* first in a run, print all info */
|
2010-01-19 22:00:20 +01:00
|
|
|
switch (vri->vri_seg) {
|
|
|
|
case T: c = 'T'; break;
|
|
|
|
case D: c = 'D'; break;
|
|
|
|
default: c = '?';
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" %c %08lx-%08lx %c%c%c %c (%lu kB)\n", c, vri->vri_addr,
|
|
|
|
vri->vri_addr + vri->vri_length,
|
|
|
|
(vri->vri_prot & PROT_READ) ? 'r' : '-',
|
|
|
|
(vri->vri_prot & PROT_WRITE) ? 'w' : '-',
|
|
|
|
(vri->vri_prot & PROT_EXEC) ? 'x' : '-',
|
2011-07-15 18:10:50 +02:00
|
|
|
(vri->vri_flags & MAP_IPC_SHARED) ? 's' : 'p',
|
2010-01-19 22:00:20 +01:00
|
|
|
vri->vri_length / 1024L);
|
2010-07-27 20:46:08 +02:00
|
|
|
(*n)++;
|
2010-01-19 22:00:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PUBLIC void vm_dmp()
|
|
|
|
{
|
|
|
|
static struct proc proc[NR_TASKS + NR_PROCS];
|
|
|
|
static struct vm_region_info vri[LINES];
|
|
|
|
struct vm_stats_info vsi;
|
|
|
|
struct vm_usage_info vui;
|
|
|
|
static int prev_i = -1;
|
|
|
|
static vir_bytes prev_base = 0;
|
|
|
|
int r, r2, i, j, first, n = 0;
|
|
|
|
|
|
|
|
if (prev_i == -1) {
|
|
|
|
if ((r = vm_info_stats(&vsi)) != OK) {
|
2010-03-05 16:05:11 +01:00
|
|
|
printf("IS: warning: couldn't talk to VM: %d\n", r);
|
2010-01-19 22:00:20 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-14 23:22:56 +02:00
|
|
|
printf("Total %u kB, free %u kB, largest free %u kB, cached %u kB\n",
|
2010-01-19 22:00:20 +01:00
|
|
|
vsi.vsi_total * (vsi.vsi_pagesize / 1024),
|
|
|
|
vsi.vsi_free * (vsi.vsi_pagesize / 1024),
|
2010-09-14 23:22:56 +02:00
|
|
|
vsi.vsi_largest * (vsi.vsi_pagesize / 1024),
|
|
|
|
vsi.vsi_cached * (vsi.vsi_pagesize / 1024));
|
2010-01-19 22:00:20 +01:00
|
|
|
n++;
|
|
|
|
printf("\n");
|
|
|
|
n++;
|
|
|
|
|
|
|
|
prev_i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((r = sys_getproctab(proc)) != OK) {
|
2010-03-05 16:05:11 +01:00
|
|
|
printf("IS: warning: couldn't get copy of process table: %d\n", r);
|
2010-01-19 22:00:20 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = prev_i; i < NR_TASKS + NR_PROCS && n < LINES; i++, prev_base = 0) {
|
|
|
|
if (i < NR_TASKS || isemptyp(&proc[i])) continue;
|
|
|
|
|
|
|
|
/* The first batch dump for each process contains a header line. */
|
|
|
|
first = prev_base == 0;
|
|
|
|
|
|
|
|
r = vm_info_region(proc[i].p_endpoint, vri, LINES - first, &prev_base);
|
|
|
|
|
|
|
|
if (r < 0) {
|
|
|
|
printf("Process %d (%s): error %d\n",
|
|
|
|
proc[i].p_endpoint, proc[i].p_name, r);
|
|
|
|
n++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (first) {
|
|
|
|
/* The entire batch should fit on the screen. */
|
|
|
|
if (n + 1 + r > LINES) {
|
|
|
|
prev_base = 0; /* restart on next page */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((r2 = vm_info_usage(proc[i].p_endpoint, &vui)) != OK) {
|
|
|
|
printf("Process %d (%s): error %d\n",
|
|
|
|
proc[i].p_endpoint, proc[i].p_name, r2);
|
|
|
|
n++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("Process %d (%s): total %lu kB, common %lu kB, "
|
|
|
|
"shared %lu kB\n",
|
|
|
|
proc[i].p_endpoint, proc[i].p_name,
|
|
|
|
vui.vui_total / 1024L, vui.vui_common / 1024L,
|
|
|
|
vui.vui_shared / 1024L);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
2010-07-27 20:46:08 +02:00
|
|
|
while (r > 0) {
|
|
|
|
for (j = 0; j < r; j++) {
|
|
|
|
print_region(&vri[j], &n);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LINES - n - 1 <= 0) break;
|
|
|
|
r = vm_info_region(proc[i].p_endpoint, vri, LINES - n - 1,
|
|
|
|
&prev_base);
|
|
|
|
|
|
|
|
if (r < 0) {
|
|
|
|
printf("Process %d (%s): error %d\n",
|
|
|
|
proc[i].p_endpoint, proc[i].p_name, r);
|
|
|
|
n++;
|
|
|
|
}
|
2010-01-19 22:00:20 +01:00
|
|
|
}
|
2010-07-27 20:46:08 +02:00
|
|
|
print_region(NULL, &n);
|
2010-01-19 22:00:20 +01:00
|
|
|
|
|
|
|
if (n > LINES) printf("IS: internal error\n");
|
|
|
|
if (n == LINES) break;
|
|
|
|
|
|
|
|
/* This may have to wipe out the "--more--" from below. */
|
|
|
|
printf(" \n");
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i >= NR_TASKS + NR_PROCS) {
|
|
|
|
i = -1;
|
|
|
|
prev_base = 0;
|
|
|
|
}
|
|
|
|
else printf("--more--\r");
|
|
|
|
prev_i = i;
|
|
|
|
}
|
|
|
|
|