• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
print(const char * s)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 
num_to_str(unsigned long num,char * buf,int len)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 
print_num(unsigned long num)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 
print_k_value(const char * s,unsigned long num,unsigned long units)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 */
_start(void)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 }
118