1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2014 Sony Mobile Communications Inc.
4  *
5  * Selftest for runtime system size
6  *
7  * Prints the amount of RAM that the currently running system is using.
8  *
9  * This program tries to be as small as possible itself, to
10  * avoid perturbing the system memory utilization with its
11  * own execution.  It also attempts to have as few dependencies
12  * on kernel features as possible.
13  *
14  * It should be statically linked, with startup libs avoided.
15  * It uses no library calls, and only the following 3 syscalls:
16  *   sysinfo(), write(), and _exit()
17  *
18  * For output, it avoids printf (which in some C libraries
19  * has large external dependencies) by  implementing it's own
20  * number output and print routines, and using __builtin_strlen()
21  */
22 
23 #include <sys/sysinfo.h>
24 #include <unistd.h>
25 
26 #define STDOUT_FILENO 1
27 
28 static int print(const char *s)
29 {
30 	return write(STDOUT_FILENO, s, __builtin_strlen(s));
31 }
32 
33 static inline char *num_to_str(unsigned long num, char *buf, int len)
34 {
35 	unsigned int digit;
36 
37 	/* put digits in buffer from back to front */
38 	buf += len - 1;
39 	*buf = 0;
40 	do {
41 		digit = num % 10;
42 		*(--buf) = digit + '0';
43 		num /= 10;
44 	} while (num > 0);
45 
46 	return buf;
47 }
48 
49 static int print_num(unsigned long num)
50 {
51 	char num_buf[30];
52 
53 	return print(num_to_str(num, num_buf, sizeof(num_buf)));
54 }
55 
56 static int print_k_value(const char *s, unsigned long num, unsigned long units)
57 {
58 	unsigned long long temp;
59 	int ccode;
60 
61 	print(s);
62 
63 	temp = num;
64 	temp = (temp * units)/1024;
65 	num = temp;
66 	ccode = print_num(num);
67 	print("\n");
68 	return ccode;
69 }
70 
71 /* this program has no main(), as startup libraries are not used */
72 void _start(void)
73 {
74 	int ccode;
75 	struct sysinfo info;
76 	unsigned long used;
77 	static const char *test_name = " get runtime memory use\n";
78 
79 	print("TAP version 13\n");
80 	print("# Testing system size.\n");
81 
82 	ccode = sysinfo(&info);
83 	if (ccode < 0) {
84 		print("not ok 1");
85 		print(test_name);
86 		print(" ---\n reason: \"could not get sysinfo\"\n ...\n");
87 		_exit(ccode);
88 	}
89 	print("ok 1");
90 	print(test_name);
91 
92 	/* ignore cache complexities for now */
93 	used = info.totalram - info.freeram - info.bufferram;
94 	print("# System runtime memory report (units in Kilobytes):\n");
95 	print(" ---\n");
96 	print_k_value(" Total:  ", info.totalram, info.mem_unit);
97 	print_k_value(" Free:   ", info.freeram, info.mem_unit);
98 	print_k_value(" Buffer: ", info.bufferram, info.mem_unit);
99 	print_k_value(" In use: ", used, info.mem_unit);
100 	print(" ...\n");
101 	print("1..1\n");
102 
103 	_exit(0);
104 }
105