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.
16 * It uses no library calls, and only the following 3 syscalls:
17 *   sysinfo(), write(), and _exit()
18 *
19 * For output, it avoids printf (which in some C libraries
20 * has large external dependencies) by  implementing it's own
21 * number output and print routines, and using __builtin_strlen()
22 */
23
24#include <sys/sysinfo.h>
25#include <unistd.h>
26
27#define STDOUT_FILENO 1
28
29static int print(const char *s)
30{
31	return write(STDOUT_FILENO, s, __builtin_strlen(s));
32}
33
34static inline char *num_to_str(unsigned long num, char *buf, int len)
35{
36	unsigned int digit;
37
38	/* put digits in buffer from back to front */
39	buf += len - 1;
40	*buf = 0;
41	do {
42		digit = num % 10;
43		*(--buf) = digit + '0';
44		num /= 10;
45	} while (num > 0);
46
47	return buf;
48}
49
50static int print_num(unsigned long num)
51{
52	char num_buf[30];
53
54	return print(num_to_str(num, num_buf, sizeof(num_buf)));
55}
56
57static int print_k_value(const char *s, unsigned long num, unsigned long units)
58{
59	unsigned long long temp;
60	int ccode;
61
62	print(s);
63
64	temp = num;
65	temp = (temp * units)/1024;
66	num = temp;
67	ccode = print_num(num);
68	print("\n");
69	return ccode;
70}
71
72/* this program has no main(), as startup libraries are not used */
73void _start(void)
74{
75	int ccode;
76	struct sysinfo info;
77	unsigned long used;
78
79	print("Testing system size.\n");
80	print("1..1\n");
81
82	ccode = sysinfo(&info);
83	if (ccode < 0) {
84		print("not ok 1 get runtime memory use\n");
85		print("# could not get sysinfo\n");
86		_exit(ccode);
87	}
88	/* ignore cache complexities for now */
89	used = info.totalram - info.freeram - info.bufferram;
90	print_k_value("ok 1 get runtime memory use # size = ", used,
91		info.mem_unit);
92
93	print("# System runtime memory report (units in Kilobytes):\n");
94	print_k_value("#   Total:  ", info.totalram, info.mem_unit);
95	print_k_value("#   Free:   ", info.freeram, info.mem_unit);
96	print_k_value("#   Buffer: ", info.bufferram, info.mem_unit);
97	print_k_value("#   In use: ", used, info.mem_unit);
98
99	_exit(0);
100}
101