diff --git a/configure.sh b/configure.sh index 740e87a4b6daf33ec094a3441e048d696962057d..7e10ec378cdb26b03b660f5d79b2ed78fba6c475 100755 --- a/configure.sh +++ b/configure.sh @@ -55,7 +55,7 @@ ls_sensors() { try find src -type f -name '*.h' | sed 's,src/\(.*\)\.h,\1,' | grep -xEv "($hdr_blacklist)" | - grep -xE "($hdr_whitelist)" + grep -xE "($hdr_whitelist)" } # gen_sensors_h(sensor, nb_sensors) @@ -118,6 +118,10 @@ detect_caps() { [ -d /sys/class/infiniband ] && hdr_whitelist="${hdr_whitelist}|infiniband" [ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load" + if [ "$(uname -r | cut -d "." -f 1)" -gt "2" ]; then + hdr_whitelist="${hdr_whitelist}|memory" + fi + if [ -r /proc/net/route ]; then dev=$(awk 'NR == 2 { print $1 }' /proc/net/route) [ -e "/sys/class/net/$dev" ] && hdr_whitelist="${hdr_whitelist}|network" diff --git a/src/amd_rapl.c b/src/amd_rapl.c index f08c5a73e80093b2d06fd13739e82796272b2cee..9eaac45938a1ed0f9e44d68408f4a8796103e96e 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -201,17 +201,36 @@ void debug_print_amd_rapl(AmdRapl *rapl) unsigned int get_nb_cpu() { char filename[BUFFER_SIZE]; + int cpy_errno; unsigned int n_cpu = 0; for (;; n_cpu++) { snprintf(filename, BUFFER_SIZE, base_str, n_cpu); int fd = open(filename, O_RDONLY); + cpy_errno = errno; if (fd < 0) { break; } close(fd); } + + if (n_cpu == 0) { + perror("open()"); + fprintf(stderr, "on the file: '%s'\n", filename); + switch (cpy_errno) { + case ENOENT: + fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n"); + exit(99); + case EACCES: + fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n"); + exit(98); + default: + fprintf(stderr, "Unexpected error\n"); + exit(97); + } + } + // n_cpu > 0 return n_cpu; } @@ -295,11 +314,6 @@ unsigned int init_amd_rapl(char *none, void **ptr) UNUSED(none); unsigned int max_cpus = get_nb_cpu(); - if (max_cpus == 0) { - fprintf(stderr, base_str, 0); - perror(":open()"); - exit(127); - } CpuSensor *cpu_information = (CpuSensor *) calloc(max_cpus, sizeof(CpuSensor)); if (parse_cpuinfo(cpu_information, max_cpus)) { diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..3356a82323d3ff8d4a79391c2bb0f36663ece9e2 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,97 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/sysinfo.h> +#include <string.h> + +#include "util.h" + +typedef enum { + TOTALRAM = 0, + FREERAM, + SHAREDRAM, + BUFFERRAM, + TOTALSWAP, + FREESWAP, + PROCS, + TOTALHIGH, + FREEHIGH, + MEM_UNIT, + + MEMORY_COUNT, +} MemoryKind; + +static const char *memory_labels[MEMORY_COUNT] = { + "totalram", "freeram", "sharedram", "bufferram", + "totalswap", "freeswap", + "procs", + "totalhigh", "freehigh", "mem_unit", +}; + +unsigned int init_memory(char *none1, void **none2) +{ + UNUSED(none1); + UNUSED(none2); + struct sysinfo info; + if (sysinfo(&info) < 0) { + fprintf(stderr, "Failed to get the memory information"); + return 0; + } + return MEMORY_COUNT; +} + +unsigned int get_memory(uint64_t *results, void *none) +{ + UNUSED(none); + struct sysinfo info; + if (sysinfo(&info) < 0) { + fprintf(stderr, "Failed to get the memory information"); + exit(99); + } + + // Can't use memcpy, the size isn't always the same + results[TOTALRAM] = info.totalram; + results[FREERAM] = info.freeram; + results[SHAREDRAM] = info.sharedram; + results[BUFFERRAM] = info.bufferram; + results[TOTALSWAP] = info.totalswap; + results[FREESWAP] = info.freeswap; + results[PROCS] = info.procs; + results[TOTALHIGH] = info.totalhigh; + results[FREEHIGH] = info.freehigh; + results[MEM_UNIT] = info.mem_unit; + + return MEMORY_COUNT; +} + +void label_memory(char **labels, void *none) +{ + UNUSED(none); + memcpy(labels, memory_labels, sizeof(char *) * MEMORY_COUNT); +} + +void clean_memory(void *none) +{ + UNUSED(none); + return; +} + diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000000000000000000000000000000000000..6e275c63e41e836364d6ead18ebad548f7952de5 --- /dev/null +++ b/src/memory.h @@ -0,0 +1,43 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + + *******************************************************/ + +unsigned int init_memory(char *, void **); +unsigned int get_memory(uint64_t *results, void *); +void clean_memory(void *); +void label_memory(char **labels, void *); + + +Sensor memory = { + .init = init_memory, + .get = get_memory, + .clean = clean_memory, + .label = label_memory, + .nb_opt = 1, +}; + +Optparse memory_opt[1] = { + { + .longname = "memory", + .shortname = 'm', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "Retrieves information about the memory via the syscall 'sysinfo(2)'.", + }, +}; diff --git a/tests/main.c b/tests/main.c index 3246f0429a7ff7ad065070ac195428af7e099872..e90e8dd69863fcc269d561c07df43dc49a2437ec 100644 --- a/tests/main.c +++ b/tests/main.c @@ -21,9 +21,11 @@ #include "util.c" #include "amd_rapl.c" #include "info_reader.c" +#include "memory.c" TMAIN({ CALL_TFUNCTION(test_util); CALL_TFUNCTION(test_amd_rapl); CALL_TFUNCTION(test_info_reader); + CALL_TFUNCTION(test_memory); }) diff --git a/tests/memory.c b/tests/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..78efd28146558909dc0a940bfa2efce57a102b3d --- /dev/null +++ b/tests/memory.c @@ -0,0 +1,78 @@ +/******************************************************* + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> + + This file is part of Mojitos. + + Mojitos is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Mojitos is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. + +*******************************************************/ + +#include "small_test.h" +#include "../src/memory.c" + +// In order to verify the integrity. +TFUNCTION(test_labels, { + // If it fails update the tests + int tested_count = 10; + int expected_count = MEMORY_COUNT; + TEST_INT(&tested_count, &expected_count); + + const char *result = NULL; + char *expected = NULL; + + expected = "totalram"; + result = memory_labels[TOTALRAM]; + TEST_STR(result, expected); + + expected = "freeram"; + result = memory_labels[FREERAM]; + TEST_STR(result, expected); + + expected = "sharedram"; + result = memory_labels[SHAREDRAM]; + TEST_STR(result, expected); + + expected = "bufferram"; + result = memory_labels[BUFFERRAM]; + TEST_STR(result, expected); + + expected = "totalswap"; + result = memory_labels[TOTALSWAP]; + TEST_STR(result, expected); + + expected = "freeswap"; + result = memory_labels[FREESWAP]; + TEST_STR(result, expected); + + expected = "procs"; + result = memory_labels[PROCS]; + TEST_STR(result, expected); + + expected = "totalhigh"; + result = memory_labels[TOTALHIGH]; + TEST_STR(result, expected); + + expected = "freehigh"; + result = memory_labels[FREEHIGH]; + TEST_STR(result, expected); + + expected = "mem_unit"; + result = memory_labels[MEM_UNIT]; + TEST_STR(result, expected); +}) + +TFILE_ENTRY_POINT(test_memory, { + CALL_TFUNCTION(test_labels); +}) + diff --git a/tests/small_test.h b/tests/small_test.h index 66c4de9119ddd3f67b0b9db85e299487074fd6e1..8301ae7ea0f8247b3b6c81cefab86c26f13aa1c7 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -253,8 +253,8 @@ #define DEFERRED_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); -typedef int (Comparator) (void *, void *); -typedef char *(Formatter) (char[FMT_BUFFER_SIZE], void *); +typedef int (Comparator) (const void *, const void *); +typedef char *(Formatter) (char[FMT_BUFFER_SIZE], const void *); typedef struct { Comparator *compare; @@ -263,7 +263,7 @@ typedef struct { // ---------------------------TEST FUNCTION -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) +int test(char *file, int line, unsigned int __indentation_level, const void *result, const void *expected, const TestInterface *interface) { __indentation_level += 1; static char buffer_result[FMT_BUFFER_SIZE]; @@ -281,7 +281,7 @@ int test(char *file, int line, unsigned int __indentation_level, void *result, v // ------------------------------INTERFACES // -- str_interface -int str_compare(void *ptr1, void *ptr2) +int str_compare(const void *ptr1, const void *ptr2) { char *str1 = (char *) ptr1; char *str2 = (char *) ptr2; @@ -295,7 +295,7 @@ int str_compare(void *ptr1, void *ptr2) } } -char *str_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *str_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { UNUSED(buffer); static char *str_null = "NULL"; @@ -310,14 +310,14 @@ static const TestInterface str_interface = { // -- bool_interface -int bool_compare(void *ptr1, void *ptr2) +int bool_compare(const void *ptr1, const void *ptr2) { bool *bool1 = (bool *) ptr1; bool *bool2 = (bool *) ptr2; return *bool1 == *bool2; } -char *bool_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *bool_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { UNUSED(buffer); bool *_bool = (bool *) ptr; @@ -331,14 +331,14 @@ static const TestInterface bool_interface = { // -- int_interface -int int_compare(void *ptr1, void *ptr2) +int int_compare(const void *ptr1, const void *ptr2) { int *int1 = (int *) ptr1; int *int2 = (int *) ptr2; return *int1 == *int2; } -char *int_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *int_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { int *_int = (int *) ptr; snprintf(buffer, FMT_BUFFER_SIZE, "%d", *_int); @@ -352,12 +352,12 @@ static const TestInterface int_interface = { // -- ptr_interface -int ptr_compare(void *ptr1, void *ptr2) +int ptr_compare(const void *ptr1, const void *ptr2) { return ptr1 == ptr2; } -char *ptr_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *ptr_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { snprintf(buffer, FMT_BUFFER_SIZE, "%p", ptr); return buffer; @@ -370,14 +370,14 @@ static const TestInterface ptr_interface = { // -- u64_interface -int u64_compare(void *ptr1, void *ptr2) +int u64_compare(const void *ptr1, const void *ptr2) { uint64_t *v1 = (uint64_t *) ptr1; uint64_t *v2 = (uint64_t *) ptr2; return *v1 == *v2; } -char *u64_format(char buffer[FMT_BUFFER_SIZE], void *ptr) +char *u64_format(char buffer[FMT_BUFFER_SIZE], const void *ptr) { uint64_t *v = (uint64_t *) ptr; snprintf(buffer, FMT_BUFFER_SIZE, "%"PRIu64"", *v); diff --git a/tests/util.c b/tests/util.c index 69941bfac22fac87d56cd282989721c0c3dc0d76..231ab47487224a3f384d44f6b969be8fee2e25b4 100644 --- a/tests/util.c +++ b/tests/util.c @@ -77,6 +77,50 @@ TFUNCTION(test_modulo_substraction, { TEST_UINT64_T(&result, &expected); }) +TFUNCTION(test_max, { + int expected = 0; + int result = 0; + + expected = 10; + result = MAX(expected, 9); + TEST_INT(&result, &expected); + + expected = -15; + result = MAX(expected, -16); + TEST_INT(&result, &expected); + + expected = 0; + result = MAX(expected, -1); + TEST_INT(&result, &expected); + + expected = 1; + result = MAX(expected, 0); + TEST_INT(&result, &expected); +}) + +TFUNCTION(test_min, { + int expected = 0; + int result = 0; + + expected = 9; + result = MIN(expected, 10); + TEST_INT(&result, &expected); + + expected = -16; + result = MIN(expected, -15); + TEST_INT(&result, &expected); + + expected = -1; + result = MIN(expected, 0); + TEST_INT(&result, &expected); + + expected = 0; + result = MIN(expected, 1); + TEST_INT(&result, &expected); +}) + TFILE_ENTRY_POINT(test_util, { CALL_TFUNCTION(test_modulo_substraction); + CALL_TFUNCTION(test_max); + CALL_TFUNCTION(test_min); })