From eab8f8bf862f796b589374803af9d501d7a7ef08 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 6 Feb 2023 14:09:22 +0100 Subject: [PATCH 01/69] Add dev name to labels plus some other changes, in particular: - index --> strchr - sprintf --> snprintf --- src/network.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/network.c b/src/network.c index 543a053..aee5659 100644 --- a/src/network.c +++ b/src/network.c @@ -28,10 +28,17 @@ #define NB_SENSOR 4 static char *route = "/proc/net/route"; +char *_labels_network[NB_SENSOR] = { + "%s:rxp", + "%s:rxb", + "%s:txp", + "%s:txb", +}; struct network_t { uint64_t values[NB_SENSOR]; uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; + char labels[NB_SENSOR][128]; }; unsigned int _get_network(uint64_t *results, int *sources) @@ -54,8 +61,6 @@ unsigned int _get_network(uint64_t *results, int *sources) return NB_SENSOR; } - - unsigned int init_network(char *dev, void **ptr) { if (dev == NULL) { @@ -79,25 +84,27 @@ unsigned int init_network(char *dev, void **ptr) exit(1); } - char *start_of_dev = index(buffer, '\n') + 1; - char *end_of_dev = index(start_of_dev, '\t'); + char *start_of_dev = strchr(buffer, '\n') + 1; + char *end_of_dev = strchr(start_of_dev, '\t'); *end_of_dev = '\0'; dev = start_of_dev; close(fd); } - char *filenames[] = {"/sys/class/net/%s/statistics/rx_packets", - "/sys/class/net/%s/statistics/rx_bytes", - "/sys/class/net/%s/statistics/tx_packets", - "/sys/class/net/%s/statistics/tx_bytes" - }; + char *filenames[] = { + "/sys/class/net/%s/statistics/rx_packets", + "/sys/class/net/%s/statistics/rx_bytes", + "/sys/class/net/%s/statistics/tx_packets", + "/sys/class/net/%s/statistics/tx_bytes", + }; struct network_t *state = malloc(sizeof(struct network_t)); char buffer2[256]; for (int i = 0; i < NB_SENSOR; i++) { - sprintf(buffer2, filenames[i], dev); + snprintf(buffer2, sizeof(buffer2), filenames[i], dev); state->sources[i] = open(buffer2, O_RDONLY); + snprintf(state->labels[i], sizeof(state->labels[i]), _labels_network[i], dev); } *ptr = (void *) state; @@ -134,12 +141,11 @@ void clean_network(void *ptr) free(state); } -char *_labels_network[NB_SENSOR] = {"rxp", "rxb", "txp", "txb"}; -void label_network(char **labels, void *none) +void label_network(char **labels, void *ptr) { - UNUSED(none); + struct network_t *state = (struct network_t *) ptr; for (int i = 0; i < NB_SENSOR; i++) { - labels[i] = _labels_network[i]; + labels[i] = state->labels[i]; } } -- GitLab From 72ae8099f4559689c3d8a30957a5933b695101a6 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 12:44:18 +0000 Subject: [PATCH 02/69] fix unit size --- src/amd_rapl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 09ea7c0..31944b1 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -49,7 +49,7 @@ struct cpu_sensor_t { char *name; int fd; - uint64_t energy_units; + unsigned int energy_units; uint64_t core_energy; uint64_t pkg_energy; }; @@ -107,7 +107,7 @@ uint64_t read_msr(int fd, uint64_t msr) return data; } -uint64_t read_unit(int fd) +unsigned int read_unit(int fd) { uint64_t unit = read_msr(fd, msr_rapl_power_unit); return ((unit & amd_energy_unit_mask) >> 8); @@ -127,14 +127,12 @@ uint64_t read_raw_pkg_energy(int fd) // ---------------------------------ENERGY -uint64_t raw_to_microjoule(uint64_t raw, uint64_t unit) +uint64_t raw_to_microjoule(uint64_t raw, unsigned int unit) { static const double to_microjoule = 1000000.0; - double d_raw = (double) raw; - double d_unit = (double) unit; // raw * (1 / (unit^2)) -> Joule // Joule * 1000000 -> uJoule - return ((d_raw * to_microjoule) / (d_unit * d_unit)); + return (uint64_t) (((double) raw * to_microjoule) / (double)(1U << unit)); } uint64_t raw_to_joule(uint64_t raw, uint64_t unit) { @@ -149,7 +147,7 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(cpu_sensor_t *sensor) { //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %ld, core_energy: %ld, pkg_energy: %ld\n", + printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %d, core_energy: %ld, pkg_energy: %ld\n", sensor->cpu_id, sensor->package_id, sensor->name, -- GitLab From ae734b928303fa5690dd1c51b83bc1f1e25751b1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 13:03:20 +0000 Subject: [PATCH 03/69] clear code --- src/amd_rapl.c | 52 ------------------------------------------------ tests/amd_rapl.c | 6 +++--- 2 files changed, 3 insertions(+), 55 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 31944b1..0d2ed29 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -165,20 +165,6 @@ void debug_print_amd_rapl(_amd_rapl_t *rapl) } } -// typedef struct { -// size_t cpu_id; -// uint64_t *results; -// size_t capacity; -// } CpuLogger; -// -// CpuLogger init_logger(size_t cpu_id, size_t capacity) -// { -// -// } -// -// void log_value(); - - #endif // ---------------------------AMD_RAPL_UTIL @@ -321,41 +307,3 @@ void clean_amd_rapl(void *ptr) free(rapl->sensors); free(rapl); } - -// -----------------------------ENTRY_POINT - -#ifdef __TESTING_AMD__ -#ifdef DEBUG -int main() -{ - s_round_to_uint64(1.0); - static const unsigned int time = 10; - _amd_rapl_t *rapl = NULL; - unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); - uint64_t results[nb_cpu]; - char *labels[nb_cpu]; - - label_amd_rapl(labels, (void *) rapl); - - for (unsigned int i = 0; i < rapl->nb; ++i) { - printf("%s ", labels[i]); - } - printf("\n"); - - // -- Run - - for (unsigned int i = 0; i < time; ++i) { - sleep(1); - get_amd_rapl(results, (void *)rapl); - - for (unsigned int j = 0; j < rapl->nb; ++j) { - printf("%ld ", results[j]); - } - printf("\n"); - } - - clean_amd_rapl(rapl); - return 0; -} -#endif -#endif diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 3f97f32..ddf76ae 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -11,7 +11,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 100; unit = 1000; - expected = 100; + expected = 390625; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification @@ -21,7 +21,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 200; unit = 1; - expected = 200000000; + expected = 100000000; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification @@ -41,7 +41,7 @@ TFUNCTION(test_raw_to_microjoule, { // -- Setup raw = 1000; unit = 3; - expected = 111111111; + expected = 125000000; // -- Run result = raw_to_microjoule(raw, unit); // -- Verification -- GitLab From 5d63d39b713348c4596905f0cebaba9a127dfd3b Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 31 Jan 2023 14:46:27 +0000 Subject: [PATCH 04/69] format --- tests/info_reader.c | 67 +++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/tests/info_reader.c b/tests/info_reader.c index 761d86a..9504631 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -84,28 +84,29 @@ TFUNCTION(test_start_with, { TEST_BOOLEAN(&result, &_false); }) -#define DUMB_KEYFINDER(key_finder, key, delimiter) \ - do { \ - key_finder = (KeyFinder) { \ - key, \ - delimiter, \ - 0, \ - 0 \ - }; \ - } while (0); - -#define DUMB_PARSER(parser, keys, nb_keys) \ - do { \ - parser = (Parser) { \ - 0, \ - 0, \ - 0, \ - 0, \ - keys, \ - nb_keys, \ - 0 \ - }; \ - } while (0); +#define NONE 0 +#define DUMMY_KEYFINDER(__key_finder, __key, __delimiter) \ + do { \ + __key_finder = (KeyFinder) { \ + .key = __key, \ + .delimiter = __delimiter, \ + .copy = NONE, \ + .set = NONE \ + }; \ + } while (0); + +#define DUMMY_PARSER(__parser, __keys, __nb_keys) \ + do { \ + __parser = (Parser) { \ + .storage = NONE, \ + .nb_stored = NONE, \ + .capacity = NONE, \ + .storage_struct_size = NONE, \ + .keys = __keys, \ + .nb_keys = __nb_keys, \ + .file = NONE \ + }; \ + } while (0); TFUNCTION(test_match, { @@ -121,8 +122,8 @@ TFUNCTION(test_match, { // Test 1: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_PARSER(parser, keys, 1); strcpy(line, "key: value"); found_key_finder = NULL; raw_value = NULL; @@ -135,8 +136,8 @@ TFUNCTION(test_match, { // Test 2: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1) + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_PARSER(parser, keys, 1) strcpy(line, "not a key: value"); found_key_finder = NULL; raw_value = NULL; @@ -149,8 +150,8 @@ TFUNCTION(test_match, { // Test 3: // -- Setup - DUMB_KEYFINDER(keys[0],"key", ": "); - DUMB_PARSER(parser, keys, 1); + DUMMY_KEYFINDER(keys[0],"key", ": "); + DUMMY_PARSER(parser, keys, 1); strcpy(line, "key:value"); found_key_finder = NULL; raw_value = NULL; @@ -163,9 +164,9 @@ TFUNCTION(test_match, { // Test 4: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_KEYFINDER(keys[1], "second_key", ": "); - DUMB_PARSER(parser, keys, 2); + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_KEYFINDER(keys[1], "second_key", ": "); + DUMMY_PARSER(parser, keys, 2); strcpy(line, "second_key: value"); found_key_finder = NULL; raw_value = NULL; @@ -178,8 +179,8 @@ TFUNCTION(test_match, { // Test 5: // -- Setup - DUMB_KEYFINDER(keys[0], "key", ": "); - DUMB_PARSER(parser, keys, 1); + DUMMY_KEYFINDER(keys[0], "key", ": "); + DUMMY_PARSER(parser, keys, 1); strcpy(line, ""); found_key_finder = NULL; raw_value = NULL; -- GitLab From e052fe6b71eb27213afbf631d6c25407e449aa24 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 4 Feb 2023 15:18:03 +0000 Subject: [PATCH 05/69] modification of test api --- tests/amd_rapl.c | 81 +++++++++++++++++++------------ tests/main.c | 2 +- tests/small_test.h | 115 ++++++++++++++++++++++++--------------------- 3 files changed, 115 insertions(+), 83 deletions(-) diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index ddf76ae..262c1f8 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -85,25 +85,25 @@ TFUNCTION(test_get_name, { }) #define NONE 0 -#define DUMB_SENSOR(sensor, cpu_id, name) \ - do { \ - sensor = (cpu_sensor_t) { \ - cpu_id, \ - NONE, \ - name, \ - NONE, \ - NONE, \ - NONE, \ - NONE \ - }; \ +#define DUMMY_SENSOR(__sensor, __cpu_id, __name) \ +do { \ + __sensor = (cpu_sensor_t) { \ + .cpu_id = __cpu_id, \ + .package_id = NONE, \ + .core_id = NONE, \ + .name = __name, \ + .fd = NONE, \ + .energy_units = NONE, \ + .core_energy = NONE, \ + }; \ } while(0); -#define DUMB_RAPL(rapl, sensors, nb) \ - do { \ - rapl = (_amd_rapl_t) { \ - sensors, \ - nb \ - }; \ +#define DUMMY_RAPL(__rapl, __sensors, __sensors_count) \ + do { \ + __rapl = (_amd_rapl_t) { \ + .sensors = __sensors, \ + .sensor_count = __sensors_count \ + }; \ } while(0); TFUNCTION(test_label_amd_rapl, { @@ -116,8 +116,8 @@ TFUNCTION(test_label_amd_rapl, { // Test 1: // -- Setup nb = 1; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_RAPL(rapl, sensors, nb); + DUMMY_SENSOR(sensors[0], 0, "core0"); + DUMMY_RAPL(rapl, sensors, nb); strcpy(expecteds[0], "core0"); // -- Run label_amd_rapl(results, (void *) &rapl); @@ -127,11 +127,11 @@ TFUNCTION(test_label_amd_rapl, { // Test 2: // -- Setup nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 1, "core1"); - DUMB_SENSOR(sensors[2], 2, "core2"); - DUMB_SENSOR(sensors[3], 3, "core3"); - DUMB_RAPL(rapl, sensors, nb); + DUMMY_SENSOR(sensors[0], 0, "core0"); + DUMMY_SENSOR(sensors[1], 1, "core1"); + DUMMY_SENSOR(sensors[2], 2, "core2"); + DUMMY_SENSOR(sensors[3], 3, "core3"); + DUMMY_RAPL(rapl, sensors, nb); strcpy(expecteds[0], "core0"); strcpy(expecteds[1], "core1"); strcpy(expecteds[2], "core2"); @@ -144,11 +144,11 @@ TFUNCTION(test_label_amd_rapl, { // Test 3: // -- Setup nb = 4; - DUMB_SENSOR(sensors[0], 0, "core0"); - DUMB_SENSOR(sensors[1], 3, "core3"); - DUMB_SENSOR(sensors[2], 1, "core1"); - DUMB_SENSOR(sensors[3], 2, "core2"); - DUMB_RAPL(rapl, sensors, nb); + DUMMY_SENSOR(sensors[0], 0, "core0"); + DUMMY_SENSOR(sensors[1], 3, "core3"); + DUMMY_SENSOR(sensors[2], 1, "core1"); + DUMMY_SENSOR(sensors[3], 2, "core2"); + DUMMY_RAPL(rapl, sensors, nb); strcpy(expecteds[0], "core0"); strcpy(expecteds[1], "core3"); strcpy(expecteds[2], "core1"); @@ -159,10 +159,33 @@ TFUNCTION(test_label_amd_rapl, { TEST_T_ARRAY(TEST_STR, nb, results, expecteds); }) +TFUNCTION(test_init_cpu_sensor, { + static const unsigned int max_cpus = 10; + unsigned char cpus_map[max_cpus * max_cpus]; + cpu_sensor_t sensor_t1; + unsigned int result; + unsigned int expected; + + // Test 1: + // -- Setup + memset(cpus_map, 0, max_cpus *max_cpus * sizeof(unsigned char)); + result = 0; + expected = 1; + memset(&sensor_t1, 0, sizeof(cpu_sensor_t)); + sensor_t1.cpu_id = 1; + sensor_t1.core_id = 0; + sensor_t1.package_id = 0; + // -- Run + result = init_cpu_sensor(&sensor_t1, 0, cpus_map, max_cpus); + // -- Verification + TEST_UINT64_T(&result, &expected); +}) + TFILE_ENTRY_POINT(test_amd_rapl, { CALL_TFUNCTION(test_raw_to_microjoule); CALL_TFUNCTION(test_get_name); CALL_TFUNCTION(test_label_amd_rapl); + // CALL_TFUNCTION(test_init_cpu_sensor); }) #ifdef __TESTING__AMD__ diff --git a/tests/main.c b/tests/main.c index a3a43cb..e48b56a 100644 --- a/tests/main.c +++ b/tests/main.c @@ -2,7 +2,7 @@ #include "amd_rapl.c" #include "info_reader.c" -TFILE_ENTRY_POINT(main, { +TMAIN({ CALL_TFUNCTION(test_util); CALL_TFUNCTION(test_amd_rapl); CALL_TFUNCTION(test_info_reader); diff --git a/tests/small_test.h b/tests/small_test.h index 0e39868..357479a 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -9,10 +9,23 @@ // ---------------------------API_INTERFACE + + +#define TMAIN(code) \ + int main() \ +{ \ + unsigned int __indentation_level = 0; \ + INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ + unsigned int __error_counter__ = 0; \ + do code while (0); \ + DEFERRED_FILE_ERROR(__error_counter__); \ + return __error_counter__; \ +} + /** * @brief Define the entry point of a test file. * This macro is used to define the entry point of a test file. - * It defines a function with the specified file_name that contains the test code specified in code. + * It defines a function with the specified __filename that contains the test code specified in code. * * When the function is called, it initializes the test file using the INIT_TEST_FILE macro, * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, @@ -20,17 +33,17 @@ * The function returns the value of __error_counter__, * which indicates the number of errors encountered during the tests. * - * @param file_name The name of the function that serves as the entry point for the test file. - * @param code The test code to be executed in the function. + * @param __filename The name of the function that serves as the entry point for the test file. + * @param __code The test code to be executed in the function. */ -#define TFILE_ENTRY_POINT(file_name, code) \ - int file_name() \ -{ \ - INIT_TEST_FILE();\ - int __error_counter__ = 0;\ - do code while(0);\ - DEFERRED_FILE_ERROR(__error_counter__); \ - return __error_counter__;\ +#define TFILE_ENTRY_POINT(__filename, __code) \ + int __filename (unsigned int __indentation_level) \ +{ \ + INIT_TEST_FILE(); \ + int __error_counter__ = 0; \ + do __code while(0); \ + DEFERRED_FILE_ERROR(__error_counter__); \ + return __error_counter__; \ } /** @@ -43,15 +56,15 @@ * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. * The function returns the value of __error_counter__, which indicates the number of errors encountered during the tests. * - * @param function_name The name of the test function. - * @param code The test code to be executed in the function. + * @param __function_name The name of the test function. + * @param __code The test code to be executed in the function. */ -#define TFUNCTION(function_name, code) \ - int function_name() \ +#define TFUNCTION(__function_name, __code) \ + int __function_name(unsigned int __indentation_level) \ { \ INIT_TEST_FUNCTION(); \ int __error_counter__ = 0; \ - do code while(0); \ + do __code while(0); \ DEFERRED_FUNCTION_ERROR(__error_counter__); \ return __error_counter__; \ } @@ -65,7 +78,7 @@ * @param function_name The name of the test function to be called. */ #define CALL_TFUNCTION(function_name) \ - __error_counter__ += function_name() + __error_counter__ += function_name(__indentation_level + 1) /** @@ -82,7 +95,7 @@ * @endcode */ #define TEST_STR(result, expected) \ - __error_counter__ += test_str(__FILE__, __LINE__, result, expected) + __error_counter__ += test_str(__FILE__, __LINE__, __indentation_level, result, expected) /** * @def TEST_BOOLEAN(result, expected) @@ -98,7 +111,7 @@ * @endcode */ #define TEST_BOOLEAN(result, expected) \ - __error_counter__ += test_boolean(__FILE__, __LINE__, result, expected) + __error_counter__ += test_boolean(__FILE__, __LINE__, __indentation_level, result, expected) /** * @def TEST_PTR(result, expected) @@ -116,7 +129,7 @@ * @endcode */ #define TEST_PTR(result, expected) \ - __error_counter__ += test_ptr(__FILE__, __LINE__, result, expected) + __error_counter__ += test_ptr(__FILE__, __LINE__, __indentation_level, result, expected) /** @@ -133,7 +146,7 @@ * @endcode */ #define TEST_UINT64_T(result, expected) \ - __error_counter__ += test_uint64_t(__FILE__, __LINE__, result, expected) + __error_counter__ += test_uint64_t(__FILE__, __LINE__, __indentation_level, result, expected) /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) @@ -161,6 +174,15 @@ // --------------------------------API_CODE + +#define INDENTED_PRINT(__fmt, ...) \ + do { \ + for(unsigned int i = 0; i < __indentation_level; i++) { \ + printf("| "); \ + } \ + printf(__fmt, ##__VA_ARGS__); \ + } while(0) + /** * @def INIT_TEST_FILE() * @brief Initialize the test file @@ -173,8 +195,8 @@ * INIT_TEST_FILE(); * @endcode */ -#define INIT_TEST_FILE() \ - init_test_file(__FILE__, __func__) +#define INIT_TEST_FILE() \ + INDENTED_PRINT("%s:%s\n", __FILE__, __func__) /** * @def INIT_TEST_FUNCTION() @@ -188,13 +210,14 @@ * @endcode */ #define INIT_TEST_FUNCTION() \ - init_test_function(__func__) + INDENTED_PRINT("%s()\n", __func__); #define DEFERRED_FILE_ERROR(nb_error) \ - printf("========== Deferred Error : %d\n", nb_error); + INDENTED_PRINT("|_Deferred Error : %u\n",nb_error); +//INDENTED_PRINT("Deferred Error in %s: %d\n",__FILE__, nb_error); #define DEFERRED_FUNCTION_ERROR(nb_error) \ - printf(" | Deferred Error : %d\n", nb_error); + INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); #define FMT_NULL(string) \ string = string ? string : "NULL" @@ -252,65 +275,51 @@ char *uint64_t_format(char *buffer, uint64_t *value) return buffer; } -void init_test_file(const char *file, const char *function) -{ - printf("========== TEST in %s -> %s()\n", file, function); -} - -void init_test_function(const char *function) -{ - printf("|=> %s()\n", function); -} - -int test(char *file, int line, void *result, void *expected, Comparator *compare, Formatter *format) +int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, Comparator *compare, Formatter *format) { + __indentation_level++; static char buffer_result[1000]; static char buffer_expected[1000]; int is_equal = compare(result, expected); - char c_result = is_equal ? 'V' : 'X'; - printf("[%c] | %s:%d: ", c_result, file, line); + char *fmt_result = format(buffer_result, expected); + char *fmt_expected = format(buffer_expected, result); if (!is_equal) { - printf("failed, expected %s, got %s\n", - format(buffer_result, expected), - format(buffer_expected, result) - ); - } else { - printf("passed\n"); + INDENTED_PRINT("%s:%d: failed, expected %s, got %s\n", file, line, fmt_expected, fmt_result); } return !is_equal; } -int test_str(char *file, int line, char *result, char *expected) +int test_str(char *file, int line,unsigned int __indentation_level, char *result, char *expected) { Comparator *compare = (Comparator *) string_compare; Formatter *format = (Formatter *) string_format; - return test(file, line, result, expected, compare, format); + return test(file, line, __indentation_level, result, expected, compare, format); } -int test_boolean(char *file, int line, bool *result, bool *expected) +int test_boolean(char *file, int line, unsigned int __indentation_level, bool *result, bool *expected) { Comparator *compare = (Comparator *) boolean_compare; Formatter *format = (Formatter *) boolean_format; - return test(file, line, (int *) result, (void *) expected, compare, format); + return test(file, line, __indentation_level, (int *) result, (void *) expected, compare, format); } -int test_ptr(char *file, int line, void *result, void *expected) +int test_ptr(char *file, int line, unsigned int __indentation_level, void *result, void *expected) { Comparator *compare = (Comparator *) ptr_compare; Formatter *format = (Formatter *) ptr_format; - return test(file, line, result, expected, compare, format); + return test(file, line, __indentation_level, result, expected, compare, format); } -int test_uint64_t(char *file, int line, void *result, void *expected) +int test_uint64_t(char *file, int line, unsigned int __indentation_level, void *result, void *expected) { Comparator *compare = (Comparator *) uint64_t_compare; Formatter *format = (Formatter *) uint64_t_format; - return test(file, line, (uint64_t *)result, (uint64_t *)expected, compare, format); + return test(file, line, __indentation_level, (uint64_t *)result, (uint64_t *)expected, compare, format); } #endif -- GitLab From 49943ea17c5bdcb96cd808454e3044c15d984b55 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sat, 4 Feb 2023 15:18:26 +0000 Subject: [PATCH 06/69] format --- src/amd_rapl.c | 136 +++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 0d2ed29..2f20ea2 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -25,8 +25,6 @@ #include <string.h> #include <errno.h> #include <stdlib.h> -#include <assert.h> -#include <math.h> #include "info_reader.h" #include "util.h" @@ -38,59 +36,66 @@ static const uint64_t amd_energy_mask = 0xFFFFFFFF; static const uint64_t amd_energy_unit_mask = 0x01F00; static const uint64_t msr_rapl_power_unit = 0xC0010299; static const uint64_t energy_core_msr = 0xC001029A; -static const uint64_t energy_pkg_msr = 0xC001029B; // ------------------------------FILE_PATHS static const char *base_str = "/dev/cpu/%d/msr"; struct cpu_sensor_t { - size_t cpu_id; - size_t package_id; - char *name; + unsigned int cpu_id; + unsigned int package_id; + unsigned int core_id; + char *name; int fd; + unsigned int energy_units; uint64_t core_energy; - uint64_t pkg_energy; }; typedef struct cpu_sensor_t cpu_sensor_t; struct _amd_rapl_t { cpu_sensor_t *sensors; - unsigned int nb; + unsigned int sensor_count; }; typedef struct _amd_rapl_t _amd_rapl_t; // -----------------------------INFO_READER #ifdef __READ_CPUINFO__ - #warning "Must be modified before release" #define MAX_CPUS 64 -#define NB_KEYS 2 +#define NB_KEYS 3 static const char *cpuinfo = "/proc/cpuinfo"; -static GenericPointer _size_t_allocator(char *s) + +static GenericPointer uint_allocator(char *s) { - size_t value = atoi(s); + unsigned int value = atoi(s); return (GenericPointer) value; } static void _set_cpu_id(GenericPointer storage, GenericPointer data) { cpu_sensor_t *cpu = (cpu_sensor_t *) storage; - cpu->cpu_id = (size_t) data; + cpu->cpu_id = (unsigned int) data; } static void _set_package_id(GenericPointer storage, GenericPointer data) { cpu_sensor_t *cpu = (cpu_sensor_t *) storage; - cpu->package_id = (size_t) data; + cpu->package_id = (unsigned int) data; +} + +static void _set_core_id(GenericPointer storage, GenericPointer data) +{ + cpu_sensor_t *cpu = (cpu_sensor_t *) storage; + cpu->core_id = (unsigned int) data; } static KeyFinder keys[NB_KEYS] = { - {"processor", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_cpu_id}, - {"physical id", ": ", (CopyAllocator *) _size_t_allocator, (Setter *) _set_package_id} + {"processor", ": ", uint_allocator, _set_cpu_id}, + {"physical id", ": ", uint_allocator, _set_package_id}, + {"core id", ": ", uint_allocator, _set_core_id} }; #endif @@ -119,13 +124,20 @@ uint64_t read_raw_core_energy(int fd) return energy & amd_energy_mask; } +// -------------------------READ_PKG_ENERGY + +#ifdef __READ_PKG_ENERGY__ +// TODO: Verify if these functions are still useful (the package energy can be calculed) + +static const uint64_t energy_pkg_msr = 0xC001029B; uint64_t read_raw_pkg_energy(int fd) { uint64_t energy = read_msr(fd, energy_pkg_msr); return energy & amd_energy_mask; } +#endif -// ---------------------------------ENERGY +// ----------------------------------ENERGY uint64_t raw_to_microjoule(uint64_t raw, unsigned int unit) { @@ -147,20 +159,19 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(cpu_sensor_t *sensor) { //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %ld, package_id : %ld, name : %s, fd: %d, energy_units : %d, core_energy: %ld, pkg_energy: %ld\n", + printf("cpu_id : %d, package_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", sensor->cpu_id, sensor->package_id, sensor->name, sensor->fd, sensor->energy_units, sensor->core_energy, - sensor->pkg_energy ); } void debug_print_amd_rapl(_amd_rapl_t *rapl) { - for (unsigned int i = 0; i < rapl->nb; i++) { + for (unsigned int i = 0; i < rapl->sensor_count; i++) { debug_print_sensor(&rapl->sensors[i]); } } @@ -186,57 +197,46 @@ unsigned int get_nb_cpu() return n_cpu; } -char *get_name(size_t cpu_id) +char *get_name(unsigned int cpu_id) { - static const char *base_name = "core%ld"; + static const char *base_name = "core%d"; static const size_t max_lenght = 20; char *name = (char *)calloc(max_lenght, sizeof(char)); snprintf(name, max_lenght, base_name, cpu_id); return name; } -void init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id) +void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) { + sensor->energy_units = read_unit(sensor->fd); + uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); + uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); + + *energy_consumed = modulo_substraction(core_energy, sensor->core_energy); + sensor->core_energy = core_energy; +} + +unsigned int init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id, unsigned char *cpus_map, unsigned int max_cpus) +{ + if (cpus_map[sensor->core_id * max_cpus + sensor->package_id] > 0) { + return 0; + } + cpus_map[sensor->core_id * max_cpus + sensor->package_id] += 1; + static char filename[BUFFER_SIZE]; sprintf(filename, base_str, cpu_id); int fd = open(filename, O_RDONLY); if (fd < 0) { - fprintf(stderr, "open("); fprintf(stderr, base_str, cpu_id); - perror(")"); + perror(":open()"); exit(127); } - uint64_t raw_core_energy = read_raw_core_energy(fd); - uint64_t raw_pkg_energy = read_raw_pkg_energy(fd); - sensor->cpu_id = cpu_id; sensor->name = get_name(cpu_id); sensor->fd = fd; - sensor->energy_units = read_unit(fd); - sensor->core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - sensor->pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); -} - -uint64_t get_core_energy(cpu_sensor_t *sensor) -{ - uint64_t raw_core_energy = read_raw_core_energy(sensor->fd); - uint64_t core_energy = raw_to_microjoule(raw_core_energy, sensor->energy_units); - - uint64_t energy_consumed = modulo_substraction(core_energy, sensor->core_energy); - sensor->core_energy = core_energy; - return energy_consumed; -} - -uint64_t get_pkg_energy(cpu_sensor_t *sensor) -{ - uint64_t raw_pkg_energy = read_raw_pkg_energy(sensor->fd); - uint64_t pkg_energy = raw_to_microjoule(raw_pkg_energy, sensor->energy_units); - - uint64_t energy_consumed = modulo_substraction(pkg_energy, sensor->pkg_energy); - sensor->pkg_energy = pkg_energy; - return energy_consumed; + return 1; } void clean_cpu_sensor(cpu_sensor_t *sensor) @@ -258,41 +258,42 @@ unsigned int init_amd_rapl(char *none, void **ptr) UNUSED(none); _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); - unsigned int nb_cpu = get_nb_cpu(); - if (nb_cpu == 0) { - fprintf(stderr, "open("); - fprintf(stderr, base_str,0); - perror(")"); + unsigned int max_cpus = get_nb_cpu(); + if (max_cpus == 0) { + fprintf(stderr, base_str, 0); + perror(":open()"); exit(127); } - cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(nb_cpu, sizeof(cpu_sensor_t)); - - rapl->nb = nb_cpu; + unsigned char *cpus_map = calloc(max_cpus * max_cpus, sizeof(unsigned char)); + cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); rapl->sensors = cpus; - for (unsigned int i = 0; i < nb_cpu; i++) { - init_cpu_sensor(&rapl->sensors[i], i); + unsigned int nb_cpu = 0; + for (unsigned int i = 0; i < max_cpus; i++) { + nb_cpu += init_cpu_sensor(&rapl->sensors[nb_cpu], i, cpus_map, max_cpus); } + rapl->sensor_count = nb_cpu; *ptr = (void *) rapl; - return rapl->nb; + free(cpus_map); + return rapl->sensor_count; } unsigned int get_amd_rapl(uint64_t *results, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; i++) { - results[i] = get_core_energy(&rapl->sensors[i]); + for (unsigned int i = 0; i < rapl->sensor_count; i++) { + update_cpu_sensor(&rapl->sensors[i], &results[i]); } - return rapl->nb; + return rapl->sensor_count; } void label_amd_rapl(char **labels, void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; i++) { + for (unsigned int i = 0; i < rapl->sensor_count; i++) { labels[i] = rapl->sensors[i].name; } } @@ -301,9 +302,10 @@ void clean_amd_rapl(void *ptr) { _amd_rapl_t *rapl = (_amd_rapl_t *) ptr; - for (unsigned int i = 0; i < rapl->nb; ++i) { + for (unsigned int i = 0; i < rapl->sensor_count; ++i) { clean_cpu_sensor(&rapl->sensors[i]); } free(rapl->sensors); free(rapl); } + -- GitLab From 6e2d8275d7863201bee91ee188adaadb6c2ad276 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:28:32 +0000 Subject: [PATCH 07/69] format --- tests/info_reader.c | 157 ++++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 51 deletions(-) diff --git a/tests/info_reader.c b/tests/info_reader.c index 9504631..32734c9 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -1,54 +1,117 @@ #include "small_test.h" TFUNCTION(test_replace_first, { - char test1[] = "This is my string"; - replace_first(test1, 'i', 'I'); - TEST_STR(test1, "ThIs is my string"); + // useful variables : + char result[100]; + char expected[100]; - char test2[] = "This is my string"; - replace_first(test2, 'x', 'X'); - TEST_STR(test2, "This is my string"); + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "ThIs is my string"); + // -- Run + replace_first(result, 'i', 'I'); + // -- Verification + TEST_STR(result, expected); + + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This is my string"); + // -- Run + replace_first(result, 'x', 'X'); + // -- Verification + TEST_STR(result, expected); + + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This_is my string"); + // -- Run + replace_first(result, ' ', '_'); + // -- Verification + TEST_STR(result, expected); + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This_is my string"); + // -- Run + replace_first(result, ' ', '_'); + // -- Verification + TEST_STR(result, expected); - char test3[] = "This is my string"; - replace_first(test3, ' ', '_'); - TEST_STR(test3, "This_is my string"); + // -- Setup + strcpy(result, "This is my string"); + strcpy(expected, "This is my string"); + // -- Run + replace_first(result, 'T', 'T'); + // -- Verification + TEST_STR(result, expected); }) TFUNCTION(test_split_on_delimiter, { - char test4[] = "key:value"; - char *key; - char *value; - - split_on_delimiter(test4, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test5[] = "key: value"; - split_on_delimiter(test5, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value"); - - char test6[] = "key:value"; - replace_first(test6, ':', ' '); - split_on_delimiter(test6, " ", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value"); - - char test7[] = ""; - split_on_delimiter(test7, ":", &key, &value); - TEST_STR(key, NULL); - TEST_STR(value, NULL); - - char test9[] = "key:value:extra"; - split_on_delimiter(test9, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, "value:extra"); - - char test10[] = "key: value :extra"; - split_on_delimiter(test10, ":", &key, &value); - TEST_STR(key, "key"); - TEST_STR(value, " value :extra"); + // Useful variables + char string[100]; + char *result_key; + char *result_value; + char expected_key[100]; + char expected_value[100]; + + // Setup + strcpy(string, "key:value"); + strcpy(expected_key, "key"); + strcpy(expected_value, "value"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, "key: value"); + strcpy(expected_key, "key"); + strcpy(expected_value, " value"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, "key:value"); + strcpy(expected_key, "key"); + strcpy(expected_value, "value"); + replace_first(string, ':', ' '); + // Run + split_on_delimiter(string, " ", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, ""); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, NULL); + TEST_STR(result_value, NULL); + + // Setup + strcpy(string, "key:value:extra"); + strcpy(expected_key, "key"); + strcpy(expected_value, "value:extra"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); + + // Setup + strcpy(string, "key: value :extra"); + strcpy(expected_key, "key"); + strcpy(expected_value, " value :extra"); + // Run + split_on_delimiter(string, ":", &result_key, &result_value); + // Verification + TEST_STR(result_key, expected_key); + TEST_STR(result_value, expected_value); }) TFUNCTION(test_start_with, { @@ -110,7 +173,7 @@ TFUNCTION(test_start_with, { TFUNCTION(test_match, { - // usefull variable : + // useful variables : bool _true = true; bool _false = false; KeyFinder keys[10]; @@ -198,11 +261,3 @@ TFILE_ENTRY_POINT(test_info_reader, { CALL_TFUNCTION(test_match); }) -#ifdef __TESTING_INFO_READER__ -int main() -{ - test_info_reader(); - return 0; -} -#endif - -- GitLab From be9a5e0585953b8b3ce75adf0a273a9e32babb19 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:28:47 +0000 Subject: [PATCH 08/69] print format --- tests/small_test.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/small_test.h b/tests/small_test.h index 357479a..d1aae8a 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -285,7 +285,7 @@ int test(char *file, int line, unsigned int __indentation_level, void *result, v char *fmt_result = format(buffer_result, expected); char *fmt_expected = format(buffer_expected, result); if (!is_equal) { - INDENTED_PRINT("%s:%d: failed, expected %s, got %s\n", file, line, fmt_expected, fmt_result); + INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); } return !is_equal; } -- GitLab From 221ec2635483b360fdd9d2198eba678609c6993c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:35:26 +0000 Subject: [PATCH 09/69] remove the gcc dependence --- tests/small_test.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index d1aae8a..9ac572c 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -7,10 +7,9 @@ #include <stdint.h> #include <stdio.h> -// ---------------------------API_INTERFACE - - +#include "../src/util.h" +// ---------------------------API_INTERFACE #define TMAIN(code) \ int main() \ { \ @@ -236,9 +235,10 @@ int string_compare(char *string1, char *string2) } } -char *string_format(__attribute__((unused)) char *buffer, char *string) +char *string_format(char *buffer, char *string) { - return FMT_NULL(string); + UNUSED(buffer); + return FMT_NULL(string); } @@ -247,8 +247,9 @@ int boolean_compare(bool *boolean1, bool *boolean2) return *boolean1 == *boolean2; } -char *boolean_format(__attribute__((unused)) char *buffer, bool *boolean) +char *boolean_format(char *buffer, bool *boolean) { + UNUSED(buffer); return *boolean ? "True" : "False"; } -- GitLab From 26c34e9e53e0c139f7cecf578b9bcf41e16f670b Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:39:10 +0000 Subject: [PATCH 10/69] example of how to use src/nfo_reader.c --- .../info_reader_ex.c | 43 ++++++------------- 1 file changed, 12 insertions(+), 31 deletions(-) rename tests/example_info_reader.c => doc/info_reader_ex.c (76%) diff --git a/tests/example_info_reader.c b/doc/info_reader_ex.c similarity index 76% rename from tests/example_info_reader.c rename to doc/info_reader_ex.c index 1dd6464..38d948a 100644 --- a/tests/example_info_reader.c +++ b/doc/info_reader_ex.c @@ -1,23 +1,20 @@ #include "info_reader.h" #include <stdint.h> -#ifdef DEBUG -#warning "PTR_TO_TPTR hide a cast warning" -#endif - #define MAX_PROCS 2 +#define NB_KEYS 6 typedef struct { - size_t processor; + unsigned int processor; char *vendor_id; - size_t family; - size_t core_id; - size_t physical_id; + unsigned int family; + unsigned int core_id; + unsigned int physical_id; char *model_name; } Cpu; GenericPointer int_allocator(char *s) { - size_t value = atoi(s); + unsigned int value = atoi(s); return (GenericPointer) value; } @@ -59,19 +56,6 @@ void set_model_name(GenericPointer storage, GenericPointer data) cpu->model_name = (char *) data; } -struct cpu_sensor_t { - //TODO: check the reset of the msr registers -#warning "Check the reset of the msr registers" - size_t cpu_id; - size_t package_id; - char *name; - - int *fd; - uint64_t energy_units; - uint64_t core_energy; - uint64_t pkg_energy; -}; - int main(int argc, char const *argv[]) { Cpu cpus[MAX_PROCS]; @@ -91,7 +75,7 @@ int main(int argc, char const *argv[]) .capacity = MAX_PROCS, .storage_struct_size = sizeof(Cpu), .keys = keys, - .nb_keys = 6, + .nb_keys = NB_KEYS, .file = fopen("/proc/cpuinfo", "r") }; @@ -99,19 +83,16 @@ int main(int argc, char const *argv[]) for (unsigned int i = 0; i < parser.nb_stored; ++i) { printf("========== PROC[%d] ==========\n", i); - printf("Processor: %ld\n", cpus[i].processor); + printf("Processor: %u\n", cpus[i].processor); printf("Vendor ID: %s\n", cpus[i].vendor_id); - printf("Family: %ld\n", cpus[i].family); - printf("Core ID: %ld\n", cpus[i].core_id); - printf("Physical ID: %ld\n", cpus[i].physical_id); + printf("Family: %u\n", cpus[i].family); + printf("Core ID: %u\n", cpus[i].core_id); + printf("Physical ID: %u\n", cpus[i].physical_id); printf("Model Name: %s\n", cpus[i].model_name); - printf("==============================\n"); free(cpus[i].vendor_id); free(cpus[i].model_name); } - - printf("size = %ld\n", sizeof (struct cpu_sensor_t)); - + printf("==============================\n"); return 0; } -- GitLab From d1d5853bdd89bf2dac4b707d163958542aa5ac76 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 08:39:44 +0000 Subject: [PATCH 11/69] format --- doc/info_reader_ex.c | 2 +- tests/small_test.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 38d948a..6b284a5 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -92,7 +92,7 @@ int main(int argc, char const *argv[]) free(cpus[i].vendor_id); free(cpus[i].model_name); } - printf("==============================\n"); + printf("==============================\n"); return 0; } diff --git a/tests/small_test.h b/tests/small_test.h index 9ac572c..33c34c6 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -237,8 +237,8 @@ int string_compare(char *string1, char *string2) char *string_format(char *buffer, char *string) { - UNUSED(buffer); - return FMT_NULL(string); + UNUSED(buffer); + return FMT_NULL(string); } -- GitLab From d8d7594057326d29a07d48057cfba3574df122e8 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 09:00:30 +0000 Subject: [PATCH 12/69] cleanup --- doc/info_reader_ex.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 6b284a5..23ee7d5 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -1,8 +1,30 @@ -#include "info_reader.h" -#include <stdint.h> +/******************************************************* + 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/>. + +*******************************************************/ + + +// ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex +#include "./../src/info_reader.h" #define MAX_PROCS 2 #define NB_KEYS 6 + typedef struct { unsigned int processor; char *vendor_id; @@ -56,7 +78,7 @@ void set_model_name(GenericPointer storage, GenericPointer data) cpu->model_name = (char *) data; } -int main(int argc, char const *argv[]) +int main() { Cpu cpus[MAX_PROCS]; KeyFinder keys[] = { -- GitLab From 730f969f8cd60054edf8cc995650fdee0f9d2d44 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:14:21 +0000 Subject: [PATCH 13/69] add test example --- doc/test_file_ex.c | 112 +++++++++++++++++++++++++++++++++++++++++++++ doc/test_main_ex | Bin 0 -> 17416 bytes doc/test_main_ex.c | 35 ++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 doc/test_file_ex.c create mode 100755 doc/test_main_ex create mode 100644 doc/test_main_ex.c diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c new file mode 100644 index 0000000..44ebc2c --- /dev/null +++ b/doc/test_file_ex.c @@ -0,0 +1,112 @@ +/******************************************************* + 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 of the test library +#include "./../tests/small_test.h" + +// -- A simple function that should pass +TFUNCTION(test_should_pass, { + char *result = "It's going to pass"; + char *expected = "It's going to pass"; + TEST_STR(result, expected); +}) + +// -- A simple function that should fail +TFUNCTION(test_should_fail, { + char *result = "a fail"; + char *expected = "a nice fail"; + TEST_STR(result, expected); +}) + +// -- Add a new type in the test framework + +typedef struct { + int simple_int; + char simple_str[20]; +} UserType; + + +// -- Implemet the interface +int usertype_compare(void *ptr1, void *ptr2) +{ + return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; +} + +char *usertype_format(char buffer[1000], void *ptr) +{ + UserType *x = (UserType *) ptr; + sprintf(buffer, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); + return buffer; +} + +// Create a variable which contains the functions +static const TestInterface usertype_interface = { + .compare = usertype_compare, + .format = usertype_format +}; + +// -- Create the test macro to call +#define TEST_USER_TYPE(__result, __expected) \ + TEST_INTERFACE(__result, __expected, &usertype_interface); + +// -- Create a macro setter +#define DUMMY_USER_TYPE(__user, __simple_int, __simple_str) \ + do { \ + __user = (UserType) { \ + .simple_int = __simple_int, \ + .simple_str = __simple_str \ + }; \ +} while (0); + +// -- Compare two usertype +TFUNCTION(test_user_type, { + UserType x1; + UserType x2; + + DUMMY_USER_TYPE(x1, 1, "John Doe"); + DUMMY_USER_TYPE(x2, 1, "John Doe"); + + TEST_USER_TYPE(&x1, &x2); +}) + + +// -- Compare an array of usetype +TFUNCTION(test_array_user_type, { + UserType *results[1]; + UserType *expecteds[1]; + + UserType x1; + UserType x2; + DUMMY_USER_TYPE(x1, 1, "John Doe"); + DUMMY_USER_TYPE(x2, 1, "John Doe"); + + results[0] = &x1; + expecteds[0] = &x2; + + TEST_T_ARRAY(TEST_USER_TYPE, 1, (void **)results, (void **)expecteds); +}) + +// Define the entry point of a test file +TFILE_ENTRY_POINT(test_file_ex, { + CALL_TFUNCTION(test_should_pass); + CALL_TFUNCTION(test_should_fail); + CALL_TFUNCTION(test_user_type); + CALL_TFUNCTION(test_array_user_type); +}) diff --git a/doc/test_main_ex b/doc/test_main_ex new file mode 100755 index 0000000000000000000000000000000000000000..0ab7870283c6ba20a50b3761a1c009eb89f3ac20 GIT binary patch literal 17416 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 A`~Uy| literal 0 HcmV?d00001 diff --git a/doc/test_main_ex.c b/doc/test_main_ex.c new file mode 100644 index 0000000..0aa86b9 --- /dev/null +++ b/doc/test_main_ex.c @@ -0,0 +1,35 @@ +/******************************************************* + 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/>. + +*******************************************************/ + +// ~/mojitos/doc$ gcc -Wall -Wextra -Wpedantic -o test_main_ex test_main_ex.c ./../src/util.c +// Include of the test library +#include "./../tests/small_test.h" + +// Include the *.c files that contain the tests +#include "./test_file_ex.c" +// #include "./test_another_test_file.c" + +// Define the entry point of the programme +TMAIN({ + // Must contain the call to the entry point functions of each file + // USE CALL_TFUNCTION(my_function) instead of my_function() + CALL_TFUNCTION(test_file_ex); + // CALL_TFUNCTION(another_file_entry_point_function); +}) -- GitLab From e16dc9f4d47bc55b5875136ff06629459839ffca Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:14:43 +0000 Subject: [PATCH 14/69] add licence --- src/amd_rapl.c | 2 +- src/amd_rapl.h | 2 +- tests/amd_rapl.c | 20 ++++ tests/info_reader.c | 40 ++++++-- tests/main.c | 20 ++++ tests/small_test.h | 216 +++++++++++++++++++++++++------------------- tests/util.c | 20 ++++ 7 files changed, 215 insertions(+), 105 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 2f20ea2..51df298 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 4f375b9..f16ed4f 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -1,5 +1,5 @@ /******************************************************* - Copyright (C) 2022-2023 Georges Da Costa <georges.da-costa@irit.fr> + Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> This file is part of Mojitos. diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 262c1f8..39214fc 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -1,3 +1,23 @@ +/******************************************************* + 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/amd_rapl.c" diff --git a/tests/info_reader.c b/tests/info_reader.c index 32734c9..b2a8c6f 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -1,3 +1,23 @@ +/******************************************************* + 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" TFUNCTION(test_replace_first, { @@ -124,27 +144,27 @@ TFUNCTION(test_start_with, { prefix = "Hello"; string = "Hello World"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); prefix = "Goodbye"; string = "Hello World"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); prefix = "Hello World"; string = "Hello"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); prefix = "Hello"; string = "Hello"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); prefix = NULL; string = "Hello World"; result = start_with(prefix, string); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); }) #define NONE 0 @@ -193,7 +213,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); TEST_PTR(found_key_finder, &keys[0]); TEST_STR(raw_value, "value"); @@ -207,7 +227,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); TEST_PTR(found_key_finder, NULL); TEST_STR(raw_value, NULL); @@ -221,7 +241,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); TEST_PTR(found_key_finder, NULL); TEST_STR(raw_value, NULL); @@ -236,7 +256,7 @@ TFUNCTION(test_match, { // -- Run result = match(&parser, line, &found_key_finder, &raw_value); // -- Verification - TEST_BOOLEAN(&result, &_true); + TEST_BOOL(&result, &_true); TEST_PTR(found_key_finder, &keys[1]); TEST_STR(raw_value, "value"); @@ -249,7 +269,7 @@ TFUNCTION(test_match, { raw_value = NULL; // -- Run result = match(&parser, line, &found_key_finder, &raw_value); - TEST_BOOLEAN(&result, &_false); + TEST_BOOL(&result, &_false); TEST_PTR(found_key_finder, NULL); TEST_STR(raw_value, NULL); }) diff --git a/tests/main.c b/tests/main.c index e48b56a..3246f04 100644 --- a/tests/main.c +++ b/tests/main.c @@ -1,3 +1,23 @@ +/******************************************************* + 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 "util.c" #include "amd_rapl.c" #include "info_reader.c" diff --git a/tests/small_test.h b/tests/small_test.h index 33c34c6..9f6a6d9 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -1,3 +1,23 @@ +/******************************************************* + 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/>. + +*******************************************************/ + #ifndef __SMALL_TEST_H #define __SMALL_TEST_H @@ -77,49 +97,48 @@ * @param function_name The name of the test function to be called. */ #define CALL_TFUNCTION(function_name) \ - __error_counter__ += function_name(__indentation_level + 1) - + do {__error_counter__ += function_name(__indentation_level + 1);} while(0) /** * @def TEST_STR(result, expected) * @brief Test strings - * This macro is used to test strings. It takes two arguments: `result`, which is the string to be tested, and `expected`, which is the expected value of the string. + * This macro is used to test strings. It takes two arguments: `__result`, which is the string to be tested, and `__expected`, which is the expected value of the string. * The macro uses the `test_str()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the string to be tested - * @param expected the expected value of the string + * @param __result the string to be tested + * @param __expected the expected value of the string * * @code * TEST_STR("Hello", "Hello"); * @endcode */ -#define TEST_STR(result, expected) \ - __error_counter__ += test_str(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_STR(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &str_interface);} while(0) /** - * @def TEST_BOOLEAN(result, expected) - * @brief Test booleans - * This macro is used to test booleans. It takes two arguments: `result`, which is the boolean to be tested, and `expected`, which is the expected value of the boolean. - * The macro uses the `test_boolean()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. + * @def TEST_BOOL(__result, __expected) + * @brief Test bools + * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to be tested, and `__expected`, which is the expected value of the bool. + * The macro uses the `test_bool()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the boolean to be tested - * @param expected the expected value of the boolean + * @param __result the bool to be tested + * @param __expected the expected value of the bool * * @code - * TEST_BOOLEAN(1 == 1, true); + * TEST_BOOL(1 == 1, true); * @endcode */ -#define TEST_BOOLEAN(result, expected) \ - __error_counter__ += test_boolean(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_BOOL(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &bool_interface);} while (0) /** - * @def TEST_PTR(result, expected) + * @def TEST_PTR(__result, __expected) * @brief Test pointers - * This macro is used to test pointers. It takes two arguments: `result`, which is the pointer to be tested, and `expected`, which is the expected value of the pointer. + * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to be tested, and `__expected`, which is the expected value of the pointer. * The macro uses the `test_ptr()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the pointer to be tested - * @param expected the expected value of the pointer + * @param __result the pointer to be tested + * @param __expected the expected value of the pointer * * @code * int x = 5; @@ -127,47 +146,48 @@ * TEST_PTR(ptr, &x); * @endcode */ -#define TEST_PTR(result, expected) \ - __error_counter__ += test_ptr(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_PTR(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &ptr_interface);} while(0) /** - * @def TEST_UINT64_T(result, expected) + * @def TEST_UINT64_T(__result, __expected) * @brief Test 64-bit unsigned integers - * This macro is used to test 64-bit unsigned integers. It takes two arguments: `result`, which is the integer to be tested, and `expected`, which is the expected value of the integer. + * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, which is the integer to be tested, and `__expected`, which is the expected value of the integer. * The macro uses the `test_uint64_t()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param result the integer to be tested - * @param expected the expected value of the integer + * @param __result the integer to be tested + * @param __expected the expected value of the integer * * @code * TEST_UINT64_T(5, 5); * @endcode */ -#define TEST_UINT64_T(result, expected) \ - __error_counter__ += test_uint64_t(__FILE__, __LINE__, __indentation_level, result, expected) +#define TEST_UINT64_T(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) + +#define TEST_INTERFACE(__result, __expected, __interface) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) * @brief Test arrays of data - * The macro uses a for loop to iterate through the array and apply the test function to each element, - * adding any errors to the nb_error variable. + * The macro uses a for loop to iterate through the array and apply the test function to each element. * - * @param function the test function to be used on each element of the array - * @param nb_error the number of errors encountered during the test - * @param size the number of elements in the array - * @param results the array of elements to be tested - * @param expecteds the array of expected values + * @param __test_macro the test function to be used on each element of the array + * @param __array_size the number of elements in the array + * @param __results the array of elements to be tested + * @param __expecteds the array of expected values * @code * int results[3] = {1, 2, 3}; * int expecteds[3] = {1, 2, 3}; - * TEST_T_ARRAY(TEST_INT, errors, 3, results, expecteds); + * TEST_T_ARRAY(TEST_INT, 3, results, expecteds); * @endcode */ -#define TEST_T_ARRAY(function, size, results, expecteds) \ - for (unsigned int i = 0; i < size; i++) { \ - function(results[i], expecteds[i]); \ +#define TEST_T_ARRAY(__test_macro, __array_size, __results, __expecteds) \ + for (unsigned int i = 0; i < __array_size; i++) { \ + __test_macro(__results[i], __expecteds[i]); \ } @@ -213,46 +233,71 @@ #define DEFERRED_FILE_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %u\n",nb_error); -//INDENTED_PRINT("Deferred Error in %s: %d\n",__FILE__, nb_error); #define DEFERRED_FUNCTION_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); -#define FMT_NULL(string) \ - string = string ? string : "NULL" - typedef int (Comparator) (void *, void *); typedef char *(Formatter) (char *, void *); -int string_compare(char *string1, char *string2) +typedef struct { + Comparator *compare; + Formatter *format; +} TestInterface; + +// ---------------------------str_interface + +int str_compare(void *ptr1, void *ptr2) { - if (string1 == NULL && string2 == NULL) { + char *str1 = (char *) ptr1; + char *str2 = (char *) ptr2; + + if (str1 == NULL && str2 == NULL) { return 1; - } else if (string1 == NULL || string2 == NULL) { + } else if (str1 == NULL || str2 == NULL) { return 0; } else { - return (strcmp(string1, string2) == 0); + return (strcmp(str1, str2) == 0); } } -char *string_format(char *buffer, char *string) +char *str_format(char *buffer, void *ptr) { UNUSED(buffer); - return FMT_NULL(string); + static char *str_null = "NULL"; + char *str = (char *) ptr; + return str ? str : str_null; } +static const TestInterface str_interface = { + .compare = str_compare, + .format = str_format +}; + +// --------------------------bool_interface -int boolean_compare(bool *boolean1, bool *boolean2) + +int bool_compare(void *ptr1, void *ptr2) { - return *boolean1 == *boolean2; + bool *bool1 = (bool *) ptr1; + bool *bool2 = (bool *) ptr2; + return *bool1 == *bool2; } -char *boolean_format(char *buffer, bool *boolean) +char *bool_format(char *buffer, void *ptr) { UNUSED(buffer); - return *boolean ? "True" : "False"; + bool *_bool = (bool *) ptr; + return *_bool ? "True" : "False"; } +static const TestInterface bool_interface = { + .compare = bool_compare, + .format = bool_format +}; + +// ---------------------------ptr_interface + int ptr_compare(void *ptr1, void *ptr2) { return ptr1 == ptr2; @@ -264,63 +309,48 @@ char *ptr_format(char *buffer, void *ptr) return buffer; } +static const TestInterface ptr_interface = { + .compare = ptr_compare, + .format = ptr_format +}; + +// ---------------------------u64_interface -int uint64_t_compare(uint64_t *value1, uint64_t *value2) +int u64_compare(void *ptr1, void *ptr2) { - return *value1 == *value2; + uint64_t *v1 = (uint64_t *) ptr1; + uint64_t *v2 = (uint64_t *) ptr2; + return *v1 == *v2; } -char *uint64_t_format(char *buffer, uint64_t *value) +char *u64_format(char *buffer, void *ptr) { - sprintf(buffer, "%"PRIu64"", *value); + uint64_t *v = (uint64_t *) ptr; + sprintf(buffer, "%"PRIu64"", *v); return buffer; } -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, Comparator *compare, Formatter *format) +static const TestInterface u64_interface = { + .compare = u64_compare, + .format = u64_format +}; + +// ---------------------------test_function + +int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) { - __indentation_level++; + __indentation_level += 1; static char buffer_result[1000]; static char buffer_expected[1000]; - int is_equal = compare(result, expected); + int is_equal = interface->compare(result, expected); - char *fmt_result = format(buffer_result, expected); - char *fmt_expected = format(buffer_expected, result); + char *fmt_result = interface->format(buffer_expected, expected); + char *fmt_expected = interface->format(buffer_result, result); if (!is_equal) { INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); } return !is_equal; } -int test_str(char *file, int line,unsigned int __indentation_level, char *result, char *expected) -{ - Comparator *compare = (Comparator *) string_compare; - Formatter *format = (Formatter *) string_format; - - return test(file, line, __indentation_level, result, expected, compare, format); -} - -int test_boolean(char *file, int line, unsigned int __indentation_level, bool *result, bool *expected) -{ - Comparator *compare = (Comparator *) boolean_compare; - Formatter *format = (Formatter *) boolean_format; - - return test(file, line, __indentation_level, (int *) result, (void *) expected, compare, format); -} - -int test_ptr(char *file, int line, unsigned int __indentation_level, void *result, void *expected) -{ - Comparator *compare = (Comparator *) ptr_compare; - Formatter *format = (Formatter *) ptr_format; - - return test(file, line, __indentation_level, result, expected, compare, format); -} - -int test_uint64_t(char *file, int line, unsigned int __indentation_level, void *result, void *expected) -{ - Comparator *compare = (Comparator *) uint64_t_compare; - Formatter *format = (Formatter *) uint64_t_format; - - return test(file, line, __indentation_level, (uint64_t *)result, (uint64_t *)expected, compare, format); -} #endif diff --git a/tests/util.c b/tests/util.c index a91c58f..69941bf 100644 --- a/tests/util.c +++ b/tests/util.c @@ -1,3 +1,23 @@ +/******************************************************* + 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 "../src/util.h" #include "small_test.h" -- GitLab From 22cbdb2ae7804be8f3a03610175c3b4e56c93dc0 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:26:23 +0000 Subject: [PATCH 15/69] add informations --- tests/small_test.h | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index 9f6a6d9..aedc685 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -30,6 +30,11 @@ #include "../src/util.h" // ---------------------------API_INTERFACE +/** + * @brief Define the entry point of the tests + * It initializes each useful variables. + */ + #define TMAIN(code) \ int main() \ { \ @@ -169,6 +174,7 @@ #define TEST_INTERFACE(__result, __expected, __interface) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) + /** * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) * @brief Test arrays of data @@ -192,6 +198,7 @@ // --------------------------------API_CODE +// These functions should not be used, only use the previous macros. #define INDENTED_PRINT(__fmt, ...) \ @@ -202,32 +209,10 @@ printf(__fmt, ##__VA_ARGS__); \ } while(0) -/** - * @def INIT_TEST_FILE() - * @brief Initialize the test file - * This macro is used to initialize the test file. It takes the `__FILE__` and `__func__` preprocessor macros as arguments, which provide the name of the current file and the current function, respectively. - * - * @param __FILE__ preprocessor macro that provides the name of the current file - * @param __func__ preprocessor macro that provides the name of the current function - * - * @code - * INIT_TEST_FILE(); - * @endcode - */ + #define INIT_TEST_FILE() \ INDENTED_PRINT("%s:%s\n", __FILE__, __func__) -/** - * @def INIT_TEST_FUNCTION() - * @brief Initialize the test function - * This macro is used to initialize the test function. It takes the `__func__` preprocessor macro as an argument, which provides the name of the current function. - * - * @param __func__ preprocessor macro that provides the name of the current function - * - * @code - * INIT_TEST_FUNCTION(); - * @endcode - */ #define INIT_TEST_FUNCTION() \ INDENTED_PRINT("%s()\n", __func__); -- GitLab From 95956fd34bad0e160dd15e96f25d006eef8df7a1 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:27:51 +0000 Subject: [PATCH 16/69] remove bin --- doc/test_main_ex | Bin 17416 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 doc/test_main_ex diff --git a/doc/test_main_ex b/doc/test_main_ex deleted file mode 100755 index 0ab7870283c6ba20a50b3761a1c009eb89f3ac20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17416 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 A`~Uy| -- GitLab From 427ee8f328e16521aa18d3778f9b769c417a5fba Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Sun, 5 Feb 2023 12:29:11 +0000 Subject: [PATCH 17/69] ignore new bin --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8110229..dd136f4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ obj *.swp *.swo .vscode +doc/test_main_ex +doc/info_reader_ex -- GitLab From fb5106fc764e64a741fe9a5e97e67e4184fb1f09 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 10:04:56 +0000 Subject: [PATCH 18/69] fix: NB_MAX cpu --- doc/info_reader_ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 23ee7d5..5cfa5f4 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -22,7 +22,7 @@ // ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex #include "./../src/info_reader.h" -#define MAX_PROCS 2 +#define MAX_PROCS 64 #define NB_KEYS 6 typedef struct { -- GitLab From 844433049c8f02aab7238679b6d052d2f84aa0ff Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 10:05:38 +0000 Subject: [PATCH 19/69] core: amd_rapl.c --- src/amd_rapl.c | 92 ++++++++++++++++++++++++++++++++++++------------ tests/amd_rapl.c | 34 +++--------------- 2 files changed, 74 insertions(+), 52 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 51df298..f6eff43 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -30,6 +30,7 @@ #include "util.h" #define BUFFER_SIZE 64 +#define __READ_CPUINFO__ // ---------------------------MSR_REGISTERS static const uint64_t amd_energy_mask = 0xFFFFFFFF; @@ -62,11 +63,9 @@ typedef struct _amd_rapl_t _amd_rapl_t; // -----------------------------INFO_READER #ifdef __READ_CPUINFO__ -#warning "Must be modified before release" -#define MAX_CPUS 64 #define NB_KEYS 3 -static const char *cpuinfo = "/proc/cpuinfo"; +static char *cpuinfo = "/proc/cpuinfo"; static GenericPointer uint_allocator(char *s) { @@ -97,6 +96,21 @@ static KeyFinder keys[NB_KEYS] = { {"physical id", ": ", uint_allocator, _set_package_id}, {"core id", ": ", uint_allocator, _set_core_id} }; + + +static unsigned int parse_cpuinfo(cpu_sensor_t* storage, unsigned int capacity) { + Parser parser = { + .storage = (GenericPointer) storage, + .nb_stored = 0, + .capacity = capacity, + .storage_struct_size = sizeof(cpu_sensor_t), + .keys = keys, + .nb_keys = NB_KEYS, + .file = fopen(cpuinfo, "r") + }; + return parse(&parser); +} + #endif // --------------------------------READ_MSR @@ -159,13 +173,14 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(cpu_sensor_t *sensor) { //CASSERT(sizeof(cpu_sensor_t) == 56, amd_rapl_c); - printf("cpu_id : %d, package_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", + printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", sensor->cpu_id, sensor->package_id, + sensor->core_id, sensor->name, sensor->fd, sensor->energy_units, - sensor->core_energy, + sensor->core_energy ); } @@ -197,6 +212,22 @@ unsigned int get_nb_cpu() return n_cpu; } +void get_arch(unsigned int *ret_nb_package, unsigned int *ret_nb_core, cpu_sensor_t *sensors, unsigned int nb_sensor) +{ + unsigned int nb_package = 0; + unsigned int nb_core = 0; + for (unsigned int i = 0; i < nb_sensor; i++) { + if (sensors[i].package_id > nb_package) { + nb_package = sensors[i].package_id; + } + if (sensors[i].core_id > nb_core) { + nb_core = sensors[i].core_id; + } + } + *ret_nb_package = nb_package + 1; + *ret_nb_core = nb_core + 1; +} + char *get_name(unsigned int cpu_id) { static const char *base_name = "core%d"; @@ -216,27 +247,29 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int init_cpu_sensor(cpu_sensor_t *sensor, unsigned int cpu_id, unsigned char *cpus_map, unsigned int max_cpus) -{ - if (cpus_map[sensor->core_id * max_cpus + sensor->package_id] > 0) { - return 0; +unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) { + if (map[sensor->core_id * nb_core + sensor->package_id]) { + return 1; } - cpus_map[sensor->core_id * max_cpus + sensor->package_id] += 1; + map[sensor->core_id * nb_core + sensor->package_id] += 1; + return 0; +} +void init_cpu_sensor(cpu_sensor_t *sensor, cpu_sensor_t *cpu_info) +{ static char filename[BUFFER_SIZE]; - sprintf(filename, base_str, cpu_id); + snprintf(filename,BUFFER_SIZE, base_str, cpu_info->cpu_id); int fd = open(filename, O_RDONLY); if (fd < 0) { - fprintf(stderr, base_str, cpu_id); + fprintf(stderr, base_str, cpu_info->cpu_id); perror(":open()"); exit(127); } - sensor->cpu_id = cpu_id; - sensor->name = get_name(cpu_id); + memcpy(sensor, cpu_info, sizeof(cpu_sensor_t)); + sensor->name = get_name(sensor->cpu_id); sensor->fd = fd; - return 1; } void clean_cpu_sensor(cpu_sensor_t *sensor) @@ -256,7 +289,6 @@ void free_amd_rapl(_amd_rapl_t *rapl) unsigned int init_amd_rapl(char *none, void **ptr) { UNUSED(none); - _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); unsigned int max_cpus = get_nb_cpu(); if (max_cpus == 0) { @@ -265,18 +297,32 @@ unsigned int init_amd_rapl(char *none, void **ptr) exit(127); } - unsigned char *cpus_map = calloc(max_cpus * max_cpus, sizeof(unsigned char)); - cpu_sensor_t *cpus = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); - rapl->sensors = cpus; + cpu_sensor_t *cpu_information = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); + if (parse_cpuinfo(cpu_information, max_cpus)) { + free(cpu_information); + PANIC(1, "cpuinfo"); + } - unsigned int nb_cpu = 0; + unsigned int nb_package; + unsigned int nb_core; + get_arch(&nb_package, &nb_core, cpu_information, max_cpus); + + unsigned char *cpu_map = (unsigned char*) calloc(nb_core * nb_package, sizeof(unsigned char)); + cpu_sensor_t *sensors = (cpu_sensor_t*) calloc(max_cpus, sizeof(cpu_sensor_t)); + + unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - nb_cpu += init_cpu_sensor(&rapl->sensors[nb_cpu], i, cpus_map, max_cpus); + if (!is_duplicate(cpu_information, cpu_map, nb_core)) { + init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); + sensor_count += 1; + } } - rapl->sensor_count = nb_cpu; + free(cpu_information); + _amd_rapl_t *rapl = (_amd_rapl_t *) calloc(1, sizeof(_amd_rapl_t)); + rapl->sensors = sensors; + rapl->sensor_count = sensor_count; *ptr = (void *) rapl; - free(cpus_map); return rapl->sensor_count; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 39214fc..2425287 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -179,48 +179,24 @@ TFUNCTION(test_label_amd_rapl, { TEST_T_ARRAY(TEST_STR, nb, results, expecteds); }) -TFUNCTION(test_init_cpu_sensor, { - static const unsigned int max_cpus = 10; - unsigned char cpus_map[max_cpus * max_cpus]; - cpu_sensor_t sensor_t1; - unsigned int result; - unsigned int expected; - - // Test 1: - // -- Setup - memset(cpus_map, 0, max_cpus *max_cpus * sizeof(unsigned char)); - result = 0; - expected = 1; - memset(&sensor_t1, 0, sizeof(cpu_sensor_t)); - sensor_t1.cpu_id = 1; - sensor_t1.core_id = 0; - sensor_t1.package_id = 0; - // -- Run - result = init_cpu_sensor(&sensor_t1, 0, cpus_map, max_cpus); - // -- Verification - TEST_UINT64_T(&result, &expected); -}) - TFILE_ENTRY_POINT(test_amd_rapl, { CALL_TFUNCTION(test_raw_to_microjoule); CALL_TFUNCTION(test_get_name); CALL_TFUNCTION(test_label_amd_rapl); - // CALL_TFUNCTION(test_init_cpu_sensor); }) #ifdef __TESTING__AMD__ int main() { - test_amd_rapl(); static const unsigned int time = 10; _amd_rapl_t *rapl = NULL; - unsigned int nb_cpu = init_amd_rapl(NULL, (void **) &rapl); - uint64_t results[nb_cpu]; - char *labels[nb_cpu]; + unsigned int count_cpu = init_amd_rapl(NULL, (void **) &rapl); + uint64_t results[count_cpu]; + char *labels[count_cpu]; label_amd_rapl(labels, (void *) rapl); - for (unsigned int i = 0; i < rapl->nb; ++i) { + for (unsigned int i = 0; i < rapl->sensor_count; ++i) { printf("%s ", labels[i]); } printf("\n"); @@ -231,7 +207,7 @@ int main() sleep(1); get_amd_rapl(results, (void *)rapl); - for (unsigned int j = 0; j < rapl->nb; ++j) { + for (unsigned int j = 0; j < rapl->sensor_count; ++j) { printf("%ld ", results[j]); } printf("\n"); -- GitLab From 76653cfafb1f60a31791a761fcd41d5c54b6b9c4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 11:47:35 +0000 Subject: [PATCH 20/69] core: small_test modification of the api --- doc/info_reader_ex.c | 2 +- doc/test_file_ex.c | 31 ++++++++---- src/amd_rapl.c | 14 +++--- tests/amd_rapl.c | 116 ++++++++++++++++++++++++++++++++++++++---- tests/small_test.h | 117 +++++++++++++++++++++++++++++++++++-------- 5 files changed, 231 insertions(+), 49 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index 5cfa5f4..f672d98 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -22,7 +22,7 @@ // ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex #include "./../src/info_reader.h" -#define MAX_PROCS 64 +#define MAX_PROCS 64 #define NB_KEYS 6 typedef struct { diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 44ebc2c..4e3a093 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -35,6 +35,20 @@ TFUNCTION(test_should_fail, { TEST_STR(result, expected); }) +// -- A simple test of array +TFUNCTION(test_array, { + static unsigned int size = 10; + int array[10]; + TEST_ARRAY(TEST_INT, size, array, array); +}) + +// -- A simple test of array of pointer +TFUNCTION(test_ptr_array, { + static unsigned int size = 10; + void *array[10]; + TEST_PTR_ARRAY(TEST_PTR, size, array, array); +}) + // -- Add a new type in the test framework typedef struct { @@ -89,24 +103,21 @@ TFUNCTION(test_user_type, { // -- Compare an array of usetype TFUNCTION(test_array_user_type, { - UserType *results[1]; - UserType *expecteds[1]; - - UserType x1; - UserType x2; - DUMMY_USER_TYPE(x1, 1, "John Doe"); - DUMMY_USER_TYPE(x2, 1, "John Doe"); + UserType results[1]; + UserType expecteds[1]; - results[0] = &x1; - expecteds[0] = &x2; + DUMMY_USER_TYPE(results[0], 1, "John Doe"); + DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - TEST_T_ARRAY(TEST_USER_TYPE, 1, (void **)results, (void **)expecteds); + TEST_ARRAY(TEST_USER_TYPE, 1, results, expecteds); }) // Define the entry point of a test file TFILE_ENTRY_POINT(test_file_ex, { CALL_TFUNCTION(test_should_pass); CALL_TFUNCTION(test_should_fail); + CALL_TFUNCTION(test_array); + CALL_TFUNCTION(test_ptr_array); CALL_TFUNCTION(test_user_type); CALL_TFUNCTION(test_array_user_type); }) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index f6eff43..1d9bc37 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -98,7 +98,8 @@ static KeyFinder keys[NB_KEYS] = { }; -static unsigned int parse_cpuinfo(cpu_sensor_t* storage, unsigned int capacity) { +static unsigned int parse_cpuinfo(cpu_sensor_t *storage, unsigned int capacity) +{ Parser parser = { .storage = (GenericPointer) storage, .nb_stored = 0, @@ -247,12 +248,13 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) { +unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) +{ if (map[sensor->core_id * nb_core + sensor->package_id]) { - return 1; + return 0; } map[sensor->core_id * nb_core + sensor->package_id] += 1; - return 0; + return 1; } void init_cpu_sensor(cpu_sensor_t *sensor, cpu_sensor_t *cpu_info) @@ -307,8 +309,8 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int nb_core; get_arch(&nb_package, &nb_core, cpu_information, max_cpus); - unsigned char *cpu_map = (unsigned char*) calloc(nb_core * nb_package, sizeof(unsigned char)); - cpu_sensor_t *sensors = (cpu_sensor_t*) calloc(max_cpus, sizeof(cpu_sensor_t)); + unsigned char *cpu_map = (unsigned char *) calloc(nb_core * nb_package, sizeof(unsigned char)); + cpu_sensor_t *sensors = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 2425287..1857a6a 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -116,15 +116,15 @@ do { \ .energy_units = NONE, \ .core_energy = NONE, \ }; \ - } while(0); +} while(0); #define DUMMY_RAPL(__rapl, __sensors, __sensors_count) \ - do { \ - __rapl = (_amd_rapl_t) { \ - .sensors = __sensors, \ - .sensor_count = __sensors_count \ - }; \ - } while(0); +do { \ + __rapl = (_amd_rapl_t) { \ + .sensors = __sensors, \ + .sensor_count = __sensors_count \ + }; \ +} while(0); TFUNCTION(test_label_amd_rapl, { cpu_sensor_t sensors[100]; @@ -142,7 +142,7 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); // Test 2: // -- Setup @@ -159,7 +159,7 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); // Test 3: // -- Setup @@ -176,13 +176,109 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_T_ARRAY(TEST_STR, nb, results, expecteds); + TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); }) + +#define DUMMY_CPUINFO(__sensor, __cpu_id, __package_id, __core_id) \ +do { \ + __sensor = (cpu_sensor_t) { \ + .cpu_id = __cpu_id, \ + .package_id = __package_id, \ + .core_id = __core_id, \ + .name = NULL, \ + .fd = NONE, \ + .energy_units = NONE, \ + .core_energy = NONE \ + }; \ +} while (0); + +TFUNCTION(test_is_duplicate, { + static const unsigned int nb_core = 4; + static const unsigned int nb_package = 2; + static const unsigned int max_cpu = 10; + + unsigned char map[nb_core * nb_package]; + cpu_sensor_t cpu_information[max_cpu]; + unsigned int results[2]; + unsigned int expecteds[2]; + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + expecteds[0] = 1; + expecteds[1] = 0; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[0], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 1, 1); + expecteds[0] = 1; + expecteds[1] = 0; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 0, 0); + expecteds[0] = 1; + expecteds[1] = 1; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 1, 0); + expecteds[0] = 1; + expecteds[1] = 1; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); + expecteds[0] = 1; + expecteds[1] = 1; + // -- Run + results[0] = is_duplicate(&cpu_information[0], map, nb_core); + results[1] = is_duplicate(&cpu_information[1], map, nb_core); + // -- Verification + TEST_BOOL(&results[0], &expecteds[0]); + TEST_BOOL(&results[1], &expecteds[1]); +}) + + TFILE_ENTRY_POINT(test_amd_rapl, { CALL_TFUNCTION(test_raw_to_microjoule); CALL_TFUNCTION(test_get_name); CALL_TFUNCTION(test_label_amd_rapl); + CALL_TFUNCTION(test_is_duplicate); }) #ifdef __TESTING__AMD__ diff --git a/tests/small_test.h b/tests/small_test.h index aedc685..ef9d90b 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -33,15 +33,17 @@ /** * @brief Define the entry point of the tests * It initializes each useful variables. + * + * @param __code The code that contains the calls to the test functions */ -#define TMAIN(code) \ +#define TMAIN(__code) \ int main() \ { \ unsigned int __indentation_level = 0; \ INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ unsigned int __error_counter__ = 0; \ - do code while (0); \ + do __code while (0); \ DEFERRED_FILE_ERROR(__error_counter__); \ return __error_counter__; \ } @@ -108,7 +110,6 @@ * @def TEST_STR(result, expected) * @brief Test strings * This macro is used to test strings. It takes two arguments: `__result`, which is the string to be tested, and `__expected`, which is the expected value of the string. - * The macro uses the `test_str()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * * @param __result the string to be tested * @param __expected the expected value of the string @@ -124,23 +125,43 @@ * @def TEST_BOOL(__result, __expected) * @brief Test bools * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to be tested, and `__expected`, which is the expected value of the bool. - * The macro uses the `test_bool()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param __result the bool to be tested - * @param __expected the expected value of the bool + * @param __result the pointer to bool to be tested + * @param __expected the pointer to the expected value of the bool * * @code - * TEST_BOOL(1 == 1, true); + * bool x = true; + * bool y = false; + * TEST_BOOL(&x, &y); * @endcode */ #define TEST_BOOL(__result, __expected) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &bool_interface);} while (0) +/** + * @def TEST_INT(__result, __expected) + * @brief Test ints + * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be tested, and `__expected`, which is the expected value of the int. + * + * @param __result the pointer to int to be tested + * @param __expected the pointer to expected value of the int + * + * @code + * int x = 1; + * int y = 1; + * TEST_INT(&x, &y) + * @endcode + */ +#define TEST_INT(__result, __expected) \ + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &int_interface);} while (0) + + + + /** * @def TEST_PTR(__result, __expected) * @brief Test pointers * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to be tested, and `__expected`, which is the expected value of the pointer. - * The macro uses the `test_ptr()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * * @param __result the pointer to be tested * @param __expected the expected value of the pointer @@ -159,24 +180,38 @@ * @def TEST_UINT64_T(__result, __expected) * @brief Test 64-bit unsigned integers * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, which is the integer to be tested, and `__expected`, which is the expected value of the integer. - * The macro uses the `test_uint64_t()` function to perform the test, and provides the `__FILE__`, `__LINE__` preprocessor macros to indicate the location of the test in the source code. * - * @param __result the integer to be tested - * @param __expected the expected value of the integer + * @param __result the pointer to integer to be tested + * @param __expected the pointer to expected value of the integer * * @code - * TEST_UINT64_T(5, 5); + * uint64_t x = 5; + * uint64_t y = 5; + * TEST_UINT64_T(&x, &y); * @endcode */ #define TEST_UINT64_T(__result, __expected) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &u64_interface);} while(0) +/** + * @def TEST_INTERFACE(__result, __expected, __interface) + * @brief Define a macro on a usertype with the given __interface + * This macro is used by the user to define a new test macro on a usertype. + * + * @param __result + * @param __expected + * @param __interface the usertype interface + * + * @code + * #define TEST_USERTYPE(__result, __expected) + * TEST_INTERFACE(__result, __expected, usertype_interface) + * @endcode + */ #define TEST_INTERFACE(__result, __expected, __interface) \ - do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) - + do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) /** - * @def TEST_T_ARRAY(function, nb_error, size, results, expecteds) + * @def TEST_T_ARRAY(__test_macro, __size, __results, __expecteds) * @brief Test arrays of data * The macro uses a for loop to iterate through the array and apply the test function to each element. * @@ -188,15 +223,33 @@ * @code * int results[3] = {1, 2, 3}; * int expecteds[3] = {1, 2, 3}; - * TEST_T_ARRAY(TEST_INT, 3, results, expecteds); + * TEST_ARRAY(TEST_INT, 3, results, expecteds); * @endcode */ -#define TEST_T_ARRAY(__test_macro, __array_size, __results, __expecteds) \ - for (unsigned int i = 0; i < __array_size; i++) { \ - __test_macro(__results[i], __expecteds[i]); \ - } +#define TEST_ARRAY(__test_macro, __array_size, __results, __expecteds) \ + for (unsigned i = 0; i < __array_size; i++) { \ + __test_macro(&__results[i], &__expecteds[i]); \ + } +/** + * @def TEST_T_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) + * @brief Test arrays of pointer + * The macro uses a for loop to iterate through the array and apply the test function to each element. + * + * @param __test_macro the test function to be used on each element of the array + * @param __array_size the number of elements in the array + * @param __results the array of elements to be tested + * @param __expecteds the array of expected values + * @code + * void* array[3]; + * TEST_PTR_ARRAY(TEST_PTR, 3, array, array); + * @endcode +*/ +#define TEST_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) \ + for (unsigned int i = 0; i < __array_size; i++) { \ + __test_macro(__results[i], __expecteds[i]); \ + } // --------------------------------API_CODE // These functions should not be used, only use the previous macros. @@ -261,7 +314,6 @@ static const TestInterface str_interface = { // --------------------------bool_interface - int bool_compare(void *ptr1, void *ptr2) { bool *bool1 = (bool *) ptr1; @@ -281,6 +333,27 @@ static const TestInterface bool_interface = { .format = bool_format }; +// ---------------------------int_interface + +int int_compare(void *ptr1, void *ptr2) +{ + int *int1 = (int *) ptr1; + int *int2 = (int *) ptr2; + return *int1 == *int2; +} + +char *int_format(char buffer[1000], void *ptr) +{ + int *_int = (int *) ptr; + snprintf(buffer, 1000, "%d", *_int); + return buffer; +} + +static const TestInterface int_interface = { + .compare = int_compare, + .format = int_format +}; + // ---------------------------ptr_interface int ptr_compare(void *ptr1, void *ptr2) -- GitLab From bab4a95c8dccf445cb0bb359fc8dfe9b8eee0d59 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 12:09:00 +0000 Subject: [PATCH 21/69] fix: is_duplicate --- src/amd_rapl.c | 2 +- tests/amd_rapl.c | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 1d9bc37..0c363af 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -314,7 +314,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - if (!is_duplicate(cpu_information, cpu_map, nb_core)) { + if (is_duplicate(cpu_information, cpu_map, nb_core) == 1) { init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); sensor_count += 1; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 1857a6a..f2d13ef 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -200,8 +200,8 @@ TFUNCTION(test_is_duplicate, { unsigned char map[nb_core * nb_package]; cpu_sensor_t cpu_information[max_cpu]; - unsigned int results[2]; - unsigned int expecteds[2]; + unsigned int results[max_cpu]; + unsigned int expecteds[max_cpu]; // -- Setup memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); @@ -271,6 +271,26 @@ TFUNCTION(test_is_duplicate, { // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); + + // -- Setup + memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); + DUMMY_CPUINFO(cpu_information[0], 0, 0, 0); + DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); + DUMMY_CPUINFO(cpu_information[2], 0, 1, 0); + DUMMY_CPUINFO(cpu_information[3], 0, 1, 1); + DUMMY_CPUINFO(cpu_information[4], 0, 0, 0); + DUMMY_CPUINFO(cpu_information[5], 0, 0, 1); + DUMMY_CPUINFO(cpu_information[6], 0, 1, 0); + DUMMY_CPUINFO(cpu_information[7], 0, 1, 1); + memset(expecteds, 1, sizeof(unsigned int) * 4); + memset(&expecteds[4], 0, sizeof(unsigned int) * 4); + // -- Run + for (unsigned int i = 0; i < 8; i++) { + results[i] = is_duplicate(&cpu_information[i], map, nb_core); + } + // -- Verification + TEST_ARRAY(TEST_BOOL, 8, results, expecteds); }) -- GitLab From a1cded04769e4d1c90e9b370419026e8c296b8e3 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 12:15:20 +0000 Subject: [PATCH 22/69] fix: init_amd_rapl --- src/amd_rapl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 0c363af..888df5a 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -314,7 +314,7 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - if (is_duplicate(cpu_information, cpu_map, nb_core) == 1) { + if (is_duplicate(&cpu_information[i], cpu_map, nb_core) == 1) { init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); sensor_count += 1; } -- GitLab From 00600d4ad379584817de4a5cdabaeb78a8206a1c Mon Sep 17 00:00:00 2001 From: Floreal Risso <frisso@grue-2.nancy.grid5000.fr> Date: Mon, 6 Feb 2023 13:54:44 +0100 Subject: [PATCH 23/69] fix is_duplicate --- src/amd_rapl.c | 11 ++++++----- tests/amd_rapl.c | 36 ++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 888df5a..805e698 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -248,12 +248,12 @@ void update_cpu_sensor(cpu_sensor_t *sensor, uint64_t *energy_consumed) sensor->core_energy = core_energy; } -unsigned int is_duplicate(cpu_sensor_t *sensor, unsigned char map[], unsigned int nb_core) +unsigned int is_duplicate(cpu_sensor_t *sensor,unsigned int nb_core, unsigned int nb_package, unsigned char map[nb_core][nb_package]) { - if (map[sensor->core_id * nb_core + sensor->package_id]) { + if (map[sensor->core_id][sensor->package_id] == 1) { return 0; } - map[sensor->core_id * nb_core + sensor->package_id] += 1; + map[sensor->core_id][sensor->package_id] += 1; return 1; } @@ -309,12 +309,13 @@ unsigned int init_amd_rapl(char *none, void **ptr) unsigned int nb_core; get_arch(&nb_package, &nb_core, cpu_information, max_cpus); - unsigned char *cpu_map = (unsigned char *) calloc(nb_core * nb_package, sizeof(unsigned char)); + unsigned char cpu_map[nb_core][nb_package]; + memset(cpu_map, 0, sizeof(cpu_map)); cpu_sensor_t *sensors = (cpu_sensor_t *) calloc(max_cpus, sizeof(cpu_sensor_t)); unsigned int sensor_count = 0; for (unsigned int i = 0; i < max_cpus; i++) { - if (is_duplicate(&cpu_information[i], cpu_map, nb_core) == 1) { + if (is_duplicate(&cpu_information[i], nb_core, nb_package, cpu_map) == 1) { init_cpu_sensor(&sensors[sensor_count],&cpu_information[i]); sensor_count += 1; } diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index f2d13ef..09ac0d9 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -198,82 +198,82 @@ TFUNCTION(test_is_duplicate, { static const unsigned int nb_package = 2; static const unsigned int max_cpu = 10; - unsigned char map[nb_core * nb_package]; + unsigned char map[nb_core][nb_package]; cpu_sensor_t cpu_information[max_cpu]; unsigned int results[max_cpu]; unsigned int expecteds[max_cpu]; // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); expecteds[0] = 1; expecteds[1] = 0; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[0], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package,map); + results[1] = is_duplicate(&cpu_information[0], nb_core, nb_package,map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 1, 1); expecteds[0] = 1; expecteds[1] = 0; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 0, 0); expecteds[0] = 1; expecteds[1] = 1; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 1, 0); expecteds[0] = 1; expecteds[1] = 1; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 1, 1); DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); expecteds[0] = 1; expecteds[1] = 1; // -- Run - results[0] = is_duplicate(&cpu_information[0], map, nb_core); - results[1] = is_duplicate(&cpu_information[1], map, nb_core); + results[0] = is_duplicate(&cpu_information[0], nb_core, nb_package, map); + results[1] = is_duplicate(&cpu_information[1], nb_core, nb_package, map); // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); // -- Setup - memset(map, NONE, sizeof(unsigned char) * nb_package * nb_core); + memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); DUMMY_CPUINFO(cpu_information[0], 0, 0, 0); DUMMY_CPUINFO(cpu_information[1], 0, 0, 1); @@ -287,7 +287,7 @@ TFUNCTION(test_is_duplicate, { memset(&expecteds[4], 0, sizeof(unsigned int) * 4); // -- Run for (unsigned int i = 0; i < 8; i++) { - results[i] = is_duplicate(&cpu_information[i], map, nb_core); + results[i] = is_duplicate(&cpu_information[i], nb_core, nb_package, map ); } // -- Verification TEST_ARRAY(TEST_BOOL, 8, results, expecteds); -- GitLab From 851cef1b09b4bf468aed0e11ca8c6cba31826067 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 16:39:07 +0000 Subject: [PATCH 24/69] fix: add ifndef --- src/info_reader.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/info_reader.h b/src/info_reader.h index 1696ede..e83b2c3 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -1,3 +1,26 @@ +/******************************************************* + 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/>. + +*******************************************************/ + +#ifndef _INFO_READER_H +#define _INFO_READER_ + #include <string.h> #include <stdbool.h> #include <stdio.h> @@ -216,3 +239,5 @@ static bool start_with(const char *prefix, const char *string) } } +#endif + -- GitLab From 5e505cc72bb11a4a119527a21c80b6d208fffdbb Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Mon, 6 Feb 2023 16:49:39 +0000 Subject: [PATCH 25/69] fix: add safety --- doc/test_file_ex.c | 4 ++-- tests/small_test.h | 24 +++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 4e3a093..13e1f48 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -63,10 +63,10 @@ int usertype_compare(void *ptr1, void *ptr2) return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; } -char *usertype_format(char buffer[1000], void *ptr) +char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UserType *x = (UserType *) ptr; - sprintf(buffer, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); + snprintf(buffer, FMT_BUFFER_SIZE, "UserType {simple_int: %d, simple_str: %s}", x->simple_int, x->simple_str); return buffer; } diff --git a/tests/small_test.h b/tests/small_test.h index ef9d90b..eddbdb0 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -29,6 +29,8 @@ #include "../src/util.h" +#define FMT_BUFFER_SIZE 1000 + // ---------------------------API_INTERFACE /** * @brief Define the entry point of the tests @@ -276,7 +278,7 @@ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); typedef int (Comparator) (void *, void *); -typedef char *(Formatter) (char *, void *); +typedef char *(Formatter) (char[FMT_BUFFER_SIZE], void *); typedef struct { Comparator *compare; @@ -299,7 +301,7 @@ int str_compare(void *ptr1, void *ptr2) } } -char *str_format(char *buffer, void *ptr) +char *str_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UNUSED(buffer); static char *str_null = "NULL"; @@ -321,7 +323,7 @@ int bool_compare(void *ptr1, void *ptr2) return *bool1 == *bool2; } -char *bool_format(char *buffer, void *ptr) +char *bool_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UNUSED(buffer); bool *_bool = (bool *) ptr; @@ -342,10 +344,10 @@ int int_compare(void *ptr1, void *ptr2) return *int1 == *int2; } -char *int_format(char buffer[1000], void *ptr) +char *int_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { int *_int = (int *) ptr; - snprintf(buffer, 1000, "%d", *_int); + snprintf(buffer, FMT_BUFFER_SIZE, "%d", *_int); return buffer; } @@ -361,9 +363,9 @@ int ptr_compare(void *ptr1, void *ptr2) return ptr1 == ptr2; } -char *ptr_format(char *buffer, void *ptr) +char *ptr_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { - sprintf(buffer, "%p", ptr); + snprintf(buffer, FMT_BUFFER_SIZE, "%p", ptr); return buffer; } @@ -381,10 +383,10 @@ int u64_compare(void *ptr1, void *ptr2) return *v1 == *v2; } -char *u64_format(char *buffer, void *ptr) +char *u64_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { uint64_t *v = (uint64_t *) ptr; - sprintf(buffer, "%"PRIu64"", *v); + snprintf(buffer, FMT_BUFFER_SIZE, "%"PRIu64"", *v); return buffer; } @@ -398,8 +400,8 @@ static const TestInterface u64_interface = { int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) { __indentation_level += 1; - static char buffer_result[1000]; - static char buffer_expected[1000]; + static char buffer_result[FMT_BUFFER_SIZE]; + static char buffer_expected[FMT_BUFFER_SIZE]; int is_equal = interface->compare(result, expected); char *fmt_result = interface->format(buffer_expected, expected); -- GitLab From 9b9a4c4206947e9cd6180cd1071441911a3783ba Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 07:55:33 +0000 Subject: [PATCH 26/69] fix: documentation --- doc/test_file_ex.c | 93 +++++++++++++++-------- doc/test_main_ex.c | 3 +- tests/amd_rapl.c | 26 +++++-- tests/small_test.h | 183 +++++++++++++++++++-------------------------- 4 files changed, 163 insertions(+), 142 deletions(-) diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 13e1f48..95baaa7 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -20,49 +20,70 @@ // Include of the test library #include "./../tests/small_test.h" +// Include the file that contains the function you want to test +// #include "a_file.c" -// -- A simple function that should pass +// This example is divided into three parts: +// 1. SOME SIMPLE EXAMPLES +// 2. A MORE COMPLEX EXAMPLE +// 3. FILE ENTRY POINT + +// -----------------1. SOME SIMPLE EXAMPLES + +// A simple function that should pass +// test_should_pass is the name of the function +// {} is the function code +// Use one of the define TEST_XXX defined in small_test.h TFUNCTION(test_should_pass, { - char *result = "It's going to pass"; - char *expected = "It's going to pass"; - TEST_STR(result, expected); + int result = 42; + int expected = 42; + TEST_INT(&result, &expected); }) -// -- A simple function that should fail +// A simple function that should pass +// test_should_fail is the name of the function +// {} is the function code +// Use one of the define TEST_XXX defined in small_test.h TFUNCTION(test_should_fail, { char *result = "a fail"; char *expected = "a nice fail"; TEST_STR(result, expected); }) -// -- A simple test of array +// A simple test on an array +// test_array is the name of the function +// {} is the function code +// Use one of the define TEST_XXX defined in small_test.h TFUNCTION(test_array, { static unsigned int size = 10; - int array[10]; - TEST_ARRAY(TEST_INT, size, array, array); + int results[10] = {0}; + int expecteds[10] = {0}; + for (unsigned int i = 0; i < size; i++) { + TEST_INT(&results[i], &expecteds[i]); + } }) -// -- A simple test of array of pointer -TFUNCTION(test_ptr_array, { - static unsigned int size = 10; - void *array[10]; - TEST_PTR_ARRAY(TEST_PTR, size, array, array); -}) +// See "TFILE_ENTRY_POINT" for how to call these functions. -// -- Add a new type in the test framework +// ------------2. THE MORE COMPLEX EXAMPLE +// This example shows how to add a new type to the framework +// The type that you want to add : typedef struct { int simple_int; char simple_str[20]; } UserType; -// -- Implemet the interface +// The test framework needs two functions : + +// A function that compares two values. int usertype_compare(void *ptr1, void *ptr2) { return memcmp(ptr1, ptr2, sizeof(UserType)) == 0; } +// A function to format a value. char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) { UserType *x = (UserType *) ptr; @@ -70,17 +91,18 @@ char *usertype_format(char buffer[FMT_BUFFER_SIZE], void *ptr) return buffer; } -// Create a variable which contains the functions +// Store the functions in the interface type. static const TestInterface usertype_interface = { .compare = usertype_compare, .format = usertype_format }; -// -- Create the test macro to call +// Create a macro that implements the interface by passing the interface created to the TEST_INTERFACE macro. #define TEST_USER_TYPE(__result, __expected) \ - TEST_INTERFACE(__result, __expected, &usertype_interface); + TEST_INTERFACE(__result, __expected, &usertype_interface) -// -- Create a macro setter + +// Creating a constructor is recommended (C can have problems parsing macros where "," is used). #define DUMMY_USER_TYPE(__user, __simple_int, __simple_str) \ do { \ __user = (UserType) { \ @@ -89,19 +111,22 @@ static const TestInterface usertype_interface = { }; \ } while (0); -// -- Compare two usertype +// Now you can write test for your new type +// all you have to do is call the macro that implements "TEST_INTERFACE". +// here it's "TEST_USERTYPE" TFUNCTION(test_user_type, { - UserType x1; - UserType x2; + UserType result; + UserType expected; - DUMMY_USER_TYPE(x1, 1, "John Doe"); - DUMMY_USER_TYPE(x2, 1, "John Doe"); + DUMMY_USER_TYPE(result, 1, "John Doe"); + DUMMY_USER_TYPE(expected, 1, "John Doe"); - TEST_USER_TYPE(&x1, &x2); + TEST_USER_TYPE(&result, &expected); }) - -// -- Compare an array of usetype +// Now you can write test for your new type +// all you have to do is call the macro that implements "TEST_INTERFACE". +// here it's "TEST_USERTYPE" TFUNCTION(test_array_user_type, { UserType results[1]; UserType expecteds[1]; @@ -109,15 +134,23 @@ TFUNCTION(test_array_user_type, { DUMMY_USER_TYPE(results[0], 1, "John Doe"); DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - TEST_ARRAY(TEST_USER_TYPE, 1, results, expecteds); + for (unsigned int i = 0; i < 1; i++) { + TEST_USER_TYPE(&results[i], &expecteds[i]); + } }) +// ---------------------3. FILE ENTRY POINT + // Define the entry point of a test file +// Use the macro "CALL_TFUNCTION" where the name of a function is defined with the macro "TFUNCTION". TFILE_ENTRY_POINT(test_file_ex, { + // Call the simple examples CALL_TFUNCTION(test_should_pass); CALL_TFUNCTION(test_should_fail); CALL_TFUNCTION(test_array); - CALL_TFUNCTION(test_ptr_array); + + // Call the more complex example CALL_TFUNCTION(test_user_type); CALL_TFUNCTION(test_array_user_type); }) + diff --git a/doc/test_main_ex.c b/doc/test_main_ex.c index 0aa86b9..a5e7841 100644 --- a/doc/test_main_ex.c +++ b/doc/test_main_ex.c @@ -22,7 +22,7 @@ // Include of the test library #include "./../tests/small_test.h" -// Include the *.c files that contain the tests +// Include the *.c files containing the tests #include "./test_file_ex.c" // #include "./test_another_test_file.c" @@ -33,3 +33,4 @@ TMAIN({ CALL_TFUNCTION(test_file_ex); // CALL_TFUNCTION(another_file_entry_point_function); }) + diff --git a/tests/amd_rapl.c b/tests/amd_rapl.c index 09ac0d9..0485099 100644 --- a/tests/amd_rapl.c +++ b/tests/amd_rapl.c @@ -142,7 +142,10 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); + for(unsigned int i = 0; i < nb; i++) + { + TEST_STR(results[i], expecteds[i]); + } // Test 2: // -- Setup @@ -159,8 +162,10 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); - + for(unsigned int i = 0; i < nb; i++) + { + TEST_STR(results[i], expecteds[i]); + } // Test 3: // -- Setup nb = 4; @@ -176,7 +181,10 @@ TFUNCTION(test_label_amd_rapl, { // -- Run label_amd_rapl(results, (void *) &rapl); // -- Verification - TEST_PTR_ARRAY(TEST_STR, nb, results, expecteds); + for(unsigned int i = 0; i < nb; i++) + { + TEST_STR(results[i], expecteds[i]); + } }) @@ -271,7 +279,7 @@ TFUNCTION(test_is_duplicate, { // -- Verification TEST_BOOL(&results[0], &expecteds[0]); TEST_BOOL(&results[1], &expecteds[1]); - + // -- Setup memset(map, NONE, sizeof(map)); memset(cpu_information,NONE, sizeof(cpu_sensor_t) * max_cpu); @@ -286,11 +294,15 @@ TFUNCTION(test_is_duplicate, { memset(expecteds, 1, sizeof(unsigned int) * 4); memset(&expecteds[4], 0, sizeof(unsigned int) * 4); // -- Run - for (unsigned int i = 0; i < 8; i++) { + for (unsigned int i = 0; i < 8; i++) + { results[i] = is_duplicate(&cpu_information[i], nb_core, nb_package, map ); } // -- Verification - TEST_ARRAY(TEST_BOOL, 8, results, expecteds); + for(unsigned int i = 0; i < 8; i++) + { + TEST_BOOL(&results[i], &expecteds[i]); + } }) diff --git a/tests/small_test.h b/tests/small_test.h index eddbdb0..abae768 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -33,10 +33,10 @@ // ---------------------------API_INTERFACE /** - * @brief Define the entry point of the tests - * It initializes each useful variables. + * @brief Define the entry point for the tests. + * It initialises any useful variables and acts as the main one. * - * @param __code The code that contains the calls to the test functions + * @param __code The code that contains the calls to the test functions. */ #define TMAIN(__code) \ @@ -46,22 +46,24 @@ INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ unsigned int __error_counter__ = 0; \ do __code while (0); \ - DEFERRED_FILE_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } /** + * @def TFILE_ENTRY_POINT(__filename, __code) + * * @brief Define the entry point of a test file. * This macro is used to define the entry point of a test file. * It defines a function with the specified __filename that contains the test code specified in code. * - * When the function is called, it initializes the test file using the INIT_TEST_FILE macro, + * When the function is called, it initialises the test file using the INIT_TEST_FILE macro, * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. * The function returns the value of __error_counter__, * which indicates the number of errors encountered during the tests. * - * @param __filename The name of the function that serves as the entry point for the test file. + * @param __filename The name of the function to be used as an entry point for the test file. * @param __code The test code to be executed in the function. */ #define TFILE_ENTRY_POINT(__filename, __code) \ @@ -70,16 +72,18 @@ INIT_TEST_FILE(); \ int __error_counter__ = 0; \ do __code while(0); \ - DEFERRED_FILE_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } /** + * @def TFUNCTION(__function_name, __code) + * * @brief Define a test function within a test file. * This macro is used to define a test function within a test file. - * It defines a function with the specified function_name that contains the test code specified in code. + * It defines a function with the given __function_name containing the test code specified in __code. * - * When the function is called, it initializes the test function using the INIT_TEST_FUNCTION macro, + * When the function is called, it initialises the test function using the INIT_TEST_FUNCTION macro, * declares an integer variable __error_counter__ to keep track of any errors encountered during the tests, * executes the test code in a do-while loop, and then checks for any deferred errors using the DEFERRED_ERROR macro. * The function returns the value of __error_counter__, which indicates the number of errors encountered during the tests. @@ -93,28 +97,32 @@ INIT_TEST_FUNCTION(); \ int __error_counter__ = 0; \ do __code while(0); \ - DEFERRED_FUNCTION_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } /** + * @def CALL_TFUNCTION(__function_name) + * * @brief Call a test function within a test file. * This macro is used to call a test function within a test file. - * It calls the function specified by function_name and adds the return value to the __error_counter__ variable. + * It calls the function specified by __function_name and adds the return value to the __error_counter__ variable. * This allows multiple test functions to be executed and their error count to be accumulated. * - * @param function_name The name of the test function to be called. + * @param __function_name The name of the test function to be called. */ -#define CALL_TFUNCTION(function_name) \ - do {__error_counter__ += function_name(__indentation_level + 1);} while(0) +#define CALL_TFUNCTION(__function_name) \ + do {__error_counter__ += __function_name(__indentation_level + 1);} while(0) /** - * @def TEST_STR(result, expected) + * @def TEST_STR(__result, __expected) + * * @brief Test strings - * This macro is used to test strings. It takes two arguments: `__result`, which is the string to be tested, and `__expected`, which is the expected value of the string. + * This macro is used to test strings. It takes two arguments: `__result`, which is the string to test, and `__expected`, + * which is the expected value of the string. * - * @param __result the string to be tested - * @param __expected the expected value of the string + * @param __result the string to test. + * @param __expected the expected value of the string. * * @code * TEST_STR("Hello", "Hello"); @@ -125,15 +133,17 @@ /** * @def TEST_BOOL(__result, __expected) + * * @brief Test bools - * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to be tested, and `__expected`, which is the expected value of the bool. + * This macro is used to test bools. It takes two arguments: `__result`, which is the bool to test, and `__expected`, + * which is the expected value of the bool. * - * @param __result the pointer to bool to be tested - * @param __expected the pointer to the expected value of the bool + * @param __result the pointer to bool to test. + * @param __expected the pointer to the expected value of the bool. * * @code * bool x = true; - * bool y = false; + * bool y = true; * TEST_BOOL(&x, &y); * @endcode */ @@ -142,11 +152,13 @@ /** * @def TEST_INT(__result, __expected) + * * @brief Test ints - * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be tested, and `__expected`, which is the expected value of the int. + * This macro is used to test ints. It takes two arguments: `__result`, which is the int to be test, and `__expected`, + * which is the expected value of the int. * - * @param __result the pointer to int to be tested - * @param __expected the pointer to expected value of the int + * @param __result the pointer to int to test. + * @param __expected the pointer to expected value of the int. * * @code * int x = 1; @@ -157,16 +169,15 @@ #define TEST_INT(__result, __expected) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, &int_interface);} while (0) - - - /** * @def TEST_PTR(__result, __expected) + * * @brief Test pointers - * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to be tested, and `__expected`, which is the expected value of the pointer. + * This macro is used to test pointers. It takes two arguments: `__result`, which is the pointer to test, and `__expected`, + * which is the expected value of the pointer. * - * @param __result the pointer to be tested - * @param __expected the expected value of the pointer + * @param __result the pointer to test. + * @param __expected the expected value of the pointer. * * @code * int x = 5; @@ -180,11 +191,13 @@ /** * @def TEST_UINT64_T(__result, __expected) + * * @brief Test 64-bit unsigned integers - * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, which is the integer to be tested, and `__expected`, which is the expected value of the integer. + * This macro is used to test 64-bit unsigned integers. It takes two arguments: `__result`, + * which is the integer to test, and `__expected`, which is the expected value of the integer. * - * @param __result the pointer to integer to be tested - * @param __expected the pointer to expected value of the integer + * @param __result the pointer to integer to test. + * @param __expected the pointer to expected value of the integer. * * @code * uint64_t x = 5; @@ -197,64 +210,28 @@ /** * @def TEST_INTERFACE(__result, __expected, __interface) - * @brief Define a macro on a usertype with the given __interface + * + * @brief Define a macro on a usertype with the given __interface. * This macro is used by the user to define a new test macro on a usertype. * * @param __result * @param __expected - * @param __interface the usertype interface + * @param __interface the interface of the usertype. * * @code - * #define TEST_USERTYPE(__result, __expected) - * TEST_INTERFACE(__result, __expected, usertype_interface) + * TestInterface usertype_interface = {.compare = ..., .format = ...}; + * #define TEST_USERTYPE(__result, __expected) \ + * TEST_INTERFACE(__result, __expected, &usertype_interface) * @endcode */ #define TEST_INTERFACE(__result, __expected, __interface) \ do {__error_counter__ += test(__FILE__, __LINE__, __indentation_level, __result, __expected, __interface);} while(0) -/** - * @def TEST_T_ARRAY(__test_macro, __size, __results, __expecteds) - * @brief Test arrays of data - * The macro uses a for loop to iterate through the array and apply the test function to each element. - * - * @param __test_macro the test function to be used on each element of the array - * @param __array_size the number of elements in the array - * @param __results the array of elements to be tested - * @param __expecteds the array of expected values - - * @code - * int results[3] = {1, 2, 3}; - * int expecteds[3] = {1, 2, 3}; - * TEST_ARRAY(TEST_INT, 3, results, expecteds); - * @endcode -*/ -#define TEST_ARRAY(__test_macro, __array_size, __results, __expecteds) \ - for (unsigned i = 0; i < __array_size; i++) { \ - __test_macro(&__results[i], &__expecteds[i]); \ - } -/** - * @def TEST_T_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) - * @brief Test arrays of pointer - * The macro uses a for loop to iterate through the array and apply the test function to each element. - * - * @param __test_macro the test function to be used on each element of the array - * @param __array_size the number of elements in the array - * @param __results the array of elements to be tested - * @param __expecteds the array of expected values - * @code - * void* array[3]; - * TEST_PTR_ARRAY(TEST_PTR, 3, array, array); - * @endcode -*/ -#define TEST_PTR_ARRAY(__test_macro, __array_size, __results, __expecteds) \ - for (unsigned int i = 0; i < __array_size; i++) { \ - __test_macro(__results[i], __expecteds[i]); \ - } -// --------------------------------API_CODE -// These functions should not be used, only use the previous macros. +// ------------------------------------CODE +// These functions should not be in use, only the previous macros should be in use. #define INDENTED_PRINT(__fmt, ...) \ do { \ @@ -271,10 +248,7 @@ #define INIT_TEST_FUNCTION() \ INDENTED_PRINT("%s()\n", __func__); -#define DEFERRED_FILE_ERROR(nb_error) \ - INDENTED_PRINT("|_Deferred Error : %u\n",nb_error); - -#define DEFERRED_FUNCTION_ERROR(nb_error) \ +#define DEFERRED_ERROR(nb_error) \ INDENTED_PRINT("|_Deferred Error : %d\n",nb_error); typedef int (Comparator) (void *, void *); @@ -285,8 +259,26 @@ typedef struct { Formatter *format; } TestInterface; -// ---------------------------str_interface +// ---------------------------TEST FUNCTION + +int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) +{ + __indentation_level += 1; + static char buffer_result[FMT_BUFFER_SIZE]; + static char buffer_expected[FMT_BUFFER_SIZE]; + int is_equal = interface->compare(result, expected); + + char *fmt_result = interface->format(buffer_expected, expected); + char *fmt_expected = interface->format(buffer_result, result); + if (!is_equal) { + INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); + } + return !is_equal; +} + +// ------------------------------INTERFACES +// -- str_interface int str_compare(void *ptr1, void *ptr2) { char *str1 = (char *) ptr1; @@ -314,7 +306,7 @@ static const TestInterface str_interface = { .format = str_format }; -// --------------------------bool_interface +// -- bool_interface int bool_compare(void *ptr1, void *ptr2) { @@ -335,7 +327,7 @@ static const TestInterface bool_interface = { .format = bool_format }; -// ---------------------------int_interface +// -- int_interface int int_compare(void *ptr1, void *ptr2) { @@ -356,7 +348,7 @@ static const TestInterface int_interface = { .format = int_format }; -// ---------------------------ptr_interface +// -- ptr_interface int ptr_compare(void *ptr1, void *ptr2) { @@ -374,7 +366,7 @@ static const TestInterface ptr_interface = { .format = ptr_format }; -// ---------------------------u64_interface +// -- u64_interface int u64_compare(void *ptr1, void *ptr2) { @@ -395,22 +387,5 @@ static const TestInterface u64_interface = { .format = u64_format }; -// ---------------------------test_function - -int test(char *file, int line, unsigned int __indentation_level, void *result, void *expected, const TestInterface *interface) -{ - __indentation_level += 1; - static char buffer_result[FMT_BUFFER_SIZE]; - static char buffer_expected[FMT_BUFFER_SIZE]; - int is_equal = interface->compare(result, expected); - - char *fmt_result = interface->format(buffer_expected, expected); - char *fmt_expected = interface->format(buffer_result, result); - if (!is_equal) { - INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result); - } - return !is_equal; -} - #endif -- GitLab From 585fa51e2a9f1d181ccd1bc10f2ac3deba544a3b Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 07:58:49 +0000 Subject: [PATCH 27/69] format --- doc/test_file_ex.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/test_file_ex.c b/doc/test_file_ex.c index 95baaa7..0595e9a 100644 --- a/doc/test_file_ex.c +++ b/doc/test_file_ex.c @@ -20,7 +20,7 @@ // Include of the test library #include "./../tests/small_test.h" -// Include the file that contains the function you want to test +// Include the file that contains the function you want to test // #include "a_file.c" // This example is divided into three parts: @@ -58,7 +58,8 @@ TFUNCTION(test_array, { static unsigned int size = 10; int results[10] = {0}; int expecteds[10] = {0}; - for (unsigned int i = 0; i < size; i++) { + for (unsigned int i = 0; i < size; i++) + { TEST_INT(&results[i], &expecteds[i]); } }) @@ -134,7 +135,8 @@ TFUNCTION(test_array_user_type, { DUMMY_USER_TYPE(results[0], 1, "John Doe"); DUMMY_USER_TYPE(expecteds[0], 1, "John Doe"); - for (unsigned int i = 0; i < 1; i++) { + for (unsigned int i = 0; i < 1; i++) + { TEST_USER_TYPE(&results[i], &expecteds[i]); } }) -- GitLab From bea62d235a126b799dd3e05692903e27cc7129ed Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 07:59:19 +0000 Subject: [PATCH 28/69] fix: use a const --- src/load.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/load.c b/src/load.c index 6dcf2b0..1c049ce 100644 --- a/src/load.c +++ b/src/load.c @@ -26,11 +26,12 @@ #include "util.h" #define LOAD_BUFFER_SIZE 1024 +#define LOAD_VALUES_SIZE 10 char buffer[LOAD_BUFFER_SIZE]; static int load_fid = -1; -static uint64_t load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static uint64_t tmp_load_values[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static uint64_t load_values[LOAD_VALUES_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static uint64_t tmp_load_values[LOAD_VALUES_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static char *stat = "/proc/stat"; void _get_load(uint64_t *results) @@ -46,8 +47,8 @@ void _get_load(uint64_t *results) pos++; } - for (int i = 0; i < 10; i++) { - results[i] = strtoull(buffer + pos, NULL, 10); + for (int i = 0; i < LOAD_VALUES_SIZE; i++) { + results[i] = strtoull(buffer + pos, NULL, LOAD_VALUES_SIZE); while (buffer[pos] <= '9' && buffer[pos] >= '0') { pos++; @@ -71,7 +72,7 @@ unsigned int init_load(char *argument, void **state) } _get_load(load_values); - return 10; + return LOAD_VALUES_SIZE; } unsigned int get_load(uint64_t *results, void *state) @@ -79,12 +80,12 @@ unsigned int get_load(uint64_t *results, void *state) UNUSED(state); _get_load(tmp_load_values); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < LOAD_VALUES_SIZE; i++) { results[i] = tmp_load_values[i] - load_values[i]; } memcpy(load_values, tmp_load_values, sizeof(load_values)); - return 10; + return LOAD_VALUES_SIZE; } void clean_load(void *state) @@ -93,14 +94,15 @@ void clean_load(void *state) close(load_fid); } -char *_labels[10] = {"user", "nice", "system", "idle", "iowait", "irq", - "softirq", "steal", "guest", "guest_nice" - }; +char *_labels[LOAD_VALUES_SIZE] = { + "user", "nice", "system", "idle", "iowait", "irq", + "softirq", "steal", "guest", "guest_nice" +}; void label_load(char **labels, void *none) { UNUSED(none); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < LOAD_VALUES_SIZE; i++) { labels[i] = _labels[i]; } } -- GitLab From fa47271704f8d2fe67a86d94b8746c8d39eb527d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:17:33 +0000 Subject: [PATCH 29/69] cleanup --- doc/info_reader_ex.c | 54 ++++++++++++++++++++++++++++++-------------- src/info_reader.h | 8 +++---- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/doc/info_reader_ex.c b/doc/info_reader_ex.c index f672d98..2e76251 100644 --- a/doc/info_reader_ex.c +++ b/doc/info_reader_ex.c @@ -23,8 +23,8 @@ #include "./../src/info_reader.h" #define MAX_PROCS 64 -#define NB_KEYS 6 +// -----------------------------The storage typedef struct { unsigned int processor; char *vendor_id; @@ -34,12 +34,16 @@ typedef struct { char *model_name; } Cpu; +// --------------IMPLEMENTING THE INTERFACE + +// -- Define the behaviour if the attempted value is an int GenericPointer int_allocator(char *s) { unsigned int value = atoi(s); return (GenericPointer) value; } +// -- Define the behaviour if the attempted value is a string GenericPointer string_allocator(char *s) { char *value = malloc(strlen(s) + 1); @@ -47,31 +51,42 @@ GenericPointer string_allocator(char *s) return (GenericPointer) value; } +// -- Define the processor setter void set_processor(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->processor = data; } + +// -- Define the vendor_id setter void set_vendor_id(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->vendor_id = (char *) data; } + +// -- Define the family setter void set_family(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->family = data; } + +// -- Define the core_id setter void set_core_id(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->core_id = data; } + +// -- Define the physical_id setter void set_physical_id(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; cpu->physical_id = data; } + +// -- Define the model_name setter void set_model_name(GenericPointer storage, GenericPointer data) { Cpu *cpu = (Cpu *) storage; @@ -81,28 +96,33 @@ void set_model_name(GenericPointer storage, GenericPointer data) int main() { Cpu cpus[MAX_PROCS]; + + // -- Define the setter, the allocator for each key / separator. KeyFinder keys[] = { - {"processor", ": ", (CopyAllocator *) int_allocator, (Setter *)set_processor}, - {"vendor_id", ": ", (CopyAllocator *) string_allocator, (Setter *)set_vendor_id}, - {"cpu family", ": ", (CopyAllocator *) int_allocator, (Setter *)set_family}, - {"core id", ": ", (CopyAllocator *) int_allocator, (Setter *)set_core_id}, - {"physical id", ": ", (CopyAllocator *) int_allocator,(Setter *)set_physical_id}, - { - "model name", ": ", (CopyAllocator *) string_allocator, - (Setter *)set_model_name - } + {.key = "processor", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_processor}, + {.key = "vendor_id", .delimiter = ": ", .copy = (CopyAllocator *) string_allocator, .set = (Setter *)set_vendor_id}, + {.key = "cpu family", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_family}, + {.key = "core id", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_core_id}, + {.key = "physical id", .delimiter = ": ", .copy = (CopyAllocator *) int_allocator, .set = (Setter *)set_physical_id}, + {.key = "model name", .delimiter = ": ", .copy = (CopyAllocator *) string_allocator, .set = (Setter *)set_model_name} }; - Parser parser = {.storage = (GenericPointer) cpus, - .capacity = MAX_PROCS, - .storage_struct_size = sizeof(Cpu), - .keys = keys, - .nb_keys = NB_KEYS, - .file = fopen("/proc/cpuinfo", "r") - }; + size_t nb_keys = sizeof(keys)/sizeof(KeyFinder); + + // -- Init the parser + Parser parser = { + .storage = (GenericPointer) cpus, + .capacity = MAX_PROCS, + .storage_struct_size = sizeof(Cpu), + .keys = keys, + .nb_keys = nb_keys, + .file = fopen("/proc/cpuinfo", "r") + }; + // -- Parse the file parse(&parser); + // Print and free the results for (unsigned int i = 0; i < parser.nb_stored; ++i) { printf("========== PROC[%d] ==========\n", i); printf("Processor: %u\n", cpus[i].processor); diff --git a/src/info_reader.h b/src/info_reader.h index e83b2c3..0d694d3 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -96,10 +96,10 @@ static bool start_with(const char *prefix, const char *string); /** * @brief Matches a line of text to a key in the parser's list of keys. * - * @param parser Pointer to the Parser struct. - * @param line Line of text to match. - * @param key_finder Pointer to a KeyFinder pointer where the matched key will be stored. - * @param raw_value Pointer to a char pointer where the value associated with the matched key will be stored. + * @param[in] parser Pointer to the Parser struct. + * @param[in] line Line of text to match. + * @param[out] key_finder Pointer to a KeyFinder pointer where the matched key will be stored. + * @param[out] raw_value Pointer to a char pointer where the value associated with the matched key will be stored. * * @return Returns 1 if a key is matched, 0 otherwise. */ -- GitLab From 402140300f756114e7ed4f18fd4692b9b5e6aae4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:25:30 +0000 Subject: [PATCH 30/69] format --- tests/small_test.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index abae768..bf0ca10 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -39,15 +39,15 @@ * @param __code The code that contains the calls to the test functions. */ -#define TMAIN(__code) \ - int main() \ -{ \ - unsigned int __indentation_level = 0; \ - INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ - unsigned int __error_counter__ = 0; \ - do __code while (0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ +#define TMAIN(__code) \ + int main() \ +{ \ + unsigned int __indentation_level = 0; \ + INDENTED_PRINT("%s:%s\n", __FILE__, __func__); \ + unsigned int __error_counter__ = 0; \ + do __code while (0); \ + DEFERRED_ERROR(__error_counter__); \ + return __error_counter__; \ } /** @@ -72,7 +72,7 @@ INIT_TEST_FILE(); \ int __error_counter__ = 0; \ do __code while(0); \ - DEFERRED_ERROR(__error_counter__); \ + DEFERRED_ERROR(__error_counter__); \ return __error_counter__; \ } @@ -91,14 +91,14 @@ * @param __function_name The name of the test function. * @param __code The test code to be executed in the function. */ -#define TFUNCTION(__function_name, __code) \ +#define TFUNCTION(__function_name, __code) \ int __function_name(unsigned int __indentation_level) \ -{ \ - INIT_TEST_FUNCTION(); \ - int __error_counter__ = 0; \ - do __code while(0); \ - DEFERRED_ERROR(__error_counter__); \ - return __error_counter__; \ +{ \ + INIT_TEST_FUNCTION(); \ + int __error_counter__ = 0; \ + do __code while(0); \ + DEFERRED_ERROR(__error_counter__); \ + return __error_counter__; \ } /** @@ -236,13 +236,13 @@ #define INDENTED_PRINT(__fmt, ...) \ do { \ for(unsigned int i = 0; i < __indentation_level; i++) { \ - printf("| "); \ + printf("| "); \ } \ printf(__fmt, ##__VA_ARGS__); \ } while(0) -#define INIT_TEST_FILE() \ +#define INIT_TEST_FILE() \ INDENTED_PRINT("%s:%s\n", __FILE__, __func__) #define INIT_TEST_FUNCTION() \ -- GitLab From 4b22f61991d079ebfce3c387d4ceae227a57ed47 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:26:24 +0000 Subject: [PATCH 31/69] doc --- tests/small_test.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/small_test.h b/tests/small_test.h index bf0ca10..66c4de9 100644 --- a/tests/small_test.h +++ b/tests/small_test.h @@ -33,6 +33,8 @@ // ---------------------------API_INTERFACE /** + * @def TMAIN(__code) + * * @brief Define the entry point for the tests. * It initialises any useful variables and acts as the main one. * -- GitLab From f29c9ade9da41bc824c40c59b4ce0e48e79c13fb Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ3-tlse.fr> Date: Tue, 7 Feb 2023 08:35:54 +0000 Subject: [PATCH 32/69] fix: header --- src/info_reader.h | 2 +- tests/info_reader.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/info_reader.h b/src/info_reader.h index 0d694d3..ec28db6 100644 --- a/src/info_reader.h +++ b/src/info_reader.h @@ -19,7 +19,7 @@ *******************************************************/ #ifndef _INFO_READER_H -#define _INFO_READER_ +#define _INFO_READER_H #include <string.h> #include <stdbool.h> diff --git a/tests/info_reader.c b/tests/info_reader.c index b2a8c6f..19d9c0a 100644 --- a/tests/info_reader.c +++ b/tests/info_reader.c @@ -19,6 +19,7 @@ *******************************************************/ #include "small_test.h" +#include "./../src/info_reader.h" TFUNCTION(test_replace_first, { // useful variables : -- GitLab From 8aeab626fdda56b5090c4b88ae6ca46631509491 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 12:39:47 +0100 Subject: [PATCH 33/69] build: support for multiple options per captor - Makefile now includes captors.mk which defines captor object files to build (the previous behaviour was to build all captors regardless of the captor selection during configuration) - correct a bug in configure.sh : now properly detect amd cpu family - configure.sh now print an error when 0 captors are selected - configure.sh now do a `make clean` on successful configuration --- .gitignore | 21 +++++----- configure.sh | 71 ++++++++++++++++++++++++-------- makefile | 14 +++---- src/amd_rapl.h | 16 ++++++-- src/counters.h | 29 +++++++++---- src/infiniband.h | 17 ++++++-- src/load.h | 16 ++++++-- src/mojitos.c | 101 ++++++++++++++++++++++++++++++---------------- src/network.h | 15 +++++-- src/optparse.h | 2 + src/rapl.h | 16 ++++++-- src/temperature.h | 16 ++++++-- 12 files changed, 234 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index dd136f4..6643912 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ -src/counters_option.h -src/captors.h -tests/run -bin -obj -*.swp -*.swo -.vscode -doc/test_main_ex -doc/info_reader_ex +doc/test_main_ex +doc/info_reader_ex +tests/run +src/counters_option.h +src/sensors.h +captors.mk +bin +obj +*.swp +*.swo +.vscode diff --git a/configure.sh b/configure.sh index 2d21bf5..49e1789 100755 --- a/configure.sh +++ b/configure.sh @@ -20,7 +20,8 @@ decho() { } debug=0 -target=src/captors.h +target_hdr=src/captors.h +target_mk=captors.mk noncaptor='counters_option|optparse|captors|util|info_reader' @@ -41,8 +42,8 @@ ls_captors() { try cd src [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' - dprint hdr_blacklist - dprint hdr_whitelist + dprint hdr_blacklist >&2 + dprint hdr_whitelist >&2 ls -1 *.h | grep -xEv "($hdr_blacklist)\.h" | @@ -50,31 +51,53 @@ ls_captors() { sed 's/\.h$//' } +# gen_captors_h(captors, nb_captors) gen_captors_h() { - captors=$(ls_captors) - nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) - printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 - printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 - echo "$captors" >&2 - - [ -n "$captors" ] || return + captors=$1 + nb_captors=$2 + nb_captor_opts=$( + for captor in $captors; do + sed -n 's/.*'"${captor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${captor}.h" + done | + paste -s -d '+' | + bc + ) + + dprint captors >&2 + dprint nb_captor_opts >&2 + isnum "$nb_captor_opts" || die "could not get total number of captors's command-line options" # gen includes for captor in $captors; do printf '#include "%s.h"\n' "$captor" done - printf '\n#define NB_CAPTORS %d\n\n' "$nb_captors" + printf '\n#define NB_CAPTOR %d\n\n' "$nb_captors" + printf '\n#define NB_CAPTOR_OPT %d\n\n' "$nb_captor_opts" # gen `init_captors()` - printf 'void init_captors(struct optparse_long *longopts, struct captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' + printf 'void init_captors(Optparse *longopts, Captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' + printf ' int opt_idx = offset;\n' for captor in $captors; do - printf ' longopts[offset + *nb_defined] = %s_opt;\n' "$captor" - printf ' captors[(*nb_defined)++] = %s;\n' "$captor" + cat <<-! + for (int i = 0; i < ${captor}.nb_opt; i++) { + longopts[opt_idx++] = ${captor}_opt[i]; + } + captors[(*nb_defined)++] = ${captor}; + ! done printf ' assert((offset + *nb_defined) <= len);\n' printf '}\n' } +gen_captors_mk() { + captors=$1 + printf 'CAPTOR_OBJ = ' + for captor in $captors; do + printf '$(OBJ_DIR)/%s.o ' "$captor" + done + printf '\n' +} + detect_caps() { [ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters [ -d /sys/class/infiniband ] && hdr_whitelist=${hdr_whitelist}|infiniband @@ -92,7 +115,7 @@ detect_caps() { hdr_whitelist="${hdr_whitelist}|rapl" ;; *amd*) - family=$(awk '/cpu[ \t]*family/ {print $3; exit}' /proc/cpuinfo) + family=$(awk '/cpu[ \t]*family/ {print $4; exit}' /proc/cpuinfo) if isnum "$family"; then [ $family -ge 17 ] && hdr_whitelist="${hdr_whitelist}|amd_rapl" fi @@ -132,4 +155,20 @@ while [ "$1" ]; do shift done -gen_captors_h > "$target" +captors=$(ls_captors) +nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) + +if [ "$nb_captors" -eq 0 ]; then + printf -- '0 captors are selected. cannot build.\n' >&2 + exit 1 +fi + +try gen_captors_h "$captors" "$nb_captors" > "$target_hdr" +try gen_captors_mk "$captors" > "$target_mk" + +printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 +printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 +echo "$captors" >&2 + +make clean >/dev/null + diff --git a/makefile b/makefile index eabffaf..3f8a70b 100644 --- a/makefile +++ b/makefile @@ -8,15 +8,13 @@ TESTS_DIR = tests BIN = mojitos +CAPTOR_OBJ = + +include ./captors.mk + OBJ = \ - $(OBJ_DIR)/counters.o \ - $(OBJ_DIR)/rapl.o \ - $(OBJ_DIR)/network.o \ - $(OBJ_DIR)/load.o \ - $(OBJ_DIR)/infiniband.o \ - $(OBJ_DIR)/temperature.o \ - $(OBJ_DIR)/util.o \ - $(OBJ_DIR)/amd_rapl.o + $(CAPTOR_OBJ) \ + $(OBJ_DIR)/util.o CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function diff --git a/src/amd_rapl.h b/src/amd_rapl.h index f16ed4f..52a7c6c 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -23,12 +23,20 @@ unsigned int get_amd_rapl(uint64_t *results, void *); void clean_amd_rapl(void *); void label_amd_rapl(char **labels, void *); -struct optparse_long amd_rapl_opt = {"amd_rapl", 'a', OPTPARSE_NONE}; -struct captor amd_rapl = { - .usage_arg = NULL, - .usage_msg = "AMD_RAPL", +Captor amd_rapl = { .init = init_amd_rapl, .get = get_amd_rapl, .clean = clean_amd_rapl, .label = label_amd_rapl, + .nb_opt = 1, +}; + +Optparse amd_rapl_opt[1] = { + { + .longname = "amd-rapl", + .shortname = 'a', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "AMD RAPL", + }, }; diff --git a/src/counters.h b/src/counters.h index 313feeb..a191e5a 100644 --- a/src/counters.h +++ b/src/counters.h @@ -22,17 +22,32 @@ unsigned int init_counters(char *, void **); unsigned int get_counters(uint64_t *results, void *); void clean_counters(void *); void label_counters(char **labels, void *); +void show_all_counters(); -struct optparse_long counters_opt = {"perf-list", 'p', OPTPARSE_REQUIRED}; -struct captor counters = { - .usage_arg = "<perf_list>", - .usage_msg = "performance counters\n" - "\tperf_list is a coma separated list of performance counters.\n" - "\tEx: instructions,cache_misses", +Captor counters = { .init = init_counters, .get = get_counters, .clean = clean_counters, .label = label_counters, + .nb_opt = 2, +}; + +Optparse counters_opt[2] = { + { + .longname = "perf-list", + .shortname = 'p', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<perf_list>", + .usage_msg = "performance counters\n" + "\tperf_list is a coma separated list of performance counters.\n" + "\tEx: instructions,cache_misses", + }, + { + .longname = "list", + .shortname = 'l', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "list the possible performance counters and quit" + }, }; -void show_all_counters(); diff --git a/src/infiniband.h b/src/infiniband.h index 0f1ad11..285b2ba 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -21,12 +21,21 @@ unsigned int init_infiniband(char *infi_path, void **ptr); void label_infiniband(char **labels, void *); -struct optparse_long infiniband_opt = {"monitor-infiniband", 'i', OPTPARSE_REQUIRED}; -struct captor infiniband = { - .usage_arg = "<infiniband_path>", - .usage_msg = "infiniband monitoring (if infiniband_path is X, tries to detect it automatically)", +Captor infiniband = { .init = init_infiniband, .get = NULL, .clean = NULL, .label = label_infiniband, + .nb_opt = 1, }; + +Optparse infiniband_opt[1] = { + { + .longname = "monitor-infiniband", + .shortname = 'i', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<infiniband_path>", + .usage_msg = "infiniband monitoring (if infiniband_path is X, tries to detect it automatically)", + }, +}; + diff --git a/src/load.h b/src/load.h index 366e448..c7c5575 100644 --- a/src/load.h +++ b/src/load.h @@ -23,12 +23,20 @@ unsigned int get_load(uint64_t *results, void *); void clean_load(void *); void label_load(char **labels, void *); -struct optparse_long load_opt = {"sysload", 'u', OPTPARSE_NONE}; -struct captor load = { - .usage_arg = NULL, - .usage_msg = "system load", +Captor load = { .init = init_load, .get = get_load, .clean = clean_load, .label = label_load, + .nb_opt = 1, +}; + +Optparse load_opt[1] = { + { + .longname = "sysload", + .shortname = 'u', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "system load", + }, }; diff --git a/src/mojitos.c b/src/mojitos.c index dc113fc..683bdfa 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -37,44 +37,75 @@ typedef void (*labeler_t)(char **, void *); typedef unsigned int (*getter_t)(uint64_t *, void *); typedef void (*cleaner_t)(void *); -struct captor { - char *usage_arg; - char *usage_msg; +typedef struct Opt Opt; +typedef struct Captor Captor; +/* optparse typedef */ +typedef struct optparse_long Optparse; + +struct Captor { initializer_t init; getter_t get; cleaner_t clean; labeler_t label; + int nb_opt; }; int nb_defined_captors = 0; #include "captors.h" -struct captor captors[NB_CAPTORS]; - -#define NB_OPTS 6 -struct optparse_long longopts[NB_OPTS + NB_CAPTORS + 1] = { - {"overhead-stats", 's', OPTPARSE_NONE}, - {"list", 'l', OPTPARSE_NONE}, - {"freq", 'f', OPTPARSE_REQUIRED}, - {"time", 't', OPTPARSE_REQUIRED}, - {"exec", 'e', OPTPARSE_REQUIRED}, - {"logfile", 'o', OPTPARSE_REQUIRED}, +Captor captors[NB_CAPTOR]; + +#define NB_OPT 5 +Optparse longopts[NB_OPT + NB_CAPTOR_OPT + 1] = { + { + .longname = "freq", .shortname = 'f', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<freq>", + .usage_msg = "specify frequency", + }, + { + .longname = "time", .shortname = 't', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<time>", + .usage_msg = "specify time", + }, + { + .longname = "exec", .shortname = 'e', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<cmd>", + .usage_msg = "specify a command", + }, + { + .longname = "logfile", .shortname = 'o', .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<file>", + .usage_msg = "specify a log file", + }, + { + .longname = "overhead-stats", .shortname = 's', .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "enable overhead statistics in nanoseconds", + }, }; +void printopt(Optparse *opt) +{ + printf("-%c", opt->shortname); + printf("|--%s", opt->longname); + if (opt->usage_arg != NULL) { + printf(" %s", opt->usage_arg); + } + printf("\n\t%s\n", opt->usage_msg); +} + void usage(char **argv) { - printf("Usage : %s [OPTIONS] [CAPTOR ...] [-o logfile] [-e cmd ...]\n" - "\nOPTIONS:\n" - "-t <time>\t\tspecify time\n" - "-f <freq>\t\tspecify frequency\n" - "-e <cmd>\t\tspecify a command\n" - "-l\t\tlist the possible performance counters and quit\n" - "-s\t\tenable overhead statistics in nanoseconds\n" - "if time==0 then loops infinitively\n" - "if -e is present, time and freq are not used\n" - , argv[0]); + printf("Usage : %s [OPTIONS] [CAPTOR ...]\n", argv[0]); + + printf("\nOPTIONS:\n"); + for (int i = 0; i < NB_OPT; i++) { + printopt(&longopts[i]); + } + printf("if time==0 then loops infinitively\n" + "if -e is present, time and freq are not used\n"); if (nb_defined_captors == 0) { // no captor to show @@ -82,13 +113,8 @@ void usage(char **argv) } printf("\nCAPTORS:\n"); - - for (int i = 0; i < nb_defined_captors; i++) { - printf("-%c", longopts[NB_OPTS + i].shortname); - if (captors[i].usage_arg != NULL) { - printf(" %s", captors[i].usage_arg); - } - printf("\n\t%s\n", captors[i].usage_msg); + for (int i = 0; i < NB_CAPTOR_OPT; i++) { + printopt(&longopts[NB_OPT + i]); } exit(EXIT_FAILURE); @@ -123,7 +149,7 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void add_source(struct captor *cpt, char *arg) +void add_source(Captor *cpt, char *arg) { nb_sources++; initializer_t init = cpt->init; @@ -160,7 +186,7 @@ int main(int argc, char **argv) char **application = NULL; int stat_mode = -1; - init_captors(longopts, captors, NB_OPTS + NB_CAPTORS, NB_OPTS, &nb_defined_captors); + init_captors(longopts, captors, NB_OPT + NB_CAPTOR_OPT, NB_OPT, &nb_defined_captors); if (argc == 1) { usage(argv); @@ -207,10 +233,15 @@ int main(int argc, char **argv) break; default: { int ismatch = 0; + int opt_idx = NB_OPT; for (int i = 0; i < nb_defined_captors && !ismatch; i++) { - if (opt == longopts[NB_OPTS + i].shortname) { - ismatch = 1; - add_source(&captors[i], options.optarg); + for (int j = 0; j < captors[i].nb_opt; j++) { + if (opt == longopts[opt_idx].shortname) { + ismatch = 1; + add_source(&captors[i], options.optarg); + break; + } + opt_idx++; } } if (!ismatch) { diff --git a/src/network.h b/src/network.h index 3182587..82fcfc3 100644 --- a/src/network.h +++ b/src/network.h @@ -23,13 +23,20 @@ unsigned int get_network(uint64_t *results, void *); void clean_network(void *); void label_network(char **labels, void *); -struct optparse_long network_opt = {"net-dev", 'd', OPTPARSE_REQUIRED}; -struct captor network = { - .usage_arg = "<net_dev>", - .usage_msg = "network monitoring (if network_device is X, tries to detect it automatically)", +Captor network = { .init = init_network, .get = get_network, .clean = clean_network, .label = label_network, + .nb_opt = 1, }; +Optparse network_opt[1] = { + { + .longname = "net-dev", + .shortname = 'd', + .argtype = OPTPARSE_REQUIRED, + .usage_arg = "<net_dev>", + .usage_msg = "network monitoring (if network_device is X, tries to detect it automatically)", + }, +}; diff --git a/src/optparse.h b/src/optparse.h index 04e60f6..b1908d4 100644 --- a/src/optparse.h +++ b/src/optparse.h @@ -71,6 +71,8 @@ struct optparse_long { const char *longname; int shortname; enum optparse_argtype argtype; + char *usage_arg; + char *usage_msg; }; /** diff --git a/src/rapl.h b/src/rapl.h index b8dc9a2..95f9fd4 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -23,13 +23,21 @@ unsigned int get_rapl(uint64_t *results, void *); void clean_rapl(void *); void label_rapl(char **labels, void *); -struct optparse_long rapl_opt = {"rapl", 'r', OPTPARSE_NONE}; -struct captor rapl = { - .usage_arg = NULL, - .usage_msg = "RAPL", +Captor rapl = { .init = init_rapl, .get = get_rapl, .clean = clean_rapl, .label = label_rapl, + .nb_opt = 1, +}; + +Optparse rapl_opt[1] = { + { + .longname = "rapl", + .shortname = 'r', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "RAPL", + }, }; diff --git a/src/temperature.h b/src/temperature.h index 5e8046e..ec2faef 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -23,12 +23,20 @@ unsigned int get_temperature(uint64_t *results, void *); void clean_temperature(void *); void label_temperature(char **labels, void *); -struct optparse_long temperature_opt = {"cpu-temp", 'c', OPTPARSE_NONE}; -struct captor temperature = { - .usage_arg = NULL, - .usage_msg = "processor temperature", +Captor temperature = { .init = init_temperature, .get = get_temperature, .clean = clean_temperature, .label = label_temperature, + .nb_opt = 1, +}; + +Optparse temperature_opt[1] = { + { + .longname = "cpu-temp", + .shortname = 'c', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "processor temperature" + }, }; -- GitLab From ea44320719bf3b4c74772dc732535ae1e45e214b Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 13:05:29 +0100 Subject: [PATCH 34/69] update documentation (doc/counter_ex.h) --- doc/counter_ex.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/counter_ex.h b/doc/counter_ex.h index 4ab7915..5702adc 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -7,12 +7,20 @@ unsigned int get_acc(uint64_t *results, void *); void clean_acc(void *); void label_acc(char **labels, void *); -struct optparse_long counters_opt = {"accumulator", 'a', OPTPARSE_NONE}; -struct captor counters = { - .usage_arg = NULL, - .usage_msg = "dumb accumulator\n" +Captor rapl = { .init = init_acc, .get = get_acc, .clean = clean_acc, .label = label_acc, + .nb_opt = 1, +}; + +Optparse rapl_opt[1] = { + { + .longname = "accumulator", + .shortname = 'a', + .argtype = OPTPARSE_NONE, /* OPTPARSE_NONE / OPTPARSE_OPTIONAL / OPTPARSE_REQUIRED */ + .usage_arg = NULL, + .usage_msg = "dumb accumulator", + }, }; -- GitLab From 569f527a427531691dee1b9e305cab5d4b6d00f8 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 31 Jan 2023 17:32:40 +0100 Subject: [PATCH 35/69] Add a generation system for README.md and doc/mojitos.1 - README.md can be updated via `make readme` - doc/mojitos.1 can be generated via `make man` - README.md is updated and doc/mojitos.1 generated on `make all` - correct wrong translation "captor", to "sensor" - update README.md build instructions - mv src/optparse.h and src/info_reader.h to ./lib/ - add the possibility to execute an alternative function when parsing sensor options (other than `add_source()`) --- .gitignore | 3 +- README.md | 75 +++++++++++++------------- configure.sh | 91 ++++++++++++++++--------------- doc/counter_ex.h | 2 +- doc/{mojitos.1 => mojitos.pre.1} | 41 +++----------- {src => lib}/info_reader.h | 0 {src => lib}/optparse.h | 1 + makefile | 18 +++++-- src/amd_rapl.h | 2 +- src/counters.c | 6 ++- src/counters.h | 7 +-- src/infiniband.h | 2 +- src/load.h | 2 +- src/mojitos.c | 93 +++++++++++++++++++++----------- src/network.h | 2 +- src/rapl.h | 2 +- src/temperature.h | 2 +- tools/update-readme-usage.sh | 27 ++++++++++ 18 files changed, 213 insertions(+), 163 deletions(-) rename doc/{mojitos.1 => mojitos.pre.1} (69%) rename {src => lib}/info_reader.h (100%) rename {src => lib}/optparse.h (99%) create mode 100755 tools/update-readme-usage.sh diff --git a/.gitignore b/.gitignore index 6643912..31260f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ doc/test_main_ex doc/info_reader_ex +doc/mojitos.1 tests/run src/counters_option.h src/sensors.h -captors.mk +sensors.mk bin obj *.swp diff --git a/README.md b/README.md index 6422ce0..10f5aaf 100644 --- a/README.md +++ b/README.md @@ -6,51 +6,52 @@ MojitO/S runs on GNU/Linux ## Usage ```bash -Usage : mojitos [-rsu] [-t time] [-f freq] [-p perf_list] \ - [-d network_device] [-o logfile] [-e command arguments...] - mojitos [-l] - - -s Enable overhead statistics (in nanoseconds). - - -u Enable system-level load monitoring. - - -r Enable RAPL. - - -p perf_list - Enable performance counters. The argument is a coma separated - list of performance counters. - - -d net_device - Enable network monitoring. - - -l List the available performance counters and quit. - - -t time - Set duration value (in seconds). If 0, then loops indefinitely. - - -f freq - Set amount of measurements per second. - - -e cmd ... - Execute a command with optional arguments. If this option is - used, any usage of -t or -f is ignored. +Usage : ./bin/mojitos [OPTIONS] [SENSOR ...] [-e <cmd> ...] + +OPTIONS: +-f|--freq <freq> + set amount of measurements per second. +-t|--time <time> + set duration value (seconds). If 0, then loops infinitely. +-e|--exec <cmd> ... + Execute a command with optional arguments. + If this option is used, any usage of -t or -f is ignored. +-o|--logfile <file> + specify a log file. +-s|--overhead-stats + enable overhead statistics (nanoseconds). + +SENSORS: +-p|--perf-list <perf_list> + performance counters + perf_list is a coma separated list of performance counters. + Ex: instructions,cache_misses +-l|--list + list the available performance counters and quit +-u|--sysload + system load +-d|--net-dev <net_dev> + network monitoring (if network_device is X, tries to detect it automatically) +-r|--rapl + RAPL +-c|--cpu-temp + processor temperature ``` ## Installation Instructions -Dependencies -```bash -sudo apt install libpowercap0 libpowercap-dev powercap-utils python3 -``` Download the source code ```bash git clone https://gitlab.irit.fr/sepia-pub/mojitos.git ``` -Compile the code +The quickest way to compile the code is: ```bash cd mojitos +./configure.sh make ``` +You may want to run `./configure.sh --help` to see configuration options. + To execute mojitos without being root to monitor performance counters ```bash sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' @@ -65,7 +66,7 @@ sudo chmod a+w /sys/class/powercap/intel-rapl/*/*/* RAPL values during 2 seconds with a frequency of 2 Hz ```bash -$ ./mojitos -t 2 -f 2 -r +$ ./bin/mojitos -t 2 -f 2 -r #timestamp package-00 core0 dram0 1036389.135659868 10986 2869 1526 1036389.500183551 1291440 255736 515562 @@ -75,7 +76,7 @@ $ ./mojitos -t 2 -f 2 -r Performance counters (cpu_cycle, cache_ll_r_a and page_faults) during 4 seconds with a frequency of 1Hz. For cache performance counters, _r and _w are respectively read and write, and _a, _m and _p are respectively access, miss, pending. ```bash -$ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults +$ ./bin/mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults #timestamp cpu_cycles cache_ll page_faults 1036846.351749455 571199 1232 0 1036847.001098880 348173344 2451387 872 @@ -85,7 +86,7 @@ $ ./mojitos -t 4 -f 1 -p cpu_cycles,cache_ll_r_a,page_faults Network values with no time limit with a frequency of 1Hz. rxp and txp are the number of received and sent packets, while rxb and txp are the number of received and sent bytes. ```bash -$ ./mojitos -t 0 -f 1 -d enp0s25 +$ ./bin/mojitos -t 0 -f 1 -d enp0s25 #timestamp rxp rxb txp txb 1036559.277376027 0 0 0 0 1036560.000161101 4 581 2 179 @@ -97,7 +98,7 @@ $ ./mojitos -t 0 -f 1 -d enp0s25 Overhead of the monitoring for RAPL and cpu_cycle ```bash -$ ./mojitos -t 5 -f 1 -p cpu_cycles -r -s +$ ./bin/mojitos -t 5 -f 1 -p cpu_cycles -r -s #timestamp cpu_cycles package-00 core0 dram0 overhead 1036988.197227391 162214 19898 4944 1586 149612 1036989.000151326 332613664 2513116 379577 1115171 739573 diff --git a/configure.sh b/configure.sh index 49e1789..62f297a 100755 --- a/configure.sh +++ b/configure.sh @@ -20,25 +20,25 @@ decho() { } debug=0 -target_hdr=src/captors.h -target_mk=captors.mk +target_hdr=src/sensors.h +target_mk=sensors.mk -noncaptor='counters_option|optparse|captors|util|info_reader' +nonsensor='counters_option|optparse|sensors|util|info_reader' -hdr_blacklist=$noncaptor +hdr_blacklist=$nonsensor hdr_whitelist='' usage() { - printf -- 'Usage: %s [-l] [-e <captor>] [-i <captor>] [-u <captor>]\n' "$(basename "$0")" >&2 - printf -- '-e | --exclude : exclude captor, can be called multiple times\n' >&2 - printf -- '-i | --include : include captor, can be called multiple times\n' >&2 - printf -- '-l | --list-captors : list all captors and exit\n' >&2 - printf -- '-u | --unique : only include the specified captor\n' >&2 + printf -- 'Usage: %s [-l] [-e <sensor>] [-i <sensor>] [-u <sensor>]\n' "$(basename "$0")" >&2 + printf -- '-e | --exclude : exclude sensor, can be called multiple times\n' >&2 + printf -- '-i | --include : include sensor, can be called multiple times\n' >&2 + printf -- '-l | --list-sensors : list all sensors and exit\n' >&2 + printf -- '-u | --unique : only include the specified sensor\n' >&2 printf -- ' if this option is used, any usage of `-e` or `-i` will be ignored\n' >&2 exit 1 } -ls_captors() { +ls_sensors() { try cd src [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' @@ -51,49 +51,52 @@ ls_captors() { sed 's/\.h$//' } -# gen_captors_h(captors, nb_captors) -gen_captors_h() { - captors=$1 - nb_captors=$2 - nb_captor_opts=$( - for captor in $captors; do - sed -n 's/.*'"${captor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${captor}.h" +# gen_sensors_h(sensor, nb_sensors) +gen_sensors_h() { + sensors=$1 + nb_sensors=$2 + nb_sensor_opts=$( + for sensor in $sensors; do + sed -n 's/.*'"${sensor}"'_opt\[\([0-9]\+\)\].*/\1/p' "src/${sensor}.h" done | paste -s -d '+' | bc ) - dprint captors >&2 - dprint nb_captor_opts >&2 - isnum "$nb_captor_opts" || die "could not get total number of captors's command-line options" + dprint sensors >&2 + dprint nb_sensor_opts >&2 + isnum "$nb_sensor_opts" || die "could not get total number of sensors's command-line options" # gen includes - for captor in $captors; do - printf '#include "%s.h"\n' "$captor" + for sensor in $sensors; do + printf '#include "%s.h"\n' "$sensor" done - printf '\n#define NB_CAPTOR %d\n\n' "$nb_captors" - printf '\n#define NB_CAPTOR_OPT %d\n\n' "$nb_captor_opts" + printf '\n' + + printf '#define NB_SENSOR %d\n' "$nb_sensors" + printf '#define NB_SENSOR_OPT %d\n' "$nb_sensor_opts" + printf '\n' - # gen `init_captors()` - printf 'void init_captors(Optparse *longopts, Captor *captors, size_t len, size_t offset, int *nb_defined)\n{\n' + # gen `init_sensors()` + printf 'void init_sensors(Optparse *opts, Sensor *sensors, size_t len, size_t offset, int *nb_defined)\n{\n' printf ' int opt_idx = offset;\n' - for captor in $captors; do + for sensor in $sensors; do cat <<-! - for (int i = 0; i < ${captor}.nb_opt; i++) { - longopts[opt_idx++] = ${captor}_opt[i]; + for (int i = 0; i < ${sensor}.nb_opt; i++) { + opts[opt_idx++] = ${sensor}_opt[i]; } - captors[(*nb_defined)++] = ${captor}; + sensors[(*nb_defined)++] = ${sensor}; ! done printf ' assert((offset + *nb_defined) <= len);\n' printf '}\n' } -gen_captors_mk() { - captors=$1 +gen_sensors_mk() { + sensors=$1 printf 'CAPTOR_OBJ = ' - for captor in $captors; do - printf '$(OBJ_DIR)/%s.o ' "$captor" + for sensor in $sensors; do + printf '$(OBJ_DIR)/%s.o ' "$sensor" done printf '\n' } @@ -140,8 +143,8 @@ while [ "$1" ]; do shift; [ "$1" ] || usage hdr_blacklist="${hdr_blacklist}|${1}" ;; - --list-captors|-l) - ls_captors + --list-sensors|-l) + ls_sensors exit 0 ;; --unique|-u) @@ -155,20 +158,20 @@ while [ "$1" ]; do shift done -captors=$(ls_captors) -nb_captors=$(echo "$captors" | sed '/^$/d' | wc -l) +sensors=$(ls_sensors) +nb_sensors=$(echo "$sensors" | sed '/^$/d' | wc -l) -if [ "$nb_captors" -eq 0 ]; then - printf -- '0 captors are selected. cannot build.\n' >&2 +if [ "$nb_sensors" -eq 0 ]; then + printf -- '0 sensors are selected. cannot build.\n' >&2 exit 1 fi -try gen_captors_h "$captors" "$nb_captors" > "$target_hdr" -try gen_captors_mk "$captors" > "$target_mk" +try gen_sensors_h "$sensors" "$nb_sensors" > "$target_hdr" +try gen_sensors_mk "$sensors" > "$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 -printf -- 'The resulting binary will have the %d following captors:\n' "$nb_captors" >&2 -echo "$captors" >&2 +printf -- 'The resulting binary will have the %d following sensors:\n' "$nb_sensors" >&2 +echo "$sensors" >&2 make clean >/dev/null diff --git a/doc/counter_ex.h b/doc/counter_ex.h index 5702adc..65fabf3 100644 --- a/doc/counter_ex.h +++ b/doc/counter_ex.h @@ -7,7 +7,7 @@ unsigned int get_acc(uint64_t *results, void *); void clean_acc(void *); void label_acc(char **labels, void *); -Captor rapl = { +Sensor rapl = { .init = init_acc, .get = get_acc, .clean = clean_acc, diff --git a/doc/mojitos.1 b/doc/mojitos.pre.1 similarity index 69% rename from doc/mojitos.1 rename to doc/mojitos.pre.1 index a7927e8..af9cb9b 100644 --- a/doc/mojitos.1 +++ b/doc/mojitos.pre.1 @@ -3,47 +3,18 @@ .Os .Sh NAME .Nm mojitos -.Nd An open source system, energy and network monitoring tool. +.Nd An open source system monitoring tool. .Sh SYNOPSIS .Nm mojitos -.Op Fl rsu -.Op Fl t Ar time -.Op Fl f Ar freq -.Op Fl p Ar perf_list -.Op Fl d Ar net_device -.Op Fl o Ar logfile +.Op Ar OPTIONS +.Op Ar SENSOR ... .Op Fl e Ar cmd ... -.Nm mojitos -.Op Fl l .Sh DESCRIPTION .Nm -enables monitoring the system, its energy comsumption and the network activity, at the OS level. -It runs on GNU/Linux. -.Pp +is a monitoring tool with a multitude of sensors that does measurements at the OS level. .Nm -supports the following options: -.Bl -tag -width Ds -.It Fl s -Enable overhead statistics (in nanoseconds). -.It Fl u -Enable system-level load monitoring. -.It Fl r -Enable RAPL. -.It Fl p Ar perf_list -Enable performance counters. -The argument is a coma separated list of performance counters. -.It Fl d Ar net_device -Enable network monitoring. -.It Fl l -List the available performance counters and quit. -.It Fl t Ar time -Set duration value (in seconds). If 0, then loops indefinitely. -.It Fl f Ar freq -Set amount of measurements per second. -.It Fl e Ar cmd ... -Execute a command with optional arguments. -If this option is used, any usage of -t or -f is ignored. -.El +runs on GNU/Linux. +USAGE .Sh EXIT STATUS .Ex .Sh EXAMPLES diff --git a/src/info_reader.h b/lib/info_reader.h similarity index 100% rename from src/info_reader.h rename to lib/info_reader.h diff --git a/src/optparse.h b/lib/optparse.h similarity index 99% rename from src/optparse.h rename to lib/optparse.h index b1908d4..1925d73 100644 --- a/src/optparse.h +++ b/lib/optparse.h @@ -73,6 +73,7 @@ struct optparse_long { enum optparse_argtype argtype; char *usage_arg; char *usage_msg; + void *(*fn)(void *, size_t); }; /** diff --git a/makefile b/makefile index 3f8a70b..d5d2d23 100644 --- a/makefile +++ b/makefile @@ -10,21 +10,21 @@ BIN = mojitos CAPTOR_OBJ = -include ./captors.mk +include ./sensors.mk OBJ = \ $(CAPTOR_OBJ) \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib CFLAGS = $(CPPFLAGS) -O3 -Werror LDFLAGS = ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -all: $(BIN) +all: $(BIN) readme man $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o @@ -48,7 +48,7 @@ $(BIN_DIR): mkdir -p $(BIN_DIR) debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og -debug: all +debug: $(BIN) tests: gcc $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run @@ -64,4 +64,12 @@ clean: \rm -f $(SRC_DIR)/counters_option.h \rm -f $(TESTS_DIR)/run -.PHONY: all clean mojitos debug format tests +readme: $(BIN) + sh ./tools/update-readme-usage.sh + +man: $(BIN) + awk -v "usage=$$($(BIN_DIR)/$(BIN) -1)" \ + '/^USAGE/ { $$0=usage } 1' \ + doc/mojitos.pre.1 > doc/mojitos.1 2>/dev/null + +.PHONY: all clean mojitos debug format tests readme man diff --git a/src/amd_rapl.h b/src/amd_rapl.h index 52a7c6c..1a16db8 100644 --- a/src/amd_rapl.h +++ b/src/amd_rapl.h @@ -23,7 +23,7 @@ unsigned int get_amd_rapl(uint64_t *results, void *); void clean_amd_rapl(void *); void label_amd_rapl(char **labels, void *); -Captor amd_rapl = { +Sensor amd_rapl = { .init = init_amd_rapl, .get = get_amd_rapl, .clean = clean_amd_rapl, diff --git a/src/counters.c b/src/counters.c index 874e6fc..d42ceae 100644 --- a/src/counters.c +++ b/src/counters.c @@ -44,11 +44,15 @@ typedef struct _counter_t *counter_t; #include "counters_option.h" -void show_all_counters() +void *show_all_counters(void *none1, size_t none2) { for (unsigned int i = 0; i < nb_counter_option; i++) { printf("%s\n", perf_static_info[i].name); } + UNUSED(none1); + UNUSED(none2); + exit(EXIT_SUCCESS); + return NULL; /* not reached */ } void perf_type_key(__u32 **perf_type, __u64 **perf_key, int *indexes, int nb) diff --git a/src/counters.h b/src/counters.h index a191e5a..0304a07 100644 --- a/src/counters.h +++ b/src/counters.h @@ -22,9 +22,9 @@ unsigned int init_counters(char *, void **); unsigned int get_counters(uint64_t *results, void *); void clean_counters(void *); void label_counters(char **labels, void *); -void show_all_counters(); +void *show_all_counters(void *, size_t); -Captor counters = { +Sensor counters = { .init = init_counters, .get = get_counters, .clean = clean_counters, @@ -47,7 +47,8 @@ Optparse counters_opt[2] = { .shortname = 'l', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "list the possible performance counters and quit" + .usage_msg = "list the available performance counters and quit", + .fn = show_all_counters, }, }; diff --git a/src/infiniband.h b/src/infiniband.h index 285b2ba..fac05f8 100644 --- a/src/infiniband.h +++ b/src/infiniband.h @@ -21,7 +21,7 @@ unsigned int init_infiniband(char *infi_path, void **ptr); void label_infiniband(char **labels, void *); -Captor infiniband = { +Sensor infiniband = { .init = init_infiniband, .get = NULL, .clean = NULL, diff --git a/src/load.h b/src/load.h index c7c5575..038b263 100644 --- a/src/load.h +++ b/src/load.h @@ -23,7 +23,7 @@ unsigned int get_load(uint64_t *results, void *); void clean_load(void *); void label_load(char **labels, void *); -Captor load = { +Sensor load = { .init = init_load, .get = get_load, .clean = clean_load, diff --git a/src/mojitos.c b/src/mojitos.c index 683bdfa..3ecf111 100644 --- a/src/mojitos.c +++ b/src/mojitos.c @@ -38,11 +38,11 @@ typedef unsigned int (*getter_t)(uint64_t *, void *); typedef void (*cleaner_t)(void *); typedef struct Opt Opt; -typedef struct Captor Captor; +typedef struct Sensor Sensor; /* optparse typedef */ typedef struct optparse_long Optparse; -struct Captor { +struct Sensor { initializer_t init; getter_t get; cleaner_t clean; @@ -50,41 +50,70 @@ struct Captor { int nb_opt; }; -int nb_defined_captors = 0; +int nb_defined_sensors = 0; -#include "captors.h" +#include "sensors.h" -Captor captors[NB_CAPTOR]; +Sensor sensors[NB_SENSOR]; #define NB_OPT 5 -Optparse longopts[NB_OPT + NB_CAPTOR_OPT + 1] = { +Optparse opts[NB_OPT + NB_SENSOR_OPT + 1] = { { .longname = "freq", .shortname = 'f', .argtype = OPTPARSE_REQUIRED, .usage_arg = "<freq>", - .usage_msg = "specify frequency", + .usage_msg = "set amount of measurements per second.", }, { .longname = "time", .shortname = 't', .argtype = OPTPARSE_REQUIRED, .usage_arg = "<time>", - .usage_msg = "specify time", + .usage_msg = "set duration value (seconds). If 0, then loops infinitely.", }, { .longname = "exec", .shortname = 'e', .argtype = OPTPARSE_REQUIRED, - .usage_arg = "<cmd>", - .usage_msg = "specify a command", + .usage_arg = "<cmd> ...", + .usage_msg = "Execute a command with optional arguments.\n" + "\tIf this option is used, any usage of -t or -f is ignored.", }, { .longname = "logfile", .shortname = 'o', .argtype = OPTPARSE_REQUIRED, .usage_arg = "<file>", - .usage_msg = "specify a log file", + .usage_msg = "specify a log file.", }, { .longname = "overhead-stats", .shortname = 's', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "enable overhead statistics in nanoseconds", + .usage_msg = "enable overhead statistics (nanoseconds).", }, }; +void dumpopt(Optparse *opt) +{ + printf(".It Fl %c | Fl \\-%s", opt->shortname, opt->longname); + if (opt->usage_arg != NULL) { + printf(" Ar %s", opt->usage_arg); + } + printf("\n"); + printf("%s\n", opt->usage_msg); +} + +void dumpopts(Optparse *opts, size_t nb_opt, size_t nb_sensor_opt) +{ + size_t i; + + /* options */ + printf(".Pp\nOPTIONS:\n.Bl -tag -width Ds\n"); + for (i = 0; i < nb_opt; i++) { + dumpopt(&opts[i]); + } + printf(".El\n"); + + /* sensors */ + printf(".Pp\nSENSORS:\n.Bl -tag -width Ds\n"); + for (i++; i < nb_opt + nb_sensor_opt; i++) { + dumpopt(&opts[i]); + } + printf(".El\n"); +} void printopt(Optparse *opt) { @@ -98,23 +127,21 @@ void printopt(Optparse *opt) void usage(char **argv) { - printf("Usage : %s [OPTIONS] [CAPTOR ...]\n", argv[0]); + printf("Usage : %s [OPTIONS] [SENSOR ...] [-e <cmd> ...]\n", argv[0]); printf("\nOPTIONS:\n"); for (int i = 0; i < NB_OPT; i++) { - printopt(&longopts[i]); + printopt(&opts[i]); } - printf("if time==0 then loops infinitively\n" - "if -e is present, time and freq are not used\n"); - if (nb_defined_captors == 0) { + if (nb_defined_sensors == 0) { // no captor to show exit(EXIT_FAILURE); } - printf("\nCAPTORS:\n"); - for (int i = 0; i < NB_CAPTOR_OPT; i++) { - printopt(&longopts[NB_OPT + i]); + printf("\nSENSORS:\n"); + for (int i = 0; i < NB_SENSOR_OPT; i++) { + printopt(&opts[NB_OPT + i]); } exit(EXIT_FAILURE); @@ -149,7 +176,7 @@ unsigned int nb_sensors = 0; char **labels = NULL; uint64_t *values = NULL; -void add_source(Captor *cpt, char *arg) +void add_source(Sensor *cpt, char *arg) { nb_sources++; initializer_t init = cpt->init; @@ -186,12 +213,17 @@ int main(int argc, char **argv) char **application = NULL; int stat_mode = -1; - init_captors(longopts, captors, NB_OPT + NB_CAPTOR_OPT, NB_OPT, &nb_defined_captors); + init_sensors(opts, sensors, NB_OPT + NB_SENSOR_OPT, NB_OPT, &nb_defined_sensors); if (argc == 1) { usage(argv); } + if (argc == 2 && argv[1][0] == '-' && argv[1][1] == '1' && argv[1][2] == '\0') { + dumpopts(opts, NB_OPT, NB_SENSOR_OPT); + exit(EXIT_SUCCESS); + } + output = stdout; atexit(flushexit); @@ -202,7 +234,7 @@ int main(int argc, char **argv) options.permute = 0; optparse_init(&options, argv); - while ((opt = optparse_long(&options, longopts, NULL)) != -1 && application == NULL) { + while ((opt = optparse_long(&options, opts, NULL)) != -1 && application == NULL) { switch (opt) { case 'f': frequency = atoi(options.optarg); @@ -218,9 +250,6 @@ int main(int argc, char **argv) case 's': stat_mode = 0; break; - case 'l': - show_all_counters(); - exit(EXIT_SUCCESS); case 'o': if ((output = fopen(options.optarg, "wb")) == NULL) { perror("fopen"); @@ -234,11 +263,15 @@ int main(int argc, char **argv) default: { int ismatch = 0; int opt_idx = NB_OPT; - for (int i = 0; i < nb_defined_captors && !ismatch; i++) { - for (int j = 0; j < captors[i].nb_opt; j++) { - if (opt == longopts[opt_idx].shortname) { + for (int i = 0; i < nb_defined_sensors && !ismatch; i++) { + for (int j = 0; j < sensors[i].nb_opt; j++) { + if (opt == opts[opt_idx].shortname) { ismatch = 1; - add_source(&captors[i], options.optarg); + if (opts[opt_idx].fn != NULL) { + (void) opts[opt_idx].fn(NULL, 0); + } else { + add_source(&sensors[i], options.optarg); + } break; } opt_idx++; diff --git a/src/network.h b/src/network.h index 82fcfc3..994651a 100644 --- a/src/network.h +++ b/src/network.h @@ -23,7 +23,7 @@ unsigned int get_network(uint64_t *results, void *); void clean_network(void *); void label_network(char **labels, void *); -Captor network = { +Sensor network = { .init = init_network, .get = get_network, .clean = clean_network, diff --git a/src/rapl.h b/src/rapl.h index 95f9fd4..a02624d 100644 --- a/src/rapl.h +++ b/src/rapl.h @@ -23,7 +23,7 @@ unsigned int get_rapl(uint64_t *results, void *); void clean_rapl(void *); void label_rapl(char **labels, void *); -Captor rapl = { +Sensor rapl = { .init = init_rapl, .get = get_rapl, .clean = clean_rapl, diff --git a/src/temperature.h b/src/temperature.h index ec2faef..8609dba 100644 --- a/src/temperature.h +++ b/src/temperature.h @@ -23,7 +23,7 @@ unsigned int get_temperature(uint64_t *results, void *); void clean_temperature(void *); void label_temperature(char **labels, void *); -Captor temperature = { +Sensor temperature = { .init = init_temperature, .get = get_temperature, .clean = clean_temperature, diff --git a/tools/update-readme-usage.sh b/tools/update-readme-usage.sh new file mode 100755 index 0000000..b9f16de --- /dev/null +++ b/tools/update-readme-usage.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +die() { yell "$*"; exit 111; } +try() { "$@" || die "cannot $*"; } +yell() { echo "$0: $*" >&2; } +echo() { printf '%s\n' "$*"; } + +usage=$(./bin/mojitos) +[ -n "$usage" ] || die 'empty usage. try to recompile mojitos.' + +try awk -v "usage=$usage" ' + /^Usage/ { + print usage + del = 1 + } + { + if (del == 1) { + if (match($0, "^```")) { + del = 0 + print $0 + } + } else { + print $0 + } + } +' README.md > README.tmp +try mv README.tmp README.md -- GitLab From 24f03a059ada281567c9b7a600cd461619865640 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 6 Feb 2023 10:43:08 +0100 Subject: [PATCH 36/69] small changes --- lib/optparse.h | 2 +- makefile | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/optparse.h b/lib/optparse.h index 1925d73..ee7dcb6 100644 --- a/lib/optparse.h +++ b/lib/optparse.h @@ -73,7 +73,7 @@ struct optparse_long { enum optparse_argtype argtype; char *usage_arg; char *usage_msg; - void *(*fn)(void *, size_t); + void *(*fn)(void *, size_t); /* SUBJECT TO CHANGE */ }; /** diff --git a/makefile b/makefile index d5d2d23..950028c 100644 --- a/makefile +++ b/makefile @@ -55,14 +55,14 @@ tests: $(TESTS_DIR)/run format: - $(ASTYLE) $(SRC_DIR)/*.[ch] - $(ASTYLE) $(DOC_DIR)/*.[ch] - $(ASTYLE) $(TESTS_DIR)/*.[ch] + $(ASTYLE) $(SRC_DIR)/*.[ch] \ + $(DOC_DIR)/*.[ch] \ + $(TESTS_DIR)/*.[ch] clean: - \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* - \rm -f $(SRC_DIR)/counters_option.h - \rm -f $(TESTS_DIR)/run + \rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \ + $(SRC_DIR)/counters_option.h \ + $(TESTS_DIR)/run readme: $(BIN) sh ./tools/update-readme-usage.sh -- GitLab From 82dc9a2e4bf08ff775bd255159fb04bb3e7346d5 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 20 Feb 2023 11:50:56 +0100 Subject: [PATCH 37/69] add some error checking --- src/network.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/network.c b/src/network.c index aee5659..0f23206 100644 --- a/src/network.c +++ b/src/network.c @@ -17,14 +17,17 @@ along with MojitO/S. If not, see <https://www.gnu.org/licenses/>. *******************************************************/ -#include <unistd.h> +#include <errno.h> #include <fcntl.h> -#include <stdlib.h> +#include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <stdint.h> +#include <unistd.h> + #include "util.h" +#define NB_MAX_DEV 8 #define NB_SENSOR 4 static char *route = "/proc/net/route"; @@ -39,6 +42,8 @@ struct network_t { uint64_t tmp_values[NB_SENSOR]; int sources[NB_SENSOR]; char labels[NB_SENSOR][128]; + char dev[NB_MAX_DEV][128]; + int ndev; }; unsigned int _get_network(uint64_t *results, int *sources) @@ -103,7 +108,14 @@ unsigned int init_network(char *dev, void **ptr) char buffer2[256]; for (int i = 0; i < NB_SENSOR; i++) { snprintf(buffer2, sizeof(buffer2), filenames[i], dev); - state->sources[i] = open(buffer2, O_RDONLY); + errno = 0; + int fd = open(buffer2, O_RDONLY); + if (fd < 0) { + perror("init_network: open"); + free(state); + return 0; + } + state->sources[i] = fd; snprintf(state->labels[i], sizeof(state->labels[i]), _labels_network[i], dev); } -- GitLab From 1cb227e7cd0d3f6562d06f4266017176daca4ecc Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 20 Feb 2023 17:21:13 +0100 Subject: [PATCH 38/69] add MIN() and MAX() macros to util.h --- src/util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util.h b/src/util.h index 23978c1..b1fa6e3 100644 --- a/src/util.h +++ b/src/util.h @@ -38,6 +38,8 @@ exit(code); \ } while (0) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) /** * @brief Substracts lhs by rhs, assuming that lhs is a cyclic increment from rhs, -- GitLab From 5b82667289ec077d9ed9c5658b72d572810fed08 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 20 Feb 2023 17:21:22 +0100 Subject: [PATCH 39/69] network sensor can now detect multiple routes from /proc/net/route note that there is a hard limit to the number of devices the sensor can watch. this limit is defined by "NB_MAX_DEV" (value of 8 for now) --- src/network.c | 170 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 125 insertions(+), 45 deletions(-) diff --git a/src/network.c b/src/network.c index 0f23206..33fdadf 100644 --- a/src/network.c +++ b/src/network.c @@ -38,18 +38,18 @@ char *_labels_network[NB_SENSOR] = { "%s:txb", }; struct network_t { - uint64_t values[NB_SENSOR]; - uint64_t tmp_values[NB_SENSOR]; - int sources[NB_SENSOR]; - char labels[NB_SENSOR][128]; - char dev[NB_MAX_DEV][128]; + uint64_t values[NB_MAX_DEV][NB_SENSOR]; + uint64_t tmp_values[NB_MAX_DEV][NB_SENSOR]; + int sources[NB_MAX_DEV][NB_SENSOR]; + char labels[NB_MAX_DEV][NB_SENSOR][128]; + char devs[NB_MAX_DEV][128]; int ndev; }; -unsigned int _get_network(uint64_t *results, int *sources) +static void _get_network(uint64_t *results, int *sources) { if (sources == NULL) { - return 0; + return; } char buffer[128]; @@ -62,16 +62,47 @@ unsigned int _get_network(uint64_t *results, int *sources) results[i] = strtoull(buffer, NULL, 10); } +} + +static int strchr_refill(int fd, char *buf, int len, char **s, char c) +{ + *s = strchr(*s, c); + + if (*s == NULL) { + int nbytes = read(fd, buf, len - 1); + if (nbytes < 0) { + perror("read"); + return -1; + } + buf[len - 1] = '\0'; + + /* whole file read */ + if (nbytes == 0) { + return 0; + } + + *s = strchr(buf, c); + } - return NB_SENSOR; + return 1; } unsigned int init_network(char *dev, void **ptr) { if (dev == NULL) { - return 0; + exit(1); } + char *filenames[] = { + "/sys/class/net/%s/statistics/rx_packets", + "/sys/class/net/%s/statistics/rx_bytes", + "/sys/class/net/%s/statistics/tx_packets", + "/sys/class/net/%s/statistics/tx_bytes", + }; + + struct network_t *state = malloc(sizeof(struct network_t)); + memset(state, '\0', sizeof(*state)); + if (strcmp(dev, "X") == 0) { int fd = open(route, O_RDONLY); @@ -83,59 +114,104 @@ unsigned int init_network(char *dev, void **ptr) char buffer[1000]; - if (read(fd, buffer, 999) < 0 ) { - perror("read"); + /* skip first line */ + char *s = buffer; + int ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\n'); + if (ret != 1) { close(fd); + free(state); exit(1); } + s++; - char *start_of_dev = strchr(buffer, '\n') + 1; - char *end_of_dev = strchr(start_of_dev, '\t'); - *end_of_dev = '\0'; - dev = start_of_dev; - close(fd); - } + char *start_of_dev = s; + /* jump to the end of the device name */ + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\t'); + if (ret != 1) { + close(fd); + free(state); + exit(1); + } - char *filenames[] = { - "/sys/class/net/%s/statistics/rx_packets", - "/sys/class/net/%s/statistics/rx_bytes", - "/sys/class/net/%s/statistics/tx_packets", - "/sys/class/net/%s/statistics/tx_bytes", - }; + state->ndev++; // ndev should be equal to 1 at this point + memcpy(&(state->devs[state->ndev - 1]), start_of_dev, + MIN((size_t)(sizeof(state->devs[0]) - 1), (size_t)(s - start_of_dev))); + + for (;;) { + /* jump to the next line */ + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\n'); + if (ret != 1) { + break; + } + s++; + + start_of_dev = s; + ret = strchr_refill(fd, buffer, sizeof(buffer), &s, '\t'); + if (ret != 1) { + break; + } + + /* compare dev name to the previously saved one */ + if (strncmp(start_of_dev, state->devs[state->ndev - 1], s - start_of_dev) != 0) { + if (state->ndev >= NB_MAX_DEV) { + fprintf(stderr, "Maximum amount of network devices exceeded (%d).\n", NB_MAX_DEV); + break; + } + state->ndev++; + memcpy(&(state->devs[state->ndev - 1]), start_of_dev, + MIN((size_t)(sizeof(state->devs[0]) - 1), (size_t)(s - start_of_dev))); + } + } - struct network_t *state = malloc(sizeof(struct network_t)); + close(fd); + } else { + state->ndev = 1; + memcpy(&(state->devs[0]), dev, strlen(dev) + 1); + } char buffer2[256]; - for (int i = 0; i < NB_SENSOR; i++) { - snprintf(buffer2, sizeof(buffer2), filenames[i], dev); - errno = 0; - int fd = open(buffer2, O_RDONLY); - if (fd < 0) { - perror("init_network: open"); - free(state); - return 0; + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + snprintf(buffer2, sizeof(buffer2), filenames[j], state->devs[i]); + errno = 0; + int fd = open(buffer2, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "init_network: open: %s: %.*s\n", strerror(errno), + (int)sizeof(buffer2), buffer2); + free(state); + exit(1); + } + state->sources[i][j] = fd; + snprintf(state->labels[i][j], sizeof(state->labels[i][j]), _labels_network[j], + state->devs[i]); } - state->sources[i] = fd; - snprintf(state->labels[i], sizeof(state->labels[i]), _labels_network[i], dev); } *ptr = (void *) state; - _get_network(state->values, state->sources); - return NB_SENSOR; + for (int i = 0; i < state->ndev; i++) { + _get_network(state->values[i], state->sources[i]); + } + + return state->ndev * NB_SENSOR; } unsigned int get_network(uint64_t *results, void *ptr) { struct network_t *state = (struct network_t *) ptr; - _get_network(state->tmp_values, state->sources); - for (int i = 0; i < NB_SENSOR; i++) { - results[i] = modulo_substraction(state->tmp_values[i], state->values[i]); + for (int i = 0; i < state->ndev; i++) { + _get_network(state->tmp_values[i], state->sources[i]); + + for (int j = 0; j < NB_SENSOR; j++) { + results[i*NB_SENSOR + j] = modulo_substraction(state->tmp_values[i][j], state->values[i][j]); + } + + memcpy(&(state->values[i]), &(state->tmp_values[i]), + NB_SENSOR * sizeof(state->values[i][0])); } - memcpy(state->values, state->tmp_values, NB_SENSOR * sizeof(uint64_t)); - return NB_SENSOR; + return state->ndev * NB_SENSOR; } void clean_network(void *ptr) @@ -146,8 +222,10 @@ void clean_network(void *ptr) return; } - for (int i = 0; i < NB_SENSOR; i++) { - close(state->sources[i]); + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + close(state->sources[i][j]); + } } free(state); @@ -157,7 +235,9 @@ void label_network(char **labels, void *ptr) { struct network_t *state = (struct network_t *) ptr; - for (int i = 0; i < NB_SENSOR; i++) { - labels[i] = state->labels[i]; + for (int i = 0; i < state->ndev; i++) { + for (int j = 0; j < NB_SENSOR; j++) { + labels[i*NB_SENSOR + j] = state->labels[i][j]; + } } } -- GitLab From afec2006a9bab8dfda94ef4ddb05d3c1708792c0 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 21 Feb 2023 16:03:02 +0100 Subject: [PATCH 40/69] add "install" and "uninstall" make targets --- makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index a197961..dc852f4 100644 --- a/makefile +++ b/makefile @@ -7,6 +7,7 @@ BIN_DIR = bin TESTS_DIR = tests BIN = mojitos +PREFIX = /usr/local CAPTOR_OBJ = @@ -74,4 +75,16 @@ man: $(BIN) '/^USAGE/ { $$0=usage } 1' \ doc/$(BIN).pre.1 > doc/$(BIN).1 2>/dev/null -.PHONY: all clean mojitos debug format tests readme man +install: $(BIN) man + mkdir -p $(PREFIX)/bin + cp $(BIN_DIR)/$(BIN) $(PREFIX)/bin/. + chmod 755 $(PREFIX)/bin/$(BIN) + mkdir -p $(PREFIX)/share/man/man1 + cp $(DOC_DIR)/$(BIN).1 $(PREFIX)/share/man/man1/. + chmod 644 $(PREFIX)/share/man/man1/$(BIN).1 + +uninstall: + rm -f $(PREFIX)/bin/$(BIN) + rm -f $(PREFIX)/share/man/man1/$(BIN).1 + +.PHONY: all clean mojitos debug format tests readme man install uninstall -- GitLab From 44b132bf26e445016c9bd6fb75373847d0188b03 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 21 Feb 2023 16:50:00 +0100 Subject: [PATCH 41/69] revise build system (makefile and sensors.mk) Make it more posix compliant (remove '%.o: %.c %.h' usage, which is not posix). Sadly, it appears to not support well separate directories for object and source files: inference rules do not work, and it recompiles everything at each invocation even though there is not necessarily any change within the source files. --- configure.sh | 5 +++++ makefile | 26 ++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/configure.sh b/configure.sh index 21c94ef..747a078 100755 --- a/configure.sh +++ b/configure.sh @@ -103,6 +103,11 @@ gen_sensors_mk() { printf '$(OBJ_DIR)/%s.o ' "$sensor" done printf '\n' + for sensor in $sensors; do + printf '$(OBJ_DIR)/%s.o: $(SRC_DIR)/%s.c $(SRC_DIR)/%s.h $(SRC_DIR)/util.h\n' \ + "$sensor" "$sensor" "$sensor" + printf '\t$(CC) $(CFLAGS) -c $< -o $@\n' + done } detect_caps() { diff --git a/makefile b/makefile index dc852f4..bd26308 100644 --- a/makefile +++ b/makefile @@ -9,14 +9,6 @@ TESTS_DIR = tests BIN = mojitos PREFIX = /usr/local -CAPTOR_OBJ = - -include ./sensors.mk - -OBJ = \ - $(CAPTOR_OBJ) \ - $(OBJ_DIR)/util.o - CC = gcc CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib CFLAGS = $(CPPFLAGS) -O3 -Werror @@ -24,9 +16,23 @@ LDFLAGS = ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q - all: $(BIN) man +CAPTOR_OBJ = + +include ./sensors.mk + +OBJ = \ + $(CAPTOR_OBJ) \ + $(OBJ_DIR)/util.o + +options: + @echo BIN: $(BIN) + @echo CC: $(CC) + @echo CFLAGS: $(CFLAGS) + @echo LDFLAGS: $(LDFLAGS) + @echo OBJ: $(OBJ) + $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o @@ -36,7 +42,7 @@ $(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h $(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(SRC_DIR)/counters_option.h $(CC) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h +$(OBJ_DIR)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h $(CC) $(CFLAGS) -c $< -o $@ $(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh -- GitLab From 745d90b59eadf5e4072c8a6a3ed86d745a674d2a Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Feb 2023 18:58:48 +0100 Subject: [PATCH 42/69] unfinished sensor --- src/nvidia_gpu.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++ src/nvidia_gpu.h | 0 2 files changed, 324 insertions(+) create mode 100644 src/nvidia_gpu.c create mode 100644 src/nvidia_gpu.h diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c new file mode 100644 index 0000000..75f0915 --- /dev/null +++ b/src/nvidia_gpu.c @@ -0,0 +1,324 @@ +#include <stdio.h> +#include <stdint.h> +#include <nvml.h> +#include <stdlib.h> +#include <string.h> + +#include "util.h" + + +// -----------------------------SENSOR_KIND +typedef enum { + CLOCK_SENSOR = 0, + MEMORY_SENSOR = 1, + UTILIZATION_SENSOR = 2, + + COUNT_SENSOR = 3, +} SENSOR_KIND; + +typedef unsigned int (Initializer) (nvmlDevice_t, void **); +typedef unsigned int (Getter) (nvmlDevice_t, uint64_t *, void *); +typedef void (Cleaner) (void *); + +typedef struct { + void *data; + + Initializer *init; + Getter *get; + Cleaner *clean; +} ISensor; + +// ----------------------------CLOCK_SENSOR +// -- All existing clocks +#if NVML_CLOCK_COUNT != 4 +#error "NVML_CLOCK_COUNT must be equal 4"; +#endif + +// -- SM : Streaming Multiprocessor +static const nvmlClockType_t clocks[NVML_CLOCK_COUNT] = {NVML_CLOCK_GRAPHICS, NVML_CLOCK_SM, NVML_CLOCK_MEM, NVML_CLOCK_VIDEO}; +static const char *clock_names[NVML_CLOCK_COUNT] = {"Graphics", "SM", "Memory", "Video"}; + +// -- Must contain the clocks compatible with the device +typedef struct { + nvmlClockType_t clocks[NVML_CLOCK_COUNT]; + unsigned int count; +} ClockData; + +unsigned int init_clock_sensor(nvmlDevice_t device, void** data) +{ + ClockData tmp = {0}; + nvmlReturn_t result; + unsigned int clock; + + // -- Test all clocks + for (unsigned int i = 0; i < NVML_CLOCK_COUNT; i++) { + if ((result = nvmlDeviceGetClockInfo(device, clocks[i], &clock)) == NVML_SUCCESS) { + tmp.clocks[tmp.count] = clocks[i]; + tmp.count += 1; + } else { + fprintf(stderr, "Failed to get %s clock : %s", clock_names[i], nvmlErrorString(result)); + } + } + + // -- No clock avaible + if (tmp.count == 0) { + return 0; + } + + *data = calloc(1, sizeof(ClockData)); + memcpy(*data, &tmp, sizeof (ClockData)); + return tmp.count; +} + +unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data) +{ + ClockData *clock_data = (ClockData *) data; + nvmlReturn_t err; + unsigned int clock; + + for (unsigned int i = 0; i < clock_data->count; i++) { + nvmlClockType_t clock_type = clock_data->clocks[i]; + + if((err = nvmlDeviceGetClockInfo(device, clock_type, &clock)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get %s clock : %s", clock_names[clock_type], nvmlErrorString(err)); + exit(99); + } + results[i] = clock; + } + return clock_data->count; +} + +void clean_clock_sensor(void* data) +{ + free(data); +} + +// ---------------------------MEMORY_SENSOR +typedef enum { + FREE_MEMORY = 0U, + USED_MEMORY = 1U, + TOTAL_MEMORY = 2U, + + COUNT_MEMORY = 3U, +} MemoryKind; +static const char *memory_names[COUNT_MEMORY] = {"Free", "Used", "Total"}; + +unsigned int init_memory_sensor(nvmlDevice_t device, void **none) +{ + UNUSED(none); + + nvmlMemory_t memory; + nvmlReturn_t result; + if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + return 0; + } + + return COUNT_MEMORY; +} + +unsigned int get_memory_sensor(nvmlDevice_t device, uint64_t *results, void *none) +{ + UNUSED(none); + + nvmlMemory_t memory; + nvmlReturn_t result; + if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + exit(99); + } + + results[FREE_MEMORY] = memory.free; + results[USED_MEMORY] = memory.used; + results[TOTAL_MEMORY] = memory.total; + return COUNT_MEMORY; +} + + +void clean_memory_sensor(void *none) +{ + UNUSED(none); +} + +// ----------------------UTILIZATION_SENSOR +typedef enum { + GPU_UTILIZATION = 0U, + MEMORY_UTILIZATION = 1U, + + COUNT_UTILIZATION = 2U, +} UtilizationKind; + +static const char *utilization_names[COUNT_UTILIZATION] = {"Gpu", "Memory"}; + +unsigned int init_utilization_sensor(nvmlDevice_t device, void **none); +{ + UNUSED(none); + + nvmlReturn_t result; + nvmlUtilization_t utilization; + if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + return 0; + } + + return COUNT_UTILIZATION; +} + +unsigned int get_utilization_sensor(nvmlDevice_t device, uint64_t *results, void* none) +{ + UNUSED(none); + + nvmlReturn_t result; + nvmlUtilization_t utilization; + if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + exit(99); + } + + results[GPU_UTILIZATION] = utilization.gpu; + results[MEMORY_UTILIZATION] = utilization.memory; + return COUNT_UTILIZATION; +} + +void clean_utilization_sensor(void* none) +{ + UNUSED(none); +} + +// ----------------------------ERROR_SENSOR +// TODO + +// ---------------------------------------- + +typedef struct { + char name[NVML_DEVICE_NAME_BUFFER_SIZE]; + nvmlDevice_t device; + + ISensor sensors[COUNT_SENSOR]; + unsigned int count; +} Device; + +typedef struct { + Device *devices; + unsigned int count; +} NvidiaSensor; + +// -------------------------AVAIBLE_SENSORS +static const ISensor avaible_sensors[COUNT_SENSOR] = { + {.init = init_clock_sensor, .get = get_clock_sensor, .clean = clean_memory_sensor, .data = NULL}; + {.init = init_memory_sensor, .get = get_memory_sensor, .clean = clean_memory_sensor, .data = NULL}; + {.init = init_utilization_sensor, .get = get_utilization_sensor, .clean = clean_memory_sensor, .data = NULL}; +}; + +// ------------------------DEVICE_FUNCTIONS + +unsigned int init_device(unsigned int device_idx, Device *device) { + nvmlReturn_t result; + nvmlDevice_t nvml_device; + if ((result = nvmlDeviceGetByIndex(i, &nvml_device) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device handle for device %d: %s\n", device_idx, nvmlErrorString(result)); + return 0; + } + + if ((result = nvmlDeviceGetName(nvml_device, device->name, NVML_DEVICE_NAME_BUFFER_SIZE))) { + fprintf(stderr, "Failed to get device name for device %d: %s\n", device_idx, nvmlErrorString(result)); + return 0; + } + + unsigned int count = 0; + for (unsigned int i = 0; i < COUNT_SENSOR; i++) { + void* data; + if (avaible_sensors.init(nvml_device, &data) != 0) { + ISensor *sensor = &device->sensors[count]; + memcpy(sensor, &avaible_sensors[i], sizeof(ISensor)); + sensor->data = data; + count += 1; + } + } + + device->device = nvml_device; + device->count = count; + return count; +} + +unsigned int get_device(Device *device, uint64_t *results) { + unsigned int count; + nvmlDevice_t nvml_device = device->device; + for (unsigned int i = 0; i < device->count; i++) { + unsigned int result = device->sensor.get(nvml_device, &device->sensor.data, results); + count += result; + results += result; + } + + return count; +} +void clean_device(Device *device) { + for (unsigned int i = 0; i < device->count; i++) { + device->sensor.clean(&device->sensor.data); + } +} + +// ------------------------NVIDIA_INTERFACE + +unsigned int init_nvidia_sensor(char *none, void **ptr) +{ + UNUSED(none); + UNUSED(ptr); + + nvmlReturn_t result; + if ((result = nvmlInit()) != NVML_SUCCESS) { + fprintf(stderr, "Failed to initialize NVML: %s\n", nvmlErrorString(result)); + exit(1); + } + + unsigned int avaible_device_count; + if ((result = nvmlDeviceGetCount(&avaible_device_count)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device count : %s\n", nvmlErrorString(result)); + nvmlShutdown(); + exit(1); + } + + Device* devices = calloc(avaible_device_count, sizeof(Device)); + + unsigned int sensor_count = 0; + unsigned int device_count = 0; + for (unsigned int i = 0; i < avaible_device_count; i++) { + unsigned int initialized_count; + if ((initialized_count = init_device(&devices[device_count])) != 0) { + sensor_count += initialized_count; + device_count += 1; + } + } + + NvidiaSensor *nvidia = (NvidiaSensor*) calloc(1, sizeof(NvidiaSensor)); + nvidia->devices = devices; + nvidia->count = device_count; + + *ptr = (void*) nvidia; + return count; +} + + +unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) { + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + unsigned count = 0; + + for (unsigned int i = 0; i < nvidia.count; i++) { + unsigned int result = get_device(&nvidia->devices[i], results); + results += result; + count += result; + } + + return count; +} +void label_nvidia_sensor(char **labels, void *ptr); + +void clean_nvidia_sensor(void *ptr) +{ + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + + for (unsigned int i = 0; i < nvidia->count; i++) { + clean_device(&nvidia->device[i]); + } + nvmlShutdown(); +} diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h new file mode 100644 index 0000000..e69de29 -- GitLab From 54bba401354dcbfc30804bea721e9a563b50c778 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 6 Mar 2023 15:20:44 +0100 Subject: [PATCH 43/69] working sensor --- src/nvidia_gpu.c | 345 ++++++++++++++++++++++++++++++++++++----------- src/nvidia_gpu.h | 43 ++++++ 2 files changed, 309 insertions(+), 79 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 75f0915..22f65a1 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -1,3 +1,23 @@ +/******************************************************* + 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 <stdint.h> #include <nvml.h> @@ -6,7 +26,6 @@ #include "util.h" - // -----------------------------SENSOR_KIND typedef enum { CLOCK_SENSOR = 0, @@ -16,47 +35,82 @@ typedef enum { COUNT_SENSOR = 3, } SENSOR_KIND; -typedef unsigned int (Initializer) (nvmlDevice_t, void **); -typedef unsigned int (Getter) (nvmlDevice_t, uint64_t *, void *); -typedef void (Cleaner) (void *); +typedef struct Device Device; +typedef struct NvidiaSensor NvidiaSensor; +typedef struct ISensor ISensor; +typedef struct Sensor Sensor; -typedef struct { - void *data; +// -- Sensor interface +typedef unsigned int (Initializer) (const Device *, void **); +typedef unsigned int (Getter) (uint64_t *, const Device *, void *); +typedef unsigned int (Labeller) (char **, void *); +typedef void (Cleaner) (void *); +struct ISensor { Initializer *init; Getter *get; + Labeller *label; Cleaner *clean; -} ISensor; +}; + +// -- Sensor +struct Sensor { + void *data; + const ISensor *fun; +}; + +// -- Device: represents a gpu +struct Device { + char name[NVML_DEVICE_NAME_BUFFER_SIZE]; + nvmlDevice_t device; + unsigned int idx; + + Sensor sensors[COUNT_SENSOR]; + unsigned int count; +}; + +// -- NvidiaSensor: represents the devices +struct NvidiaSensor { + Device *devices; + unsigned int count; +}; + +// -- Label template +static const char *label_template = "gpu%u_%s_%s"; // ----------------------------CLOCK_SENSOR -// -- All existing clocks -#if NVML_CLOCK_COUNT != 4 -#error "NVML_CLOCK_COUNT must be equal 4"; -#endif +#define CLOCK_LABEL_SIZE 25 + +// -- All existing clocks // -- SM : Streaming Multiprocessor static const nvmlClockType_t clocks[NVML_CLOCK_COUNT] = {NVML_CLOCK_GRAPHICS, NVML_CLOCK_SM, NVML_CLOCK_MEM, NVML_CLOCK_VIDEO}; -static const char *clock_names[NVML_CLOCK_COUNT] = {"Graphics", "SM", "Memory", "Video"}; +static const char *clock_names[NVML_CLOCK_COUNT] = {"graphics", "sm", "memory", "video"}; +static const char *clock_base_name = "clk"; // -- Must contain the clocks compatible with the device typedef struct { nvmlClockType_t clocks[NVML_CLOCK_COUNT]; + char labels[NVML_CLOCK_COUNT][CLOCK_LABEL_SIZE]; unsigned int count; } ClockData; -unsigned int init_clock_sensor(nvmlDevice_t device, void** data) +unsigned int init_clock_sensor(const Device *device, void **data) { + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; ClockData tmp = {0}; nvmlReturn_t result; unsigned int clock; // -- Test all clocks for (unsigned int i = 0; i < NVML_CLOCK_COUNT; i++) { - if ((result = nvmlDeviceGetClockInfo(device, clocks[i], &clock)) == NVML_SUCCESS) { + if ((result = nvmlDeviceGetClockInfo(nvml_device, clocks[i], &clock)) == NVML_SUCCESS) { + snprintf(tmp.labels[tmp.count], CLOCK_LABEL_SIZE, label_template, device_idx, clock_base_name, clock_names[i]); tmp.clocks[tmp.count] = clocks[i]; tmp.count += 1; } else { - fprintf(stderr, "Failed to get %s clock : %s", clock_names[i], nvmlErrorString(result)); + fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[i], nvmlErrorString(result)); } } @@ -70,8 +124,9 @@ unsigned int init_clock_sensor(nvmlDevice_t device, void** data) return tmp.count; } -unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data) +unsigned int get_clock_sensor(uint64_t *results, const Device *device, void *data) { + const nvmlDevice_t nvml_device = device->device; ClockData *clock_data = (ClockData *) data; nvmlReturn_t err; unsigned int clock; @@ -79,8 +134,8 @@ unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data for (unsigned int i = 0; i < clock_data->count; i++) { nvmlClockType_t clock_type = clock_data->clocks[i]; - if((err = nvmlDeviceGetClockInfo(device, clock_type, &clock)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get %s clock : %s", clock_names[clock_type], nvmlErrorString(err)); + if((err = nvmlDeviceGetClockInfo(nvml_device, clock_type, &clock)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[clock_type], nvmlErrorString(err)); exit(99); } results[i] = clock; @@ -88,42 +143,69 @@ unsigned int get_clock_sensor(nvmlDevice_t device, uint64_t *results, void* data return clock_data->count; } -void clean_clock_sensor(void* data) +unsigned int label_clock_sensor(char **labels, void *data) +{ + ClockData *clock_data = (ClockData *) data; + + for (unsigned int i = 0; i < clock_data->count; i++) { + labels[i] = clock_data->labels[i]; + } + + return clock_data->count; +} + +void clean_clock_sensor(void *data) { free(data); } // ---------------------------MEMORY_SENSOR +#define MEMORY_LABEL_SIZE 25 + typedef enum { FREE_MEMORY = 0U, USED_MEMORY = 1U, TOTAL_MEMORY = 2U, - + COUNT_MEMORY = 3U, } MemoryKind; -static const char *memory_names[COUNT_MEMORY] = {"Free", "Used", "Total"}; -unsigned int init_memory_sensor(nvmlDevice_t device, void **none) +static const char *memory_names[COUNT_MEMORY] = {"free", "used", "total"}; +static const char *memory_base_name = "mem"; + +typedef struct { + char labels[COUNT_MEMORY][MEMORY_LABEL_SIZE]; +} MemoryData; + +unsigned int init_memory_sensor(const Device *device, void **data) { - UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; nvmlMemory_t memory; nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); return 0; } + MemoryData *memory_data = (MemoryData *) calloc(1, sizeof(MemoryData)); + for (unsigned int i = 0; i < COUNT_MEMORY; i++) { + snprintf(memory_data->labels[i], MEMORY_LABEL_SIZE, label_template, device_idx, memory_base_name, memory_names[i]); + } + + *data = (void *) memory_data; return COUNT_MEMORY; } -unsigned int get_memory_sensor(nvmlDevice_t device, uint64_t *results, void *none) +unsigned int get_memory_sensor(uint64_t *results, const Device *device, void *none) { UNUSED(none); + const nvmlDevice_t nvml_device = device->device; nvmlMemory_t memory; nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(device, &memory)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); exit(99); } @@ -135,12 +217,23 @@ unsigned int get_memory_sensor(nvmlDevice_t device, uint64_t *results, void *non } -void clean_memory_sensor(void *none) +unsigned int label_memory_sensor(char **labels, void* data) { - UNUSED(none); + MemoryData *memory_data = (MemoryData *) data; + + for (unsigned int i = 0; i < COUNT_MEMORY; i++) { + labels[i] = memory_data->labels[i]; + } + + return COUNT_MEMORY; +} +void clean_memory_sensor(void *data) +{ + free(data); } // ----------------------UTILIZATION_SENSOR +#define UTILIZATION_LABEL_SIZE 35 typedef enum { GPU_UTILIZATION = 0U, MEMORY_UTILIZATION = 1U, @@ -148,29 +241,42 @@ typedef enum { COUNT_UTILIZATION = 2U, } UtilizationKind; -static const char *utilization_names[COUNT_UTILIZATION] = {"Gpu", "Memory"}; +typedef struct { + char labels[COUNT_UTILIZATION][UTILIZATION_LABEL_SIZE]; +} UtilizationData; + +static const char *utilization_names[COUNT_UTILIZATION] = {"gpu", "memory"}; +static const char *utilization_base_name = "utilization"; -unsigned int init_utilization_sensor(nvmlDevice_t device, void **none); +unsigned int init_utilization_sensor(const Device *device, void **data) { - UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; nvmlReturn_t result; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); return 0; } + UtilizationData *utilization_data = (UtilizationData *) calloc(1, sizeof(UtilizationData)); + for (unsigned int i = 0; i < COUNT_UTILIZATION; i++) { +snprintf(utilization_data->labels[i], UTILIZATION_LABEL_SIZE, label_template, device_idx, utilization_base_name, utilization_names[i]); + } + + *data = (void *) utilization_data; return COUNT_UTILIZATION; } -unsigned int get_utilization_sensor(nvmlDevice_t device, uint64_t *results, void* none) +unsigned int get_utilization_sensor(uint64_t *results, const Device *device, void *none) { UNUSED(none); + const nvmlDevice_t nvml_device = device->device; nvmlReturn_t result; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(device, &utilization)) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); exit(99); } @@ -180,9 +286,19 @@ unsigned int get_utilization_sensor(nvmlDevice_t device, uint64_t *results, void return COUNT_UTILIZATION; } -void clean_utilization_sensor(void* none) +unsigned int label_utilization_sensor(char **labels, void* data) { - UNUSED(none); + UtilizationData *utilization_data = (UtilizationData *) data; + + for (unsigned int i = 0; i < COUNT_UTILIZATION; i++) { + labels[i] = utilization_data->labels[i]; + } + + return COUNT_UTILIZATION; +} +void clean_utilization_sensor(void *data) +{ + free(data); } // ----------------------------ERROR_SENSOR @@ -190,32 +306,21 @@ void clean_utilization_sensor(void* none) // ---------------------------------------- -typedef struct { - char name[NVML_DEVICE_NAME_BUFFER_SIZE]; - nvmlDevice_t device; - - ISensor sensors[COUNT_SENSOR]; - unsigned int count; -} Device; - -typedef struct { - Device *devices; - unsigned int count; -} NvidiaSensor; // -------------------------AVAIBLE_SENSORS static const ISensor avaible_sensors[COUNT_SENSOR] = { - {.init = init_clock_sensor, .get = get_clock_sensor, .clean = clean_memory_sensor, .data = NULL}; - {.init = init_memory_sensor, .get = get_memory_sensor, .clean = clean_memory_sensor, .data = NULL}; - {.init = init_utilization_sensor, .get = get_utilization_sensor, .clean = clean_memory_sensor, .data = NULL}; + {.init = init_clock_sensor, .get = get_clock_sensor, .label = label_clock_sensor, .clean = clean_clock_sensor}, + {.init = init_memory_sensor, .get = get_memory_sensor, .label = label_memory_sensor, .clean = clean_memory_sensor}, + {.init = init_utilization_sensor, .get = get_utilization_sensor, .label = label_utilization_sensor, .clean = clean_utilization_sensor}, }; // ------------------------DEVICE_FUNCTIONS -unsigned int init_device(unsigned int device_idx, Device *device) { +unsigned int init_device(unsigned int device_idx, Device *device) +{ nvmlReturn_t result; nvmlDevice_t nvml_device; - if ((result = nvmlDeviceGetByIndex(i, &nvml_device) != NVML_SUCCESS) { + if ((result = nvmlDeviceGetHandleByIndex(device_idx, &nvml_device)) != NVML_SUCCESS) { fprintf(stderr, "Failed to get device handle for device %d: %s\n", device_idx, nvmlErrorString(result)); return 0; } @@ -225,39 +330,62 @@ unsigned int init_device(unsigned int device_idx, Device *device) { return 0; } - unsigned int count = 0; + device->device = nvml_device; + device->idx = device_idx; + + unsigned int sensor_count = 0; + unsigned int total_count = 0; + for (unsigned int i = 0; i < COUNT_SENSOR; i++) { - void* data; - if (avaible_sensors.init(nvml_device, &data) != 0) { - ISensor *sensor = &device->sensors[count]; - memcpy(sensor, &avaible_sensors[i], sizeof(ISensor)); - sensor->data = data; - count += 1; + Sensor *sensor = &device->sensors[sensor_count]; + sensor->fun = &avaible_sensors[i]; + unsigned int count; + + if ((count = sensor->fun->init(device, &sensor->data)) != 0) { + sensor_count += 1; + total_count += count; } } - device->device = nvml_device; - device->count = count; - return count; + device->count = sensor_count; + return total_count; } -unsigned int get_device(Device *device, uint64_t *results) { - unsigned int count; - nvmlDevice_t nvml_device = device->device; +unsigned int get_device(uint64_t *results, Device *device) +{ + unsigned int count = 0; for (unsigned int i = 0; i < device->count; i++) { - unsigned int result = device->sensor.get(nvml_device, &device->sensor.data, results); + Sensor *sensor = &device->sensors[i]; + unsigned int result = sensor->fun->get(results, device, sensor->data); count += result; results += result; } return count; } -void clean_device(Device *device) { + +unsigned int label_device(char **labels, Device *device) +{ + unsigned int count = 0; + for (unsigned int i = 0; i < device->count; i++) { + Sensor *sensor = &device->sensors[i]; + unsigned int result = sensor->fun->label(labels, sensor->data); + labels += result; + count += result; + } + + return count; +} + +void clean_device(Device *device) +{ for (unsigned int i = 0; i < device->count; i++) { - device->sensor.clean(&device->sensor.data); + Sensor *sensor = &device->sensors[i]; + sensor->fun->clean(sensor->data); } } + // ------------------------NVIDIA_INTERFACE unsigned int init_nvidia_sensor(char *none, void **ptr) @@ -278,47 +406,106 @@ unsigned int init_nvidia_sensor(char *none, void **ptr) exit(1); } - Device* devices = calloc(avaible_device_count, sizeof(Device)); + Device *devices = calloc(avaible_device_count, sizeof(Device)); unsigned int sensor_count = 0; unsigned int device_count = 0; for (unsigned int i = 0; i < avaible_device_count; i++) { unsigned int initialized_count; - if ((initialized_count = init_device(&devices[device_count])) != 0) { + if ((initialized_count = init_device(i, &devices[device_count])) != 0) { sensor_count += initialized_count; device_count += 1; } } - NvidiaSensor *nvidia = (NvidiaSensor*) calloc(1, sizeof(NvidiaSensor)); + NvidiaSensor *nvidia = (NvidiaSensor *) calloc(1, sizeof(NvidiaSensor)); nvidia->devices = devices; nvidia->count = device_count; - *ptr = (void*) nvidia; - return count; + *ptr = (void *) nvidia; + return sensor_count; } -unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) { +unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) +{ NvidiaSensor *nvidia = (NvidiaSensor *) ptr; unsigned count = 0; - for (unsigned int i = 0; i < nvidia.count; i++) { - unsigned int result = get_device(&nvidia->devices[i], results); + for (unsigned int i = 0; i < nvidia->count; i++) { + unsigned int result = get_device(results, &nvidia->devices[i]); results += result; count += result; } return count; } -void label_nvidia_sensor(char **labels, void *ptr); + +unsigned int label_nvidia_sensor(char **labels, void *ptr) { + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + unsigned count = 0; + + for (unsigned int i = 0; i < nvidia->count; i++) { + unsigned int result = label_device(labels, &nvidia->devices[i]); + labels += result; + count += result; + } + + return count; +} void clean_nvidia_sensor(void *ptr) { NvidiaSensor *nvidia = (NvidiaSensor *) ptr; for (unsigned int i = 0; i < nvidia->count; i++) { - clean_device(&nvidia->device[i]); + clean_device(&nvidia->devices[i]); } + + free(nvidia->devices); + free(nvidia); nvmlShutdown(); } + +// -------------------------------TEST_MAIN + +#ifdef __NVIDIA__MAIN__TEST +int main() +{ + void *ptr = NULL; + char *none = NULL; + + unsigned int sensor_count = init_nvidia_sensor(none, &ptr); + + NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + printf("%d\n", nvidia->count); + printf("%u\n", sensor_count); + + + + uint64_t results[sensor_count]; + char *labels[sensor_count]; + + memset(results, 0, sensor_count * sizeof(uint64_t)); + memset(labels, 0, sensor_count * sizeof(char**)); + + + unsigned count_label = label_nvidia_sensor(labels, ptr); + unsigned count_get = get_nvidia_sensor(results, ptr); + printf("total : %u, get : %u, label : %u\n", sensor_count, count_get, count_label); + + + for (unsigned int i = 0; i < sensor_count; i++) { + printf("%s ", labels[i]); + } + printf("\n"); + for (unsigned int i = 0; i < sensor_count; i++) { + printf("%lu ", results[i]); + } + printf("\n"); + printf("sensor_count: %d\n", sensor_count); + + clean_nvidia_sensor(ptr); +} +#endif + diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index e69de29..6f2419e 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.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_nvidia_sensor(char *, void **); +unsigned int get_nvidia_sensor(uint64_t *results, void *); +void clean_nvidia_sensor(void *); +void label_nvidia_sensor(char **labels, void *); + + +Sensor nvidia_gpu = { + .init = init_nvidia_sensor, + .get = get_nvidia_sensor, + .clean = clean_nvidia_sensor, + .label = label_nvidia_sensor, + .nb_opt = 1, +}; + +Optparse nvidia_gpu_opt[1] = { + { + .longname = "nvidia", + .shortname = 'n', + .argtype = OPTPARSE_NONE, + .usage_arg = NULL, + .usage_msg = "NVIDIA GPU", + }, +}; -- GitLab From 5b6f0ec8b3ac06859e2f5294e1210ddefdb393de Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 6 Mar 2023 15:51:47 +0100 Subject: [PATCH 44/69] pedantic --- src/nvidia_gpu.c | 55 ++++++++++++++++++++++++++---------------------- src/nvidia_gpu.h | 18 ++++++++-------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 22f65a1..479eecb 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -20,10 +20,14 @@ #include <stdio.h> #include <stdint.h> -#include <nvml.h> #include <stdlib.h> #include <string.h> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#include <nvml.h> +#pragma GCC diagnostic pop + #include "util.h" // -----------------------------SENSOR_KIND @@ -36,7 +40,7 @@ typedef enum { } SENSOR_KIND; typedef struct Device Device; -typedef struct NvidiaSensor NvidiaSensor; +typedef struct NvidiaGpu NvidiaGpu; typedef struct ISensor ISensor; typedef struct Sensor Sensor; @@ -69,8 +73,8 @@ struct Device { unsigned int count; }; -// -- NvidiaSensor: represents the devices -struct NvidiaSensor { +// -- NvidiaGpu: represents the devices +struct NvidiaGpu { Device *devices; unsigned int count; }; @@ -217,7 +221,7 @@ unsigned int get_memory_sensor(uint64_t *results, const Device *device, void *no } -unsigned int label_memory_sensor(char **labels, void* data) +unsigned int label_memory_sensor(char **labels, void *data) { MemoryData *memory_data = (MemoryData *) data; @@ -229,7 +233,7 @@ unsigned int label_memory_sensor(char **labels, void* data) } void clean_memory_sensor(void *data) { - free(data); + free(data); } // ----------------------UTILIZATION_SENSOR @@ -242,7 +246,7 @@ typedef enum { } UtilizationKind; typedef struct { - char labels[COUNT_UTILIZATION][UTILIZATION_LABEL_SIZE]; + char labels[COUNT_UTILIZATION][UTILIZATION_LABEL_SIZE]; } UtilizationData; static const char *utilization_names[COUNT_UTILIZATION] = {"gpu", "memory"}; @@ -262,7 +266,7 @@ unsigned int init_utilization_sensor(const Device *device, void **data) UtilizationData *utilization_data = (UtilizationData *) calloc(1, sizeof(UtilizationData)); for (unsigned int i = 0; i < COUNT_UTILIZATION; i++) { -snprintf(utilization_data->labels[i], UTILIZATION_LABEL_SIZE, label_template, device_idx, utilization_base_name, utilization_names[i]); + snprintf(utilization_data->labels[i], UTILIZATION_LABEL_SIZE, label_template, device_idx, utilization_base_name, utilization_names[i]); } *data = (void *) utilization_data; @@ -286,7 +290,7 @@ unsigned int get_utilization_sensor(uint64_t *results, const Device *device, voi return COUNT_UTILIZATION; } -unsigned int label_utilization_sensor(char **labels, void* data) +unsigned int label_utilization_sensor(char **labels, void *data) { UtilizationData *utilization_data = (UtilizationData *) data; @@ -388,7 +392,7 @@ void clean_device(Device *device) // ------------------------NVIDIA_INTERFACE -unsigned int init_nvidia_sensor(char *none, void **ptr) +unsigned int init_nvidia_gpu(char *none, void **ptr) { UNUSED(none); UNUSED(ptr); @@ -418,7 +422,7 @@ unsigned int init_nvidia_sensor(char *none, void **ptr) } } - NvidiaSensor *nvidia = (NvidiaSensor *) calloc(1, sizeof(NvidiaSensor)); + NvidiaGpu *nvidia = (NvidiaGpu *) calloc(1, sizeof(NvidiaGpu)); nvidia->devices = devices; nvidia->count = device_count; @@ -427,9 +431,9 @@ unsigned int init_nvidia_sensor(char *none, void **ptr) } -unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) +unsigned int get_nvidia_gpu(uint64_t *results, void *ptr) { - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; unsigned count = 0; for (unsigned int i = 0; i < nvidia->count; i++) { @@ -441,8 +445,9 @@ unsigned int get_nvidia_sensor(uint64_t *results, void *ptr) return count; } -unsigned int label_nvidia_sensor(char **labels, void *ptr) { - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; +unsigned int label_nvidia_gpu(char **labels, void *ptr) +{ + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; unsigned count = 0; for (unsigned int i = 0; i < nvidia->count; i++) { @@ -454,9 +459,9 @@ unsigned int label_nvidia_sensor(char **labels, void *ptr) { return count; } -void clean_nvidia_sensor(void *ptr) +void clean_nvidia_gpu(void *ptr) { - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; for (unsigned int i = 0; i < nvidia->count; i++) { clean_device(&nvidia->devices[i]); @@ -475,26 +480,26 @@ int main() void *ptr = NULL; char *none = NULL; - unsigned int sensor_count = init_nvidia_sensor(none, &ptr); + unsigned int sensor_count = init_nvidia_gpu(none, &ptr); - NvidiaSensor *nvidia = (NvidiaSensor *) ptr; + NvidiaGpu *nvidia = (NvidiaGpu *) ptr; printf("%d\n", nvidia->count); printf("%u\n", sensor_count); - + uint64_t results[sensor_count]; char *labels[sensor_count]; memset(results, 0, sensor_count * sizeof(uint64_t)); - memset(labels, 0, sensor_count * sizeof(char**)); + memset(labels, 0, sensor_count * sizeof(char **)); - unsigned count_label = label_nvidia_sensor(labels, ptr); - unsigned count_get = get_nvidia_sensor(results, ptr); + unsigned count_label = label_nvidia_gpu(labels, ptr); + unsigned count_get = get_nvidia_gpu(results, ptr); printf("total : %u, get : %u, label : %u\n", sensor_count, count_get, count_label); - + for (unsigned int i = 0; i < sensor_count; i++) { printf("%s ", labels[i]); } @@ -505,7 +510,7 @@ int main() printf("\n"); printf("sensor_count: %d\n", sensor_count); - clean_nvidia_sensor(ptr); + clean_nvidia_gpu(ptr); } #endif diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index 6f2419e..c741055 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -18,23 +18,23 @@ *******************************************************/ -unsigned int init_nvidia_sensor(char *, void **); -unsigned int get_nvidia_sensor(uint64_t *results, void *); -void clean_nvidia_sensor(void *); -void label_nvidia_sensor(char **labels, void *); +unsigned int init_nvidia_gpu(char *, void **); +unsigned int get_nvidia_gpu(uint64_t *results, void *); +void clean_nvidia_gpu(void *); +void label_nvidia_gpu(char **labels, void *); Sensor nvidia_gpu = { - .init = init_nvidia_sensor, - .get = get_nvidia_sensor, - .clean = clean_nvidia_sensor, - .label = label_nvidia_sensor, + .init = init_nvidia_gpu, + .get = get_nvidia_gpu, + .clean = clean_nvidia_gpu, + .label = label_nvidia_gpu, .nb_opt = 1, }; Optparse nvidia_gpu_opt[1] = { { - .longname = "nvidia", + .longname = "nvidia-gpu", .shortname = 'n', .argtype = OPTPARSE_NONE, .usage_arg = NULL, -- GitLab From 5c6076ad0729836751c1a1284357d69a9e26bf46 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 7 Mar 2023 09:04:34 +0100 Subject: [PATCH 45/69] temp change of the make file --- makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index a197961..81a4e41 100644 --- a/makefile +++ b/makefile @@ -17,9 +17,9 @@ OBJ = \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib -I/usr/local/cuda/include CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS = +LDFLAGS = -L/usr/local/cuda/lib64 -lnvidia-ml ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q @@ -27,7 +27,7 @@ ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q all: $(BIN) man $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o - $(CC) $(LDFLAGS) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o + $(CC) -o $(BIN_DIR)/$(BIN) $(OBJ) $(OBJ_DIR)/$(BIN).o $(LDFLAGS) $(OBJ): $(OBJ_DIR) $(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h -- GitLab From 8709019f8d0c1c986ec94ce25792d7942b2ece87 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Tue, 7 Mar 2023 11:36:46 +0100 Subject: [PATCH 46/69] compare new dev name to all saved ones --- src/network.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/network.c b/src/network.c index 33fdadf..cea2a89 100644 --- a/src/network.c +++ b/src/network.c @@ -64,6 +64,10 @@ static void _get_network(uint64_t *results, int *sources) } } +/* + * read from fd len chars and store them into buf + * make *s points to the first occurence of c into buf +*/ static int strchr_refill(int fd, char *buf, int len, char **s, char c) { *s = strchr(*s, c); @@ -152,7 +156,13 @@ unsigned int init_network(char *dev, void **ptr) } /* compare dev name to the previously saved one */ - if (strncmp(start_of_dev, state->devs[state->ndev - 1], s - start_of_dev) != 0) { + int newdev = 1; + for (int i = 0; i < state->ndev && newdev; i++) { + if (strncmp(start_of_dev, state->devs[i], s - start_of_dev) == 0) { + newdev = 0; + } + } + if (newdev) { if (state->ndev >= NB_MAX_DEV) { fprintf(stderr, "Maximum amount of network devices exceeded (%d).\n", NB_MAX_DEV); break; -- GitLab From 38fe56fc0d5de9d32dd906fc261eef2521f62d82 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 7 Mar 2023 12:56:44 +0100 Subject: [PATCH 47/69] debug help --- src/nvidia_gpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 479eecb..0be83ce 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -18,6 +18,8 @@ *******************************************************/ +// -- test : +// gcc -std=gnu99 -Wall -Wextra -Wpedantic -fsanitize=address -D__NVIDIA__MAIN__TEST nvidia_gpu.c -I/lib -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lnvidia-ml #include <stdio.h> #include <stdint.h> #include <stdlib.h> @@ -300,6 +302,7 @@ unsigned int label_utilization_sensor(char **labels, void *data) return COUNT_UTILIZATION; } + void clean_utilization_sensor(void *data) { free(data); -- GitLab From 2622d3c0087d88ec10da2fd87dae8d8fd4624578 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 08:28:36 +0100 Subject: [PATCH 48/69] fix print uint64_t format --- src/amd_rapl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 1e08517..253711f 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -120,7 +120,7 @@ uint64_t read_msr(int fd, uint64_t msr) { uint64_t data; if (pread(fd, &data, sizeof data, msr) != sizeof data) { - fprintf(stderr, "read_msr(%ld):", msr); + fprintf(stderr, "read_msr(%"PRIu64"):", msr); perror("pread"); exit(127); } @@ -175,7 +175,7 @@ uint64_t raw_to_joule(uint64_t raw, uint64_t unit) void debug_print_sensor(CpuSensor *sensor) { //CASSERT(sizeof(CpuSensor) == 56, amd_rapl_c); - printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %ld\n", + printf("cpu_id : %d, package_id : %d, core_id : %d, name : %s, fd: %d, energy_units : %d, core_energy: %"PRIu64"\n", sensor->cpu_id, sensor->package_id, sensor->core_id, -- GitLab From 73936d2860b2b91689380450f438b07f2123b04b Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 09:27:42 +0100 Subject: [PATCH 49/69] add msg --- src/nvidia_gpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index c741055..681a028 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -38,6 +38,6 @@ Optparse nvidia_gpu_opt[1] = { .shortname = 'n', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "NVIDIA GPU", + .usage_msg = "provides basic gpu information", }, }; -- GitLab From d19aa35ecc91d47c143fd503abf5ff776eceaf48 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 09:37:45 +0100 Subject: [PATCH 50/69] fix include --- src/amd_rapl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index 253711f..f08c5a7 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -25,6 +25,7 @@ #include <string.h> #include <errno.h> #include <stdlib.h> +#include <inttypes.h> #include "info_reader.h" #include "util.h" -- GitLab From bfb4c16b6334e029f1871396a200615d248004b4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 10:02:36 +0100 Subject: [PATCH 51/69] add the detection of nvidia --- configure.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.sh b/configure.sh index 21c94ef..24a379d 100755 --- a/configure.sh +++ b/configure.sh @@ -115,6 +115,10 @@ detect_caps() { [ -e "/sys/class/net/$dev" ] && hdr_whitelist="${hdr_whitelist}|network" fi + if [ -e /usr/local/cuda/lib64 ] && [ -e /usr/local/cuda/include ]; then + hdr_whitelist="${hdr_whitelist}|nvidia_gpu" + fi + vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) vendor_lc=$(echo "$vendor" | tr 'A-Z' 'a-z') case $vendor_lc in -- GitLab From 1a5443e32e004050a96ad27dddfd0bfcef66d05e Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 13:11:27 +0100 Subject: [PATCH 52/69] temperature/power --- src/nvidia_gpu.c | 155 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 18 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 0be83ce..5f4a460 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -37,8 +37,10 @@ typedef enum { CLOCK_SENSOR = 0, MEMORY_SENSOR = 1, UTILIZATION_SENSOR = 2, + POWER_SENSOR = 3, + TEMPERATURE_SENSOR = 4, - COUNT_SENSOR = 3, + COUNT_SENSOR = 5, } SENSOR_KIND; typedef struct Device Device; @@ -83,6 +85,7 @@ struct NvidiaGpu { // -- Label template static const char *label_template = "gpu%u_%s_%s"; +static const char *short_label_template = "gpu%u_%s"; // ----------------------------CLOCK_SENSOR @@ -106,17 +109,17 @@ unsigned int init_clock_sensor(const Device *device, void **data) const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; ClockData tmp = {0}; - nvmlReturn_t result; + nvmlReturn_t err; unsigned int clock; // -- Test all clocks for (unsigned int i = 0; i < NVML_CLOCK_COUNT; i++) { - if ((result = nvmlDeviceGetClockInfo(nvml_device, clocks[i], &clock)) == NVML_SUCCESS) { + if ((err = nvmlDeviceGetClockInfo(nvml_device, clocks[i], &clock)) == NVML_SUCCESS) { snprintf(tmp.labels[tmp.count], CLOCK_LABEL_SIZE, label_template, device_idx, clock_base_name, clock_names[i]); tmp.clocks[tmp.count] = clocks[i]; tmp.count += 1; } else { - fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[i], nvmlErrorString(result)); + fprintf(stderr, "Failed to get %s clock : %s\n", clock_names[i], nvmlErrorString(err)); } } @@ -189,9 +192,9 @@ unsigned int init_memory_sensor(const Device *device, void **data) const unsigned int device_idx = device->idx; nvmlMemory_t memory; - nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + nvmlReturn_t err; + if ((err = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(err)); return 0; } @@ -210,9 +213,9 @@ unsigned int get_memory_sensor(uint64_t *results, const Device *device, void *no const nvmlDevice_t nvml_device = device->device; nvmlMemory_t memory; - nvmlReturn_t result; - if ((result = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(result)); + nvmlReturn_t err; + if ((err = nvmlDeviceGetMemoryInfo(nvml_device, &memory)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device memory : %s\n", nvmlErrorString(err)); exit(99); } @@ -259,10 +262,10 @@ unsigned int init_utilization_sensor(const Device *device, void **data) const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; - nvmlReturn_t result; + nvmlReturn_t err; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + if ((err = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(err)); return 0; } @@ -280,10 +283,10 @@ unsigned int get_utilization_sensor(uint64_t *results, const Device *device, voi UNUSED(none); const nvmlDevice_t nvml_device = device->device; - nvmlReturn_t result; + nvmlReturn_t err; nvmlUtilization_t utilization; - if ((result = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { - fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(result)); + if ((err = nvmlDeviceGetUtilizationRates(nvml_device, &utilization)) != NVML_SUCCESS) { + fprintf(stderr, "Failed to get device utilization: %s\n", nvmlErrorString(err)); exit(99); } @@ -308,8 +311,122 @@ void clean_utilization_sensor(void *data) free(data); } -// ----------------------------ERROR_SENSOR -// TODO +// ----------------------------POWER_SENSOR + +#define POWER_LABEL_SIZE 25 +#define COUNT_POWER 1 + +static const char *power_base_name = "power"; + +typedef struct { + char label[POWER_LABEL_SIZE]; +} PowerData; + + +unsigned int init_power_sensor(const Device *device, void** data) { + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; + + unsigned int power; + nvmlReturn_t err; + if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + return 0; + } + + PowerData *power_data = (PowerData *) calloc(1, sizeof(PowerData)); + snprintf(power_data->label, POWER_LABEL_SIZE, short_label_template, device_idx, power_base_name); + + *data = (void *) power_data; + return COUNT_POWER; +} + +unsigned int get_power_sensor(uint64_t *results, const Device *device, void *none) { + UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + + unsigned int power; + nvmlReturn_t err; + if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + exit(99); + } + + *results = power; + return COUNT_POWER; +} + +unsigned int label_power_sensor(char** labels, void *data) { + PowerData *power_data = (PowerData *) data; + *labels = power_data->label; + return COUNT_POWER; +} + +void clean_power_sensor(void *data) { + free(data); +} + +// ----------------------TEMPERATURE_SENSOR + + +#define TEMPERATURE_LABEL_SIZE 35 +#define COUNT_TEMPERATURE 1 + +static const char *temperature_base_name = "temperature"; + +typedef struct { + char label[TEMPERATURE_LABEL_SIZE]; +} TemperatureData; + +unsigned int init_temperature_sensor(const Device *device, void** data) { + const nvmlDevice_t nvml_device = device->device; + const unsigned int device_idx = device->idx; + + unsigned int temperature; + nvmlReturn_t err; + if ((err = nvmlDeviceGetTemperature(nvml_device, NVML_TEMPERATURE_GPU, &temperature)) != NVML_SUCCESS) { + printf("Failed to get the device temperature: %s\n", nvmlErrorString(err)); + return 0; + } + + TemperatureData *temperature_data = (TemperatureData *) calloc(1, sizeof(TemperatureData)); + snprintf(temperature_data->label, TEMPERATURE_LABEL_SIZE, short_label_template, device_idx, temperature_base_name); + + *data = (void *) temperature_data; + return COUNT_TEMPERATURE; +} + +unsigned int get_temperature_sensor(uint64_t *results, const Device *device, void *none) { + UNUSED(none); + const nvmlDevice_t nvml_device = device->device; + + unsigned int temperature; + nvmlReturn_t err; + if ((err = nvmlDeviceGetTemperature(nvml_device, NVML_TEMPERATURE_GPU, &temperature)) != NVML_SUCCESS) { + printf("Failed to get the device temperature: %s\n", nvmlErrorString(err)); + exit(99); + } + + *results = temperature; + return COUNT_TEMPERATURE; +} + +unsigned int label_temperature_sensor(char** labels, void *data) { + TemperatureData *temperature_data = (TemperatureData *) data; + *labels = temperature_data->label; + return COUNT_TEMPERATURE; +} + +void clean_temperature_sensor(void *data) { + free(data); +} +// // Get the temperature +// result = nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temperature); +// if (NVML_SUCCESS != result) { +// printf("Failed to get temperature for device %d: %s\n", i, nvmlErrorString(result)); +// continue; +// } +// printf("\t - temperature: %u\n", temperature); // ---------------------------------------- @@ -319,6 +436,8 @@ static const ISensor avaible_sensors[COUNT_SENSOR] = { {.init = init_clock_sensor, .get = get_clock_sensor, .label = label_clock_sensor, .clean = clean_clock_sensor}, {.init = init_memory_sensor, .get = get_memory_sensor, .label = label_memory_sensor, .clean = clean_memory_sensor}, {.init = init_utilization_sensor, .get = get_utilization_sensor, .label = label_utilization_sensor, .clean = clean_utilization_sensor}, + {.init = init_power_sensor, .get = get_power_sensor, .label = label_power_sensor, .clean = clean_power_sensor}, + {.init = init_temperature_sensor, .get = get_temperature_sensor, .label = label_temperature_sensor, .clean = clean_temperature_sensor}, }; // ------------------------DEVICE_FUNCTIONS -- GitLab From 73e90167bb968cee8a90b903c829fed3da0bf812 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 13:11:56 +0100 Subject: [PATCH 53/69] doc nvidia --- doc/nvidia-gpu.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 doc/nvidia-gpu.md diff --git a/doc/nvidia-gpu.md b/doc/nvidia-gpu.md new file mode 100644 index 0000000..8c54afd --- /dev/null +++ b/doc/nvidia-gpu.md @@ -0,0 +1,58 @@ +# Nvidia Gpu + +The `nvidia-gpu` sensor provides basic information about the gpu. Depending on +the driver version it is possible that not all sensors are supported, so an +error message will be written to `stderr` but the execution will continue. + +For more information you can consult the [nvidia nvml api](https://docs.nvidia.com/deploy/index.html). + +## [Clock](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g805c0647be9996589fc5e3f6ff680c64) + +All speeds are in Mhz. + +|Output |Description | +|--------|-------------------------------| +|graphics|Graphics clock | +|sm |Streaming Multiprocessor clock | +|memory |Memory clock | +|video |Video encoder/decoder clock | + +## [Memory](https://docs.nvidia.com/deploy/nvml-api/structnvmlMemory__t.html#structnvmlMemory__t) + +All values are in bytes. + +|Output |Description | +|--------|-------------------------------------| +|free |Unallocated device memory | +|used |Sum of Reserved and Allocated memory | +|total |Total physical device memory | + + +## [Utilization](https://docs.nvidia.com/deploy/nvml-api/structnvmlUtilization__t.html#structnvmlUtilization__t) + +Utilization information for a device. Each sample period may be between 1 +second and 1/6 second, depending on the product being queried. + +All values are a percent of time over the past sample period. + +|Output |Description | +|--------|---------------------| +|gpu | Usage of the GPU | +|memory | Usage of the Memory | + +## [Power](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceQueries.html#group__nvmlDeviceQueries_1g7ef7dff0ff14238d08a19ad7fb23fc87) + +Retrieves power usage for this GPU in milliwatts and its associated circuitry (e.g. memory) + +|Output |Description | +|--------|-------------------------| +|power | Power consumption in mW | + +## [Temperature](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g2650b526841fa38b8f293c2d509a1de0) + +Temperature of the GPU. + +|Output |Description | +|------------|----------------------------| +|temperature | Temperature of the GPU die | + -- GitLab From 7a99793661194c32f5b366aca7f9e2289dc7dde7 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 13:18:49 +0100 Subject: [PATCH 54/69] fix line --- doc/nvidia-gpu.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/nvidia-gpu.md b/doc/nvidia-gpu.md index 8c54afd..5a5cebc 100644 --- a/doc/nvidia-gpu.md +++ b/doc/nvidia-gpu.md @@ -49,7 +49,6 @@ Retrieves power usage for this GPU in milliwatts and its associated circuitry (e |power | Power consumption in mW | ## [Temperature](https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g2650b526841fa38b8f293c2d509a1de0) - Temperature of the GPU. |Output |Description | -- GitLab From 8e1a6b567cd3270e38f74a8290112b71da6c9feb Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 14:08:11 +0100 Subject: [PATCH 55/69] fix name --- doc/{nvidia-gpu.md => nvidia_gpu.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename doc/{nvidia-gpu.md => nvidia_gpu.md} (97%) diff --git a/doc/nvidia-gpu.md b/doc/nvidia_gpu.md similarity index 97% rename from doc/nvidia-gpu.md rename to doc/nvidia_gpu.md index 5a5cebc..15cc8aa 100644 --- a/doc/nvidia-gpu.md +++ b/doc/nvidia_gpu.md @@ -1,6 +1,6 @@ # Nvidia Gpu -The `nvidia-gpu` sensor provides basic information about the gpu. Depending on +The `nvidia_gpu` sensor provides basic information about the gpu. Depending on the driver version it is possible that not all sensors are supported, so an error message will be written to `stderr` but the execution will continue. -- GitLab From 22721bfe5886ec3159ca34091e593a172511ce05 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 13 Mar 2023 14:09:41 +0100 Subject: [PATCH 56/69] format --- src/nvidia_gpu.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 5f4a460..17d77f5 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -319,19 +319,20 @@ void clean_utilization_sensor(void *data) static const char *power_base_name = "power"; typedef struct { - char label[POWER_LABEL_SIZE]; + char label[POWER_LABEL_SIZE]; } PowerData; -unsigned int init_power_sensor(const Device *device, void** data) { +unsigned int init_power_sensor(const Device *device, void **data) +{ const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; unsigned int power; nvmlReturn_t err; if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { - printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); - return 0; + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + return 0; } PowerData *power_data = (PowerData *) calloc(1, sizeof(PowerData)); @@ -341,28 +342,31 @@ unsigned int init_power_sensor(const Device *device, void** data) { return COUNT_POWER; } -unsigned int get_power_sensor(uint64_t *results, const Device *device, void *none) { +unsigned int get_power_sensor(uint64_t *results, const Device *device, void *none) +{ UNUSED(none); const nvmlDevice_t nvml_device = device->device; unsigned int power; nvmlReturn_t err; if ((err = nvmlDeviceGetPowerUsage(nvml_device, &power)) != NVML_SUCCESS) { - printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); - exit(99); + printf("Failed to get the device power consumption: %s\n", nvmlErrorString(err)); + exit(99); } *results = power; return COUNT_POWER; } -unsigned int label_power_sensor(char** labels, void *data) { +unsigned int label_power_sensor(char **labels, void *data) +{ PowerData *power_data = (PowerData *) data; *labels = power_data->label; return COUNT_POWER; } -void clean_power_sensor(void *data) { +void clean_power_sensor(void *data) +{ free(data); } @@ -375,10 +379,11 @@ void clean_power_sensor(void *data) { static const char *temperature_base_name = "temperature"; typedef struct { - char label[TEMPERATURE_LABEL_SIZE]; + char label[TEMPERATURE_LABEL_SIZE]; } TemperatureData; -unsigned int init_temperature_sensor(const Device *device, void** data) { +unsigned int init_temperature_sensor(const Device *device, void **data) +{ const nvmlDevice_t nvml_device = device->device; const unsigned int device_idx = device->idx; @@ -396,7 +401,8 @@ unsigned int init_temperature_sensor(const Device *device, void** data) { return COUNT_TEMPERATURE; } -unsigned int get_temperature_sensor(uint64_t *results, const Device *device, void *none) { +unsigned int get_temperature_sensor(uint64_t *results, const Device *device, void *none) +{ UNUSED(none); const nvmlDevice_t nvml_device = device->device; @@ -411,13 +417,15 @@ unsigned int get_temperature_sensor(uint64_t *results, const Device *device, voi return COUNT_TEMPERATURE; } -unsigned int label_temperature_sensor(char** labels, void *data) { +unsigned int label_temperature_sensor(char **labels, void *data) +{ TemperatureData *temperature_data = (TemperatureData *) data; *labels = temperature_data->label; return COUNT_TEMPERATURE; } -void clean_temperature_sensor(void *data) { +void clean_temperature_sensor(void *data) +{ free(data); } // // Get the temperature -- GitLab From 6ac893561fca6e5b433a3b9ab779a61c11b13744 Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Mar 2023 14:17:48 +0100 Subject: [PATCH 57/69] add doc to "network" sensor explaining #interfaces hard-limit in use --- doc/network.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/network.md diff --git a/doc/network.md b/doc/network.md new file mode 100644 index 0000000..b5d1e68 --- /dev/null +++ b/doc/network.md @@ -0,0 +1,8 @@ +This sensor can autodetect interfaces in use by giving the special +interface name "X". But the total number of interfaces it can autodetect +is currently under a hard-limit. This hard-limit can be changed by +modifying this line in `src/network.c`: + +```c +#define NB_MAX_DEV 8 +``` -- GitLab From 1e6746bee0c8e7f867c778f50369e3a17d3f5ddb Mon Sep 17 00:00:00 2001 From: ghuter <ghuter@disroot.org> Date: Mon, 13 Mar 2023 15:36:34 +0100 Subject: [PATCH 58/69] configure.sh: avoid cd(1) and ls(1) in ls_sensors() --- configure.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.sh b/configure.sh index 747a078..203fd04 100755 --- a/configure.sh +++ b/configure.sh @@ -43,16 +43,16 @@ usage() { } ls_sensors() { - try cd src + [ -d src ] || die 'fatal: the "src" directory does not exit.' [ -z "$hdr_whitelist" ] && hdr_whitelist='.*' dprint hdr_blacklist >&2 dprint hdr_whitelist >&2 - ls -1 *.h | - grep -xEv "($hdr_blacklist)\.h" | - grep -xE "($hdr_whitelist)\.h" | - sed 's/\.h$//' + try find src -type f -name '*.h' | + sed 's,src/\(.*\)\.h,\1,' | + grep -xEv "($hdr_blacklist)" | + grep -xE "($hdr_whitelist)" } # gen_sensors_h(sensor, nb_sensors) -- GitLab From 856c5a6e577428882179c3dceba4aeaf1bb7192d Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 08:56:20 +0100 Subject: [PATCH 59/69] auto config nvidia --- configure.sh | 79 +++++++++++++++++++++++++++++----------------------- makefile | 6 ++-- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/configure.sh b/configure.sh index 24a379d..207cf07 100755 --- a/configure.sh +++ b/configure.sh @@ -4,12 +4,15 @@ # Copyright (C) 2023-2023 Georges Da Costa <georges.da-costa@irit.fr> try() { "$@" || die "cannot $*"; } -die() { yell "$*"; exit 111; } +die() { + yell "$*" + exit 111 +} yell() { echo "$0: $*" >&2; } echo() { printf '%s\n' "$*"; } isnum() { case "${1#[+-]}" in - *[!0-9]*|'') return 1 ;; + *[!0-9]* | '') return 1 ;; *) return 0 ;; esac } @@ -51,7 +54,7 @@ ls_sensors() { ls -1 *.h | grep -xEv "($hdr_blacklist)\.h" | - grep -xE "($hdr_whitelist)\.h" | + grep -xE "($hdr_whitelist)\.h" | sed 's/\.h$//' } @@ -86,10 +89,10 @@ gen_sensors_h() { printf ' int opt_idx = offset;\n' for sensor in $sensors; do cat <<-! - for (int i = 0; i < ${sensor}.nb_opt; i++) { - opts[opt_idx++] = ${sensor}_opt[i]; - } - sensors[(*nb_defined)++] = ${sensor}; + for (int i = 0; i < ${sensor}.nb_opt; i++) { + opts[opt_idx++] = ${sensor}_opt[i]; + } + sensors[(*nb_defined)++] = ${sensor}; ! done printf ' assert((offset + *nb_defined) <= len);\n' @@ -117,6 +120,8 @@ detect_caps() { if [ -e /usr/local/cuda/lib64 ] && [ -e /usr/local/cuda/include ]; then hdr_whitelist="${hdr_whitelist}|nvidia_gpu" + NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml" + NVML_IFLAGS="-I/usr/local/cuda/include" fi vendor=$(awk '/vendor_id/ {print $3; exit}' /proc/cpuinfo) @@ -140,7 +145,7 @@ detect_caps() { } case $1 in ---all|-a) +--all | -a) all=1 ;; esac @@ -148,30 +153,33 @@ esac [ "$all" ] || detect_caps [ "$all" ] || -while [ "$1" ]; do - case $1 in - --include|-i) - shift; [ "$1" ] || usage - hdr_whitelist="${hdr_whitelist}|${1}" - ;; - --exclude|-e) - shift; [ "$1" ] || usage - hdr_blacklist="${hdr_blacklist}|${1}" - ;; - --list-sensors|-l) - ls_sensors - exit 0 - ;; - --unique|-u) - shift; [ "$1" ] || usage - hdr_whitelist=$1 - ;; - --help|-h) - usage - ;; - esac - shift -done + while [ "$1" ]; do + case $1 in + --include | -i) + shift + [ "$1" ] || usage + hdr_whitelist="${hdr_whitelist}|${1}" + ;; + --exclude | -e) + shift + [ "$1" ] || usage + hdr_blacklist="${hdr_blacklist}|${1}" + ;; + --list-sensors | -l) + ls_sensors + exit 0 + ;; + --unique | -u) + shift + [ "$1" ] || usage + hdr_whitelist=$1 + ;; + --help | -h) + usage + ;; + esac + shift + done sensors=$(ls_sensors) nb_sensors=$(echo "$sensors" | sed '/^$/d' | wc -l) @@ -181,12 +189,13 @@ if [ "$nb_sensors" -eq 0 ]; then exit 1 fi -try gen_sensors_h "$sensors" "$nb_sensors" > "$target_hdr" -try gen_sensors_mk "$sensors" > "$target_mk" +try gen_sensors_h "$sensors" "$nb_sensors" >"$target_hdr" +try gen_sensors_mk "$sensors" >"$target_mk" +try printf "LDFLAGS += %s\n" "$NVML_LDFLAGS" >>"$target_mk" +try printf "IFLAGS += %s\n" "$NVML_IFLAGS" >>"$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 printf -- 'The resulting binary will have the %d following sensors:\n' "$nb_sensors" >&2 echo "$sensors" >&2 make clean >/dev/null - diff --git a/makefile b/makefile index 81a4e41..1b636c4 100644 --- a/makefile +++ b/makefile @@ -9,6 +9,8 @@ TESTS_DIR = tests BIN = mojitos CAPTOR_OBJ = +IFLAGS = +LDFLAGS = include ./sensors.mk @@ -17,9 +19,9 @@ OBJ = \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib -I/usr/local/cuda/include +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(IFLAGS) CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS = -L/usr/local/cuda/lib64 -lnvidia-ml +LDFLAGS += ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -- GitLab From ddbe21e68e58bc5923b17d59d64d08ae9fc45cee Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 09:19:06 +0100 Subject: [PATCH 60/69] fix: Readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c6d591..9fee622 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,15 @@ make ``` You may want to run `./configure.sh --help` to see configuration options. +To use `amd_rapl` you have to load the module `msr` +```bash +sudo modprobe msr +``` To execute mojitos without being root to monitor performance counters ```bash sudo sh -c 'echo 0 >/proc/sys/kernel/perf_event_paranoid' ``` -To execute mohitos without being root for accessing RAPL +To execute mojitos without being root for accessing RAPL ```bash sudo chmod a+w /sys/class/powercap/intel-rapl/*/* sudo chmod a+w /sys/class/powercap/intel-rapl/*/*/* -- GitLab From bd68a69a55783fe7985910fe0e3e359de7102e3c Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 11:36:10 +0100 Subject: [PATCH 61/69] auto configure nvml --- configure.sh | 5 +++-- makefile | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/configure.sh b/configure.sh index 207cf07..ebf6881 100755 --- a/configure.sh +++ b/configure.sh @@ -191,8 +191,9 @@ fi try gen_sensors_h "$sensors" "$nb_sensors" >"$target_hdr" try gen_sensors_mk "$sensors" >"$target_mk" -try printf "LDFLAGS += %s\n" "$NVML_LDFLAGS" >>"$target_mk" -try printf "IFLAGS += %s\n" "$NVML_IFLAGS" >>"$target_mk" + +try printf "NVML_LDFLAGS = %s\n" "$NVML_LDFLAGS" >>"$target_mk" +try printf "NVML_IFLAGS = %s\n" "$NVML_IFLAGS" >>"$target_mk" printf -- 'Run `make` to build `bin/mojitos`.\n' >&2 printf -- 'The resulting binary will have the %d following sensors:\n' "$nb_sensors" >&2 diff --git a/makefile b/makefile index 1b636c4..8a3c129 100644 --- a/makefile +++ b/makefile @@ -9,8 +9,8 @@ TESTS_DIR = tests BIN = mojitos CAPTOR_OBJ = -IFLAGS = -LDFLAGS = +NVML_LDFLAGS = +NVML_IFLAGS = include ./sensors.mk @@ -19,9 +19,9 @@ OBJ = \ $(OBJ_DIR)/util.o CC = gcc -CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(IFLAGS) +CPPFLAGS = -std=gnu99 -Wall -Wextra -Wpedantic -Wno-unused-function -I./lib $(NVML_IFLAGS) CFLAGS = $(CPPFLAGS) -O3 -Werror -LDFLAGS += +LDFLAGS = $(NVML_LDFLAGS) ASTYLE = astyle --style=kr -xf -s4 -k3 -n -Z -Q -- GitLab From a7ae9dc8fc367af447a1a76c1ba72630e893e2b4 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 12:00:11 +0100 Subject: [PATCH 62/69] clean up --- src/nvidia_gpu.c | 55 +----------------------------------------------- 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/src/nvidia_gpu.c b/src/nvidia_gpu.c index 17d77f5..4078002 100644 --- a/src/nvidia_gpu.c +++ b/src/nvidia_gpu.c @@ -18,13 +18,12 @@ *******************************************************/ -// -- test : -// gcc -std=gnu99 -Wall -Wextra -Wpedantic -fsanitize=address -D__NVIDIA__MAIN__TEST nvidia_gpu.c -I/lib -I/usr/local/cuda/include -L/usr/local/cuda/lib64 -lnvidia-ml #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +// Pedantic throws a warning in the nvml library #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #include <nvml.h> @@ -428,16 +427,6 @@ void clean_temperature_sensor(void *data) { free(data); } -// // Get the temperature -// result = nvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &temperature); -// if (NVML_SUCCESS != result) { -// printf("Failed to get temperature for device %d: %s\n", i, nvmlErrorString(result)); -// continue; -// } -// printf("\t - temperature: %u\n", temperature); - -// ---------------------------------------- - // -------------------------AVAIBLE_SENSORS static const ISensor avaible_sensors[COUNT_SENSOR] = { @@ -602,45 +591,3 @@ void clean_nvidia_gpu(void *ptr) nvmlShutdown(); } -// -------------------------------TEST_MAIN - -#ifdef __NVIDIA__MAIN__TEST -int main() -{ - void *ptr = NULL; - char *none = NULL; - - unsigned int sensor_count = init_nvidia_gpu(none, &ptr); - - NvidiaGpu *nvidia = (NvidiaGpu *) ptr; - printf("%d\n", nvidia->count); - printf("%u\n", sensor_count); - - - - uint64_t results[sensor_count]; - char *labels[sensor_count]; - - memset(results, 0, sensor_count * sizeof(uint64_t)); - memset(labels, 0, sensor_count * sizeof(char **)); - - - unsigned count_label = label_nvidia_gpu(labels, ptr); - unsigned count_get = get_nvidia_gpu(results, ptr); - printf("total : %u, get : %u, label : %u\n", sensor_count, count_get, count_label); - - - for (unsigned int i = 0; i < sensor_count; i++) { - printf("%s ", labels[i]); - } - printf("\n"); - for (unsigned int i = 0; i < sensor_count; i++) { - printf("%lu ", results[i]); - } - printf("\n"); - printf("sensor_count: %d\n", sensor_count); - - clean_nvidia_gpu(ptr); -} -#endif - -- GitLab From 82224cf547220db437b09b720285141c575c2982 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Mon, 20 Mar 2023 12:08:10 +0100 Subject: [PATCH 63/69] fix: usage msg --- src/nvidia_gpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvidia_gpu.h b/src/nvidia_gpu.h index 681a028..1f3d053 100644 --- a/src/nvidia_gpu.h +++ b/src/nvidia_gpu.h @@ -38,6 +38,6 @@ Optparse nvidia_gpu_opt[1] = { .shortname = 'n', .argtype = OPTPARSE_NONE, .usage_arg = NULL, - .usage_msg = "provides basic gpu information", + .usage_msg = "provides basic gpu information [clocks, memory, utilization, power, temperature].", }, }; -- GitLab From 80686673103879c1eb6b197c45493b521c7702a9 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 10:41:57 +0100 Subject: [PATCH 64/69] add memory sensor --- configure.sh | 6 +++- src/memory.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/memory.h | 43 +++++++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/memory.c create mode 100644 src/memory.h diff --git a/configure.sh b/configure.sh index 740e87a..7e10ec3 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/memory.c b/src/memory.c new file mode 100644 index 0000000..3356a82 --- /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 0000000..6e275c6 --- /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)'.", + }, +}; -- GitLab From 482202be2c2811baf0f5f4fff1c5056f9b2b3e04 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 11:21:58 +0100 Subject: [PATCH 65/69] non breaking change, ptr -> const ptr --- tests/small_test.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/small_test.h b/tests/small_test.h index 66c4de9..8301ae7 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); -- GitLab From 32ff911bf1e940750eadf0e5080f374aa45921ef Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 11:23:21 +0100 Subject: [PATCH 66/69] add tests --- tests/main.c | 2 ++ tests/memory.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/memory.c diff --git a/tests/main.c b/tests/main.c index 3246f04..e90e8dd 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 0000000..78efd28 --- /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); +}) + -- GitLab From 4ffdcfaf2192b0929cd7d0902bcb5a2cc34510fe Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 11:39:45 +0100 Subject: [PATCH 67/69] add tests --- tests/util.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/util.c b/tests/util.c index 69941bf..231ab47 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); }) -- GitLab From bdb2908f2cecc768711d92eede0d41e5d856c404 Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 12:46:42 +0100 Subject: [PATCH 68/69] add: exit information --- src/amd_rapl.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index f08c5a7..adc4461 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 %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"); + 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)) { -- GitLab From f3368b52b60d7b46a39411a0e8f69e378a285f0a Mon Sep 17 00:00:00 2001 From: FlorealRISSO <floreal.risso@univ-tlse3.fr> Date: Tue, 21 Mar 2023 12:52:02 +0100 Subject: [PATCH 69/69] error handling --- src/amd_rapl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/amd_rapl.c b/src/amd_rapl.c index adc4461..9eaac45 100644 --- a/src/amd_rapl.c +++ b/src/amd_rapl.c @@ -217,7 +217,7 @@ unsigned int get_nb_cpu() if (n_cpu == 0) { perror("open()"); - fprintf(stderr, "on %s\n", filename); + 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"); @@ -226,7 +226,7 @@ unsigned int get_nb_cpu() fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n"); exit(98); default: - fprintf(stderr, "Unexpected error"); + fprintf(stderr, "Unexpected error\n"); exit(97); } } -- GitLab