linux/tools/testing/selftests/size/get_size.c
<<
>>
Prefs
   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.  It uses
  15 * no library calls except the syscall() function for the following 3
  16 * 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 * The test may crash if any of the above syscalls fails because in some
  24 * libc implementations (e.g. the GNU C Library) errno is saved in
  25 * thread-local storage, which does not get initialized due to avoiding
  26 * startup libs.
  27 */
  28
  29#include <sys/sysinfo.h>
  30#include <unistd.h>
  31#include <sys/syscall.h>
  32
  33#define STDOUT_FILENO 1
  34
  35static int print(const char *s)
  36{
  37        size_t len = 0;
  38
  39        while (s[len] != '\0')
  40                len++;
  41
  42        return syscall(SYS_write, STDOUT_FILENO, s, len);
  43}
  44
  45static inline char *num_to_str(unsigned long num, char *buf, int len)
  46{
  47        unsigned int digit;
  48
  49        /* put digits in buffer from back to front */
  50        buf += len - 1;
  51        *buf = 0;
  52        do {
  53                digit = num % 10;
  54                *(--buf) = digit + '0';
  55                num /= 10;
  56        } while (num > 0);
  57
  58        return buf;
  59}
  60
  61static int print_num(unsigned long num)
  62{
  63        char num_buf[30];
  64
  65        return print(num_to_str(num, num_buf, sizeof(num_buf)));
  66}
  67
  68static int print_k_value(const char *s, unsigned long num, unsigned long units)
  69{
  70        unsigned long long temp;
  71        int ccode;
  72
  73        print(s);
  74
  75        temp = num;
  76        temp = (temp * units)/1024;
  77        num = temp;
  78        ccode = print_num(num);
  79        print("\n");
  80        return ccode;
  81}
  82
  83/* this program has no main(), as startup libraries are not used */
  84void _start(void)
  85{
  86        int ccode;
  87        struct sysinfo info;
  88        unsigned long used;
  89        static const char *test_name = " get runtime memory use\n";
  90
  91        print("TAP version 13\n");
  92        print("# Testing system size.\n");
  93
  94        ccode = syscall(SYS_sysinfo, &info);
  95        if (ccode < 0) {
  96                print("not ok 1");
  97                print(test_name);
  98                print(" ---\n reason: \"could not get sysinfo\"\n ...\n");
  99                syscall(SYS_exit, ccode);
 100        }
 101        print("ok 1");
 102        print(test_name);
 103
 104        /* ignore cache complexities for now */
 105        used = info.totalram - info.freeram - info.bufferram;
 106        print("# System runtime memory report (units in Kilobytes):\n");
 107        print(" ---\n");
 108        print_k_value(" Total:  ", info.totalram, info.mem_unit);
 109        print_k_value(" Free:   ", info.freeram, info.mem_unit);
 110        print_k_value(" Buffer: ", info.bufferram, info.mem_unit);
 111        print_k_value(" In use: ", used, info.mem_unit);
 112        print(" ...\n");
 113        print("1..1\n");
 114
 115        syscall(SYS_exit, 0);
 116}
 117