/*===========================================================================* * printmemstats * *===========================================================================*/ void printmemstats(void) { int nodes, pages, largest; memstats(&nodes, &pages, &largest); printf("%d blocks, %d pages (%lukB) free, largest %d pages (%lukB)\n", nodes, pages, (unsigned long) pages * (VM_PAGE_SIZE/1024), largest, (unsigned long) largest * (VM_PAGE_SIZE/1024)); }
/*===========================================================================* * do_info * *===========================================================================*/ int do_info(message *m) { struct vm_stats_info vsi; struct vm_usage_info vui; static struct vm_region_info vri[MAX_VRI_COUNT]; struct vmproc *vmp; vir_bytes addr, size, next, ptr; int r, pr, dummy, count, free_pages, largest_contig; if (vm_isokendpt(m->m_source, &pr) != OK) return EINVAL; vmp = &vmproc[pr]; ptr = (vir_bytes) m->m_lsys_vm_info.ptr; switch(m->m_lsys_vm_info.what) { case VMIW_STATS: vsi.vsi_pagesize = VM_PAGE_SIZE; vsi.vsi_total = total_pages; memstats(&dummy, &free_pages, &largest_contig); vsi.vsi_free = free_pages; vsi.vsi_largest = largest_contig; get_stats_info(&vsi); addr = (vir_bytes) &vsi; size = sizeof(vsi); break; case VMIW_USAGE: if(m->m_lsys_vm_info.ep < 0) get_usage_info_kernel(&vui); else if (vm_isokendpt(m->m_lsys_vm_info.ep, &pr) != OK) return EINVAL; else get_usage_info(&vmproc[pr], &vui); addr = (vir_bytes) &vui; size = sizeof(vui); break; case VMIW_REGION: if(m->m_lsys_vm_info.ep == SELF) { m->m_lsys_vm_info.ep = m->m_source; } if (vm_isokendpt(m->m_lsys_vm_info.ep, &pr) != OK) return EINVAL; count = MIN(m->m_lsys_vm_info.count, MAX_VRI_COUNT); next = m->m_lsys_vm_info.next; count = get_region_info(&vmproc[pr], vri, count, &next); m->m_lsys_vm_info.count = count; m->m_lsys_vm_info.next = next; addr = (vir_bytes) vri; size = sizeof(vri[0]) * count; break; default: return EINVAL; } if (size == 0) return OK; /* Make sure that no page faults can occur while copying out. A page * fault would cause the kernel to send a notify to us, while we would * be waiting for the result of the copy system call, resulting in a * deadlock. Note that no memory mapping can be undone without the * involvement of VM, so we are safe until we're done. */ r = handle_memory_once(vmp, ptr, size, 1 /*wrflag*/); if (r != OK) return r; /* Now that we know the copy out will succeed, perform the actual copy * operation. */ return sys_datacopy(SELF, addr, (vir_bytes) vmp->vm_endpoint, ptr, size); }
int main(int argc, char** argv) { bool cpu_stats = false; bool mem_stats = false; zx_duration_t delay = ZX_SEC(1); int num_loops = -1; bool timestamp = false; int c; while ((c = getopt(argc, argv, "cd:n:hmt")) > 0) { switch (c) { case 'c': cpu_stats = true; break; case 'd': delay = ZX_SEC(atoi(optarg)); if (delay == 0) { fprintf(stderr, "Bad -d value '%s'\n", optarg); print_help(stderr); return 1; } break; case 'n': num_loops = atoi(optarg); if (num_loops == 0) { fprintf(stderr, "Bad -n value '%s'\n", optarg); print_help(stderr); return 1; } break; case 'h': print_help(stdout); return 0; case 'm': mem_stats = true; break; case 't': timestamp = true; break; default: fprintf(stderr, "Unknown option\n"); print_help(stderr); return 1; } } if (!cpu_stats && !mem_stats) { fprintf(stderr, "No statistics selected\n"); print_help(stderr); return 1; } zx_handle_t root_resource; zx_status_t ret = get_root_resource(&root_resource); if (ret != ZX_OK) { return ret; } // set stdin to non blocking so we can intercept ctrl-c. // TODO: remove once ctrl-c works in the shell fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); for (;;) { zx_time_t next_deadline = zx_deadline_after(delay); // Print the current UTC time with milliseconds as // an ISO 8601 string. if (timestamp) { struct timespec now; timespec_get(&now, TIME_UTC); struct tm nowtm; gmtime_r(&now.tv_sec, &nowtm); char tbuf[40]; strftime(tbuf, sizeof(tbuf), "%FT%T", &nowtm); printf("\n--- %s.%03ldZ ---\n", tbuf, now.tv_nsec / (1000 * 1000)); } if (cpu_stats) { ret |= cpustats(root_resource, delay); } if (mem_stats) { ret |= memstats(root_resource); } if (ret != ZX_OK) break; if (num_loops > 0) { if (--num_loops == 0) { break; } } else { // TODO: replace once ctrl-c works in the shell char c; int err; while ((err = read(STDIN_FILENO, &c, 1)) > 0) { if (c == 0x3) return 0; } } zx_nanosleep(next_deadline); } zx_handle_close(root_resource); return ret; }