if (strstr(migrate_info, "CMA"))
allocator |= ALLOCATOR_CMA; if (strstr(migrate_info, "slab"))
allocator |= ALLOCATOR_SLAB;
tmp = strstr(buf, "__vmalloc_node_range"); if (tmp) {
second_line = tmp; while (*tmp != '\n')
tmp--;
tmp--; while (*tmp != '\n')
tmp--;
first_line = ++tmp;
tmp = strstr(tmp, "alloc_pages"); if (tmp && first_line <= tmp && tmp < second_line)
allocator |= ALLOCATOR_VMALLOC;
} if (allocator == 0)
allocator = ALLOCATOR_OTHERS; return allocator;
}
staticbool match_num_list(int num, int *list, int list_size)
{ for (int i = 0; i < list_size; ++i) if (list[i] == num) returntrue; returnfalse;
}
staticbool match_str_list(constchar *str, char **list, int list_size)
{ for (int i = 0; i < list_size; ++i) if (!strcmp(list[i], str)) returntrue; returnfalse;
}
staticvoid print_allocator(FILE *out, int allocator)
{
fprintf(out, "allocated by "); if (allocator & ALLOCATOR_CMA)
fprintf(out, "CMA "); if (allocator & ALLOCATOR_SLAB)
fprintf(out, "SLAB "); if (allocator & ALLOCATOR_VMALLOC)
fprintf(out, "VMALLOC "); if (allocator & ALLOCATOR_OTHERS)
fprintf(out, "OTHERS ");
}
#define BUF_SIZE (128 * 1024)
staticvoid usage(void)
{
printf("Usage: ./page_owner_sort [OPTIONS] "-a\t\t\tSort by memory allocation time.\n" "-m\t\t\tSort by total memory.\n" "-n\t\t\tSort by task command name.\n" "-p\t\t\tSort by pid.\n" "-P\t\t\tSort by tgid.\n" "-s\t\t\tSort by the stacktrace.\n" "-t\t\t\tSort by number of times record is seen (default).\n\n" "--pid \t\tSelect by pid. This selects the information" " of\n\t\t\tblocks whose process ID numbers appear in .\n" "--tgid \tSelect by tgid. This selects the information" " of\n\t\t\tblocks whose Thread Group ID numbers appear in " ".\n" "--name \tSelect by command name. This selects the" " information\n\t\t\tof blocks whose command name appears in" " .\n" "--cull \t\tCull by user-defined rules. is a " "single\n\t\t\targument in the form of a comma-separated list " "with some\n\t\t\tcommon fields predefined (pid, tgid, comm, " "stacktrace, allocator)\n" "--sort \t\tSpecify sort order as: [+|-]key[,[+|-]key[,...]]\n"
);
}
while ((opt = getopt_long(argc, argv, "admnpstP", longopts, NULL)) != -1) switch (opt) { case'a':
compare_flag |= COMP_ALLOC; break; case'd':
debug_on = true; break; case'm':
compare_flag |= COMP_PAGE_NUM; break; case'p':
compare_flag |= COMP_PID; break; case's':
compare_flag |= COMP_STACK; break; case't':
compare_flag |= COMP_NUM; break; case'P':
compare_flag |= COMP_TGID; break; case'n':
compare_flag |= COMP_COMM; break; case 1:
filter = filter | FILTER_PID;
fc.pids = parse_nums_list(optarg, &fc.pids_size); if (fc.pids == NULL) {
fprintf(stderr, "wrong/invalid pid in from the command line:%s\n",
optarg); exit(1);
} break; case 2:
filter = filter | FILTER_TGID;
fc.tgids = parse_nums_list(optarg, &fc.tgids_size); if (fc.tgids == NULL) {
fprintf(stderr, "wrong/invalid tgid in from the command line:%s\n",
optarg); exit(1);
} break; case 3:
filter = filter | FILTER_COMM;
fc.comms = explode(',', optarg, &fc.comms_size); break; case 4: if (!parse_cull_args(optarg)) {
fprintf(stderr, "wrong argument after --cull option:%s\n",
optarg); exit(1);
} break; case 5: if (!parse_sort_args(optarg)) {
fprintf(stderr, "wrong argument after --sort option:%s\n",
optarg); exit(1);
} break; default:
usage(); exit(1);
}
if (optind >= (argc - 1)) {
usage(); exit(1);
}
/* Only one compare option is allowed, yet we also want handle the * default case were no option is provided, but we still want to * match the behavior of the -t option (compare by number of times * a record is seen
*/ switch (compare_flag) { case COMP_ALLOC:
set_single_cmp(compare_ts, SORT_ASC); break; case COMP_PAGE_NUM:
set_single_cmp(compare_page_num, SORT_DESC); break; case COMP_PID:
set_single_cmp(compare_pid, SORT_ASC); break; case COMP_STACK:
set_single_cmp(compare_stacktrace, SORT_ASC); break; case COMP_NO_FLAG: case COMP_NUM:
set_single_cmp(compare_num, SORT_DESC); break; case COMP_TGID:
set_single_cmp(compare_tgid, SORT_ASC); break; case COMP_COMM:
set_single_cmp(compare_comm, SORT_ASC); break; default:
usage(); exit(1);
}
fin = fopen(argv[optind], "r");
fout = fopen(argv[optind + 1], "w"); if (!fin || !fout) {
usage();
perror("open: "); exit(1);
}
if (!check_regcomp(&order_pattern, "order\\s*([0-9]*),")) goto out_order; if (!check_regcomp(&pid_pattern, "pid\\s*([0-9]*),")) goto out_pid; if (!check_regcomp(&tgid_pattern, "tgid\\s*([0-9]*) ")) goto out_tgid; if (!check_regcomp(&comm_pattern, "tgid\\s*[0-9]*\\s*\\((.*)\\),\\s*ts")) goto out_comm; if (!check_regcomp(&ts_nsec_pattern, "ts\\s*([0-9]*)\\s*ns")) goto out_ts;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.