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