|  | /* | 
|  | * Copyright 2014 Sony Mobile Communications Inc. | 
|  | * | 
|  | * Licensed under the terms of the GNU GPL License version 2 | 
|  | * | 
|  | * Selftest for runtime system size | 
|  | * | 
|  | * Prints the amount of RAM that the currently running system is using. | 
|  | * | 
|  | * This program tries to be as small as possible itself, to | 
|  | * avoid perturbing the system memory utilization with its | 
|  | * own execution.  It also attempts to have as few dependencies | 
|  | * on kernel features as possible. | 
|  | * | 
|  | * It should be statically linked, with startup libs avoided. | 
|  | * It uses no library calls, and only the following 3 syscalls: | 
|  | *   sysinfo(), write(), and _exit() | 
|  | * | 
|  | * For output, it avoids printf (which in some C libraries | 
|  | * has large external dependencies) by  implementing it's own | 
|  | * number output and print routines, and using __builtin_strlen() | 
|  | */ | 
|  |  | 
|  | #include <sys/sysinfo.h> | 
|  | #include <unistd.h> | 
|  |  | 
|  | #define STDOUT_FILENO 1 | 
|  |  | 
|  | static int print(const char *s) | 
|  | { | 
|  | return write(STDOUT_FILENO, s, __builtin_strlen(s)); | 
|  | } | 
|  |  | 
|  | static inline char *num_to_str(unsigned long num, char *buf, int len) | 
|  | { | 
|  | unsigned int digit; | 
|  |  | 
|  | /* put digits in buffer from back to front */ | 
|  | buf += len - 1; | 
|  | *buf = 0; | 
|  | do { | 
|  | digit = num % 10; | 
|  | *(--buf) = digit + '0'; | 
|  | num /= 10; | 
|  | } while (num > 0); | 
|  |  | 
|  | return buf; | 
|  | } | 
|  |  | 
|  | static int print_num(unsigned long num) | 
|  | { | 
|  | char num_buf[30]; | 
|  |  | 
|  | return print(num_to_str(num, num_buf, sizeof(num_buf))); | 
|  | } | 
|  |  | 
|  | static int print_k_value(const char *s, unsigned long num, unsigned long units) | 
|  | { | 
|  | unsigned long long temp; | 
|  | int ccode; | 
|  |  | 
|  | print(s); | 
|  |  | 
|  | temp = num; | 
|  | temp = (temp * units)/1024; | 
|  | num = temp; | 
|  | ccode = print_num(num); | 
|  | print("\n"); | 
|  | return ccode; | 
|  | } | 
|  |  | 
|  | /* this program has no main(), as startup libraries are not used */ | 
|  | void _start(void) | 
|  | { | 
|  | int ccode; | 
|  | struct sysinfo info; | 
|  | unsigned long used; | 
|  |  | 
|  | print("Testing system size.\n"); | 
|  | print("1..1\n"); | 
|  |  | 
|  | ccode = sysinfo(&info); | 
|  | if (ccode < 0) { | 
|  | print("not ok 1 get runtime memory use\n"); | 
|  | print("# could not get sysinfo\n"); | 
|  | _exit(ccode); | 
|  | } | 
|  | /* ignore cache complexities for now */ | 
|  | used = info.totalram - info.freeram - info.bufferram; | 
|  | print_k_value("ok 1 get runtime memory use # size = ", used, | 
|  | info.mem_unit); | 
|  |  | 
|  | print("# System runtime memory report (units in Kilobytes):\n"); | 
|  | print_k_value("#   Total:  ", info.totalram, info.mem_unit); | 
|  | print_k_value("#   Free:   ", info.freeram, info.mem_unit); | 
|  | print_k_value("#   Buffer: ", info.bufferram, info.mem_unit); | 
|  | print_k_value("#   In use: ", used, info.mem_unit); | 
|  |  | 
|  | _exit(0); | 
|  | } |