Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * User-space helper to sort the output of /sys/kernel/debug/page_owner
  4 *
  5 * Example use:
  6 * cat /sys/kernel/debug/page_owner > page_owner_full.txt
  7 * grep -v ^PFN page_owner_full.txt > page_owner.txt
  8 * ./sort page_owner.txt sorted_page_owner.txt
  9*/
 10
 11#include <stdio.h>
 12#include <stdlib.h>
 13#include <sys/types.h>
 14#include <sys/stat.h>
 15#include <fcntl.h>
 16#include <unistd.h>
 17#include <string.h>
 18
 19struct block_list {
 20	char *txt;
 21	int len;
 22	int num;
 23};
 24
 25
 26static struct block_list *list;
 27static int list_size;
 28static int max_size;
 29
 30struct block_list *block_head;
 31
 32int read_block(char *buf, int buf_size, FILE *fin)
 33{
 34	char *curr = buf, *const buf_end = buf + buf_size;
 35
 36	while (buf_end - curr > 1 && fgets(curr, buf_end - curr, fin)) {
 37		if (*curr == '\n') /* empty line */
 38			return curr - buf;
 39		curr += strlen(curr);
 40	}
 41
 42	return -1; /* EOF or no space left in buf. */
 43}
 44
 45static int compare_txt(const void *p1, const void *p2)
 46{
 47	const struct block_list *l1 = p1, *l2 = p2;
 48
 49	return strcmp(l1->txt, l2->txt);
 50}
 51
 52static int compare_num(const void *p1, const void *p2)
 53{
 54	const struct block_list *l1 = p1, *l2 = p2;
 55
 56	return l2->num - l1->num;
 57}
 58
 59static void add_list(char *buf, int len)
 60{
 61	if (list_size != 0 &&
 62	    len == list[list_size-1].len &&
 63	    memcmp(buf, list[list_size-1].txt, len) == 0) {
 64		list[list_size-1].num++;
 65		return;
 66	}
 67	if (list_size == max_size) {
 68		printf("max_size too small??\n");
 69		exit(1);
 70	}
 71	list[list_size].txt = malloc(len+1);
 72	list[list_size].len = len;
 73	list[list_size].num = 1;
 74	memcpy(list[list_size].txt, buf, len);
 75	list[list_size].txt[len] = 0;
 76	list_size++;
 77	if (list_size % 1000 == 0) {
 78		printf("loaded %d\r", list_size);
 79		fflush(stdout);
 80	}
 81}
 82
 83#define BUF_SIZE	(128 * 1024)
 84
 85int main(int argc, char **argv)
 86{
 87	FILE *fin, *fout;
 88	char *buf;
 89	int ret, i, count;
 90	struct block_list *list2;
 91	struct stat st;
 92
 93	if (argc < 3) {
 94		printf("Usage: ./program <input> <output>\n");
 95		perror("open: ");
 96		exit(1);
 97	}
 98
 99	fin = fopen(argv[1], "r");
100	fout = fopen(argv[2], "w");
101	if (!fin || !fout) {
102		printf("Usage: ./program <input> <output>\n");
103		perror("open: ");
104		exit(1);
105	}
106
107	fstat(fileno(fin), &st);
108	max_size = st.st_size / 100; /* hack ... */
109
110	list = malloc(max_size * sizeof(*list));
111	buf = malloc(BUF_SIZE);
112	if (!list || !buf) {
113		printf("Out of memory\n");
114		exit(1);
115	}
116
117	for ( ; ; ) {
118		ret = read_block(buf, BUF_SIZE, fin);
119		if (ret < 0)
120			break;
121
122		add_list(buf, ret);
123	}
124
125	printf("loaded %d\n", list_size);
126
127	printf("sorting ....\n");
128
129	qsort(list, list_size, sizeof(list[0]), compare_txt);
130
131	list2 = malloc(sizeof(*list) * list_size);
132
133	printf("culling\n");
134
135	for (i = count = 0; i < list_size; i++) {
136		if (count == 0 ||
137		    strcmp(list2[count-1].txt, list[i].txt) != 0) {
138			list2[count++] = list[i];
139		} else {
140			list2[count-1].num += list[i].num;
141		}
142	}
143
144	qsort(list2, count, sizeof(list[0]), compare_num);
145
146	for (i = 0; i < count; i++)
147		fprintf(fout, "%d times:\n%s\n", list2[i].num, list2[i].txt);
148
149	return 0;
150}