14f19048fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23ce51050STim Bird /*
33ce51050STim Bird * Copyright 2014 Sony Mobile Communications Inc.
43ce51050STim Bird *
53ce51050STim Bird * Selftest for runtime system size
63ce51050STim Bird *
73ce51050STim Bird * Prints the amount of RAM that the currently running system is using.
83ce51050STim Bird *
93ce51050STim Bird * This program tries to be as small as possible itself, to
103ce51050STim Bird * avoid perturbing the system memory utilization with its
113ce51050STim Bird * own execution. It also attempts to have as few dependencies
123ce51050STim Bird * on kernel features as possible.
133ce51050STim Bird *
14*6b64a650SSiddhesh Poyarekar * It should be statically linked, with startup libs avoided. It uses
15*6b64a650SSiddhesh Poyarekar * no library calls except the syscall() function for the following 3
16*6b64a650SSiddhesh Poyarekar * syscalls:
173ce51050STim Bird * sysinfo(), write(), and _exit()
183ce51050STim Bird *
193ce51050STim Bird * For output, it avoids printf (which in some C libraries
203ce51050STim Bird * has large external dependencies) by implementing it's own
213ce51050STim Bird * number output and print routines, and using __builtin_strlen()
22*6b64a650SSiddhesh Poyarekar *
23*6b64a650SSiddhesh Poyarekar * The test may crash if any of the above syscalls fails because in some
24*6b64a650SSiddhesh Poyarekar * libc implementations (e.g. the GNU C Library) errno is saved in
25*6b64a650SSiddhesh Poyarekar * thread-local storage, which does not get initialized due to avoiding
26*6b64a650SSiddhesh Poyarekar * startup libs.
273ce51050STim Bird */
283ce51050STim Bird
293ce51050STim Bird #include <sys/sysinfo.h>
303ce51050STim Bird #include <unistd.h>
31*6b64a650SSiddhesh Poyarekar #include <sys/syscall.h>
323ce51050STim Bird
333ce51050STim Bird #define STDOUT_FILENO 1
343ce51050STim Bird
print(const char * s)353ce51050STim Bird static int print(const char *s)
363ce51050STim Bird {
37*6b64a650SSiddhesh Poyarekar size_t len = 0;
38*6b64a650SSiddhesh Poyarekar
39*6b64a650SSiddhesh Poyarekar while (s[len] != '\0')
40*6b64a650SSiddhesh Poyarekar len++;
41*6b64a650SSiddhesh Poyarekar
42*6b64a650SSiddhesh Poyarekar return syscall(SYS_write, STDOUT_FILENO, s, len);
433ce51050STim Bird }
443ce51050STim Bird
num_to_str(unsigned long num,char * buf,int len)453ce51050STim Bird static inline char *num_to_str(unsigned long num, char *buf, int len)
463ce51050STim Bird {
473ce51050STim Bird unsigned int digit;
483ce51050STim Bird
493ce51050STim Bird /* put digits in buffer from back to front */
503ce51050STim Bird buf += len - 1;
513ce51050STim Bird *buf = 0;
523ce51050STim Bird do {
533ce51050STim Bird digit = num % 10;
543ce51050STim Bird *(--buf) = digit + '0';
553ce51050STim Bird num /= 10;
563ce51050STim Bird } while (num > 0);
573ce51050STim Bird
583ce51050STim Bird return buf;
593ce51050STim Bird }
603ce51050STim Bird
print_num(unsigned long num)613ce51050STim Bird static int print_num(unsigned long num)
623ce51050STim Bird {
633ce51050STim Bird char num_buf[30];
643ce51050STim Bird
653ce51050STim Bird return print(num_to_str(num, num_buf, sizeof(num_buf)));
663ce51050STim Bird }
673ce51050STim Bird
print_k_value(const char * s,unsigned long num,unsigned long units)683ce51050STim Bird static int print_k_value(const char *s, unsigned long num, unsigned long units)
693ce51050STim Bird {
703ce51050STim Bird unsigned long long temp;
713ce51050STim Bird int ccode;
723ce51050STim Bird
733ce51050STim Bird print(s);
743ce51050STim Bird
753ce51050STim Bird temp = num;
763ce51050STim Bird temp = (temp * units)/1024;
773ce51050STim Bird num = temp;
783ce51050STim Bird ccode = print_num(num);
793ce51050STim Bird print("\n");
803ce51050STim Bird return ccode;
813ce51050STim Bird }
823ce51050STim Bird
833ce51050STim Bird /* this program has no main(), as startup libraries are not used */
_start(void)843ce51050STim Bird void _start(void)
853ce51050STim Bird {
863ce51050STim Bird int ccode;
873ce51050STim Bird struct sysinfo info;
883ce51050STim Bird unsigned long used;
8948e42f91STim Bird static const char *test_name = " get runtime memory use\n";
903ce51050STim Bird
9148e42f91STim Bird print("TAP version 13\n");
9248e42f91STim Bird print("# Testing system size.\n");
933ce51050STim Bird
94*6b64a650SSiddhesh Poyarekar ccode = syscall(SYS_sysinfo, &info);
953ce51050STim Bird if (ccode < 0) {
9648e42f91STim Bird print("not ok 1");
9748e42f91STim Bird print(test_name);
9848e42f91STim Bird print(" ---\n reason: \"could not get sysinfo\"\n ...\n");
99*6b64a650SSiddhesh Poyarekar syscall(SYS_exit, ccode);
1003ce51050STim Bird }
10148e42f91STim Bird print("ok 1");
10248e42f91STim Bird print(test_name);
10348e42f91STim Bird
1043ce51050STim Bird /* ignore cache complexities for now */
1053ce51050STim Bird used = info.totalram - info.freeram - info.bufferram;
1063ce51050STim Bird print("# System runtime memory report (units in Kilobytes):\n");
10748e42f91STim Bird print(" ---\n");
10848e42f91STim Bird print_k_value(" Total: ", info.totalram, info.mem_unit);
10948e42f91STim Bird print_k_value(" Free: ", info.freeram, info.mem_unit);
11048e42f91STim Bird print_k_value(" Buffer: ", info.bufferram, info.mem_unit);
11148e42f91STim Bird print_k_value(" In use: ", used, info.mem_unit);
11248e42f91STim Bird print(" ...\n");
11348e42f91STim Bird print("1..1\n");
1143ce51050STim Bird
115*6b64a650SSiddhesh Poyarekar syscall(SYS_exit, 0);
1163ce51050STim Bird }
117