Skip to content
Snippets Groups Projects
Commit 4d546b74 authored by Georges Da Costa's avatar Georges Da Costa
Browse files

Merge branch 'pr_final' into 'devel'

Add memory counters and fix makefile

See merge request !7
parents 61037b58 b3d0e43d
No related branches found
No related tags found
2 merge requests!9fix sensor example (doc),!7Add memory counters and fix makefile
Pipeline #5586 failed
......@@ -6,6 +6,7 @@ doc/info_reader_ex
doc/mojitos.1
tests/run
src/counters_option.h
src/memory_option.h
src/sensors.h
sensors.mk
bin
......
......@@ -27,7 +27,7 @@ The following is an exhaustive list of all the sensors (it is very likely
that one will not have all the sensors activated in his build):
```bash
SENSORS:
-a|--amd-rapl
-r|--amd-rapl
AMD RAPL
-p|--perf-list <perf_list>
performance counters
......@@ -41,8 +41,20 @@ SENSORS:
system load
-d|--net-dev <net_dev>
network monitoring (if network_device is X, tries to detect it automatically)
-n|--nvidia-gpu
provides basic gpu information [clocks, memory, utilization, power, temperature].
-r|--intel-rapl
INTEL RAPL
-c|--cpu-temp
processor temperature
-m|--memory
Retrieves information about the memory via the syscall 'sysinfo(2)'.
-M|--memory-counters <memory_list>
memory counters
memory_list is a coma separated list of memory counters.
Ex: Zswap,Zswapped
-L|--memory-list
list the available memory counters and quit
```
## Installation Instructions
......
......@@ -29,7 +29,7 @@ debug=0
target_hdr=src/sensors.h
target_mk=sensors.mk
nonsensor='counters_option|sensors|util'
nonsensor='counters_option|memory_option|sensors|util'
hdr_blacklist=$nonsensor
hdr_whitelist=''
......@@ -117,6 +117,7 @@ detect_caps() {
[ -r /usr/include/linux/perf_event.h ] && hdr_whitelist=counters
[ -d /sys/class/infiniband ] && hdr_whitelist="${hdr_whitelist}|infiniband"
[ -r /proc/stat ] && hdr_whitelist="${hdr_whitelist}|load"
[ -r /proc/meminfo ] && hdr_whitelist="${hdr_whitelist}|memory_counters"
if [ "$(uname -r | cut -d "." -f 1)" -gt "2" ]; then
hdr_whitelist="${hdr_whitelist}|memory"
......@@ -156,6 +157,8 @@ detect_caps() {
case $1 in
--all | -a)
all=1
NVML_LDFLAGS="-L/usr/local/cuda/lib64 -lnvidia-ml"
NVML_IFLAGS="-I/usr/local/cuda/include"
;;
esac
......
......@@ -18,8 +18,10 @@
*******************************************************/
// ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex
// info_reader_ex.c ./../src/util.c && ./info_reader_ex
// ~/mojitos/doc/$ gcc -Wall -Wextra -Wpedantic -O3 -o info_reader_ex info_reader_ex.c ./../src/util.c && ./info_reader_ex
#include "./../lib/info_reader.c"
#include "./../lib/info_reader.h"
#define MAX_PROCS 64
......@@ -40,7 +42,7 @@ typedef struct {
GenericPointer int_allocator(char *s)
{
unsigned int value = atoi(s);
return (GenericPointer) value;
return (GenericPointer)value;
}
// -- Define the behaviour if the attempted value is a string
......@@ -48,49 +50,49 @@ GenericPointer string_allocator(char *s)
{
char *value = malloc(strlen(s) + 1);
strcpy(value, s);
return (GenericPointer) value;
return (GenericPointer)value;
}
// -- Define the processor setter
void set_processor(GenericPointer storage, GenericPointer data)
{
Cpu *cpu = (Cpu *) storage;
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;
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 *cpu = (Cpu *)storage;
cpu->family = data;
}
// -- Define the core_id setter
void set_core_id(GenericPointer storage, GenericPointer data)
{
Cpu *cpu = (Cpu *) storage;
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 *cpu = (Cpu *)storage;
cpu->physical_id = data;
}
// -- Define the model_name setter
void set_model_name(GenericPointer storage, GenericPointer data)
{
Cpu *cpu = (Cpu *) storage;
cpu->model_name = (char *) data;
Cpu *cpu = (Cpu *)storage;
cpu->model_name = (char *)data;
}
int main()
......@@ -98,26 +100,54 @@ int main()
Cpu cpus[MAX_PROCS];
// -- Define the setter, the allocator for each key / separator.
KeyFinder keys[] = {
{.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}
KeyFinder keys[] = {{
.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
}
};
size_t nb_keys = sizeof(keys)/sizeof(KeyFinder);
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")
};
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);
......@@ -137,4 +167,3 @@ int main()
printf("==============================\n");
return 0;
}
#include <info_reader.h>
void set_value(Parser *parser, KeyFinder *key_finder, char *raw_value)
{
GenericPointer address = parser->storage + (parser->storage_struct_size * parser->nb_stored);
GenericPointer value = key_finder->copy(raw_value);
key_finder->set(address, value);
}
unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value)
{
for (unsigned int i = 0; i < parser->nb_keys; i++) {
KeyFinder *finder = &parser->keys[i];
if (start_with(finder->key, line)) {
char *value = NULL;
char *key = NULL;
split_on_delimiter(line, finder->delimiter, &key, &value);
if ( key == NULL || value == NULL) {
return 0;
}
*key_finder = finder;
*raw_value = value;
return 1;
}
}
return 0;
}
unsigned int move_to_next(Parser *parser)
{
parser->nb_stored += 1;
if (parser->nb_stored >= parser->capacity) {
return 0;
}
return 1;
}
#define PAGE_SIZE 4096
ssize_t buffer_getline(char **lineptr, FILE *stream) {
ssize_t num_chars_read = 0;
static char buffer[PAGE_SIZE] = {0};
if (!lineptr || !stream) {
return -1;
}
while (1) {
int ch = fgetc(stream);
if (ch == EOF) {
if (num_chars_read == 0) {
return -1;
} else {
break;
}
}
if (num_chars_read == PAGE_SIZE - 1) {
return -1;
}
buffer[num_chars_read++] = ch;
if (ch == '\n') {
break;
}
}
buffer[num_chars_read] = '\0';
*lineptr = buffer;
return num_chars_read;
}
unsigned int parse(Parser *parser)
{
char *line = NULL;
ssize_t read;
unsigned int key_assigned = 0;
while ((read = buffer_getline(&line, parser->file)) != -1) {
if (key_assigned == parser->nb_keys && read > 1) {
continue;
} else if (read == 1) {
if (!move_to_next(parser)) {
return 0;
}
key_assigned = 0;
} else {
KeyFinder *key_finder = NULL;
char *raw_value = NULL;
replace_first(line, '\n', '\0');
if (match(parser, line, &key_finder, &raw_value)) {
set_value(parser, key_finder, raw_value);
++key_assigned;
}
}
}
if (key_assigned > 0) {
parser->nb_stored++;
}
return 1;
}
void replace_first(char *string, char from, char to)
{
for (int i = 0; string[i] != '\0'; i++) {
if (string[i] == from) {
string[i] = to;
break;
}
}
}
void split_on_delimiter(char *string, const char *delimiter, char **key, char **value)
{
*key = NULL;
*value = NULL;
size_t delimiter_len = strlen(delimiter);
char *start_delimiter = strstr(string, delimiter);
if (start_delimiter != NULL) {
*start_delimiter = '\0';
*key = string;
*value = start_delimiter + delimiter_len;
}
}
bool start_with(const char *prefix, const char *string)
{
if (prefix == NULL || string == NULL) {
return false;
}
size_t prefix_len = strlen(prefix);
size_t string_len = strlen(string);
if (string_len < prefix_len) {
return false;
} else {
return memcmp(prefix, string, prefix_len) == 0;
}
}
......@@ -21,36 +21,42 @@
#ifndef _INFO_READER_H
#define _INFO_READER_H
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* @struct Parser
* @brief The parser struct
* The struct containing all the necessary informations and functions to parse a file
* The struct containing all the necessary informations and functions to parse a
* file
*
* @var storage : GenericPointer : pointer to the storage where the parsed data will be stored
* @var storage : GenericPointer : pointer to the storage where the parsed data
* will be stored
* @var nb_stored : unsigned int : the number of struct stored
* @var capacity : unsigned int : the maximum number of struct that can be stored
* @var storage_struct_size : size_t : the size of the struct stored in the storage
* @var keys : KeyFinder* : pointer to an array of KeyFinder containing the possible keys
* @var capacity : unsigned int : the maximum number of struct that can be
* stored
* @var storage_struct_size : size_t : the size of the struct stored in the
* storage
* @var keys : KeyFinder* : pointer to an array of KeyFinder containing the
* possible keys
* @var nb_keys : unsigned int : number of key finders
* @var file : FILE* : pointer to the file that will be parsed
*/
*/
typedef struct Parser Parser;
/**
* @struct KeyFinder
* @brief The key finder struct
* The struct containing all the necessary informations and functions to find a key in a line of text
* The struct containing all the necessary informations and functions to find a
* key in a line of text
*
* @var key : char* : the key to be found
* @var delimiter : char* : the delimiter between the key and the value
* @var copy : CopyAllocator*: the function to use to make a copy of the value
* @var set : Setter*: the function to use to store the value in the storage
*/
*/
typedef struct KeyFinder KeyFinder;
/**
......@@ -68,20 +74,24 @@ typedef struct KeyFinder KeyFinder;
* @param[out] value A pointer to a char pointer where the value will be stored.
* @return None.
*/
static void split_on_delimiter(char *string, const char *delimiter, char **key, char **value);
void split_on_delimiter(char *string, const char *delimiter, char **key,
char **value);
/**
* @brief Replace the first occurrence of a character in a string with another character.
* @brief Replace the first occurrence of a character in a string with another
* character.
*
* The function takes a string and two characters as input, and replaces the first
* occurrence of the first character in the string with the second character.
* The function takes a string and two characters as input, and replaces the
* first occurrence of the first character in the string with the second
* character.
*
* @param[in,out] string The input string where the replacement should take place.
* @param[in,out] string The input string where the replacement should take
* place.
* @param[in] from The character to be replaced.
* @param[in] to The character to replace with.
* @return None.
*/
static void replace_first(char *string, char from, char to);
void replace_first(char *string, char from, char to);
/**
* @brief Check if a string starts with a prefix.
......@@ -89,155 +99,74 @@ static void replace_first(char *string, char from, char to);
* @param[in] prefix The prefix to check.
* @param[in] string The string to check.
* @return true The string starts with the prefix.
* @return false The string does not start with the prefix or one of the input pointers is NULL.
* @return false The string does not start with the prefix or one of the input
* pointers is NULL.
*/
static bool start_with(const char *prefix, const char *string);
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[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.
* @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.
*/
static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value);
unsigned int match(Parser *parser, char *line, KeyFinder **key_finder,
char **raw_value);
/**
* @brief Reads a line of text from a file stream and stores it in a static
buffer with a maximum size of PAGE_SIZE.
* This function reads a line of text from the input stream pointed to by
* 'stream'. The line of text is stored in a static buffer with a maximum size of
* PAGE_SIZE. The function updates the pointer pointed to by 'lineptr' to point
to
* the buffer containing the line of text. If the line of text is longer than the
* buffer, the function returns -1. If an error occurs,
* @param lineptr A pointer to a pointer to the buffer where the line of text
will be stored.
* @param stream A pointer to the input stream to read from.
* @return The number of characters read, or -1 if an error occurred the
function returns -1.
*/
ssize_t buffer_getline(char **lineptr, FILE *stream);
/**
* @brief Parse with the configured parser.
*
* @param parser the parser.
*/
unsigned int parse(Parser *parser);
typedef size_t GenericPointer;
typedef GenericPointer (CopyAllocator) (char *string);
typedef void (Setter) (GenericPointer storage, GenericPointer value);
typedef GenericPointer(CopyAllocator)(char *string);
typedef void(Setter)(GenericPointer storage, GenericPointer value);
struct KeyFinder {
char *key;
char *delimiter;
char *key;
char *delimiter;
CopyAllocator *copy;
Setter *set;
CopyAllocator *copy;
Setter *set;
};
struct Parser {
GenericPointer storage;
unsigned int nb_stored;
unsigned int capacity;
size_t storage_struct_size;
GenericPointer storage;
unsigned int nb_stored;
unsigned int capacity;
size_t storage_struct_size;
KeyFinder *keys;
unsigned int nb_keys;
KeyFinder *keys;
unsigned int nb_keys;
FILE *file;
FILE *file;
};
static void set_value(Parser *parser, KeyFinder *key_finder, char *raw_value)
{
GenericPointer address = parser->storage + (parser->storage_struct_size * parser->nb_stored);
GenericPointer value = key_finder->copy(raw_value);
key_finder->set(address, value);
}
static unsigned int match(Parser *parser, char *line, KeyFinder **key_finder, char **raw_value)
{
for (unsigned int i = 0; i < parser->nb_keys; i++) {
KeyFinder *finder = &parser->keys[i];
if (start_with(finder->key, line)) {
char *value = NULL;
char *key = NULL;
split_on_delimiter(line, finder->delimiter, &key, &value);
if ( key == NULL || value == NULL) {
return 0;
}
*key_finder = finder;
*raw_value = value;
return 1;
}
}
return 0;
}
static unsigned int move_to_next(Parser *parser)
{
parser->nb_stored += 1;
if (parser->nb_stored >= parser->capacity) {
return 0;
}
return 1;
}
static unsigned int parse(Parser *parser)
{
char *line = NULL;
size_t len = 0;
ssize_t read;
unsigned int key_assigned = 0;
while ((read = getline(&line, &len, parser->file)) != -1) {
if (key_assigned == parser->nb_keys && read > 1) {
continue;
} else if (read == 1) {
if (!move_to_next(parser)) {
return 0;
}
key_assigned = 0;
} else {
KeyFinder *key_finder = NULL;
char *raw_value = NULL;
replace_first(line, '\n', '\0');
if (match(parser, line, &key_finder, &raw_value)) {
set_value(parser, key_finder, raw_value);
++key_assigned;
}
}
}
if (key_assigned > 0) {
parser->nb_stored++;
}
free(line);
return 1;
}
static void replace_first(char *string, char from, char to)
{
for (int i = 0; string[i] != '\0'; i++) {
if (string[i] == from) {
string[i] = to;
break;
}
}
}
static void split_on_delimiter(char *string, const char *delimiter, char **key, char **value)
{
*key = NULL;
*value = NULL;
size_t delimiter_len = strlen(delimiter);
char *start_delimiter = strstr(string, delimiter);
if (start_delimiter != NULL) {
*start_delimiter = '\0';
*key = string;
*value = start_delimiter + delimiter_len;
}
}
static bool start_with(const char *prefix, const char *string)
{
if (prefix == NULL || string == NULL) {
return false;
}
size_t prefix_len = strlen(prefix);
size_t string_len = strlen(string);
if (string_len < prefix_len) {
return false;
} else {
return memcmp(prefix, string, prefix_len) == 0;
}
}
#endif
......@@ -3,6 +3,7 @@
SRC_DIR = src
DOC_DIR = doc
OBJ_DIR = obj
LIB_DIR = lib
BIN_DIR = bin
TESTS_DIR = tests
......@@ -25,8 +26,9 @@ NVML_IFLAGS =
include ./sensors.mk
OBJ = \
$(CAPTOR_OBJ) \
$(OBJ_DIR)/util.o
$(OBJ_DIR)/util.o \
$(OBJ_DIR)/info_reader.o \
$(CAPTOR_OBJ)
options:
@echo BIN: $(BIN)
......@@ -40,16 +42,23 @@ $(BIN): $(BIN_DIR) $(OBJ) $(OBJ_DIR)/$(BIN).o
$(OBJ): $(OBJ_DIR)
$(OBJ_DIR)/counters.o: $(SRC_DIR)/counters_option.h
$(OBJ_DIR)/memory_counters.o: $(SRC_DIR)/memory_option.h
$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c $(SRC_DIR)/counters_option.h
$(OBJ_DIR)/$(BIN).o: $(SRC_DIR)/$(BIN).c
$(CC) $(CFLAGS) -c $< -o $@
$(OBJ_DIR)/util.o: $(SRC_DIR)/util.c $(SRC_DIR)/util.h
$(CC) $(CFLAGS) -c $< -o $@
$(OBJ_DIR)/info_reader.o: $(LIB_DIR)/info_reader.c
$(CC) $(CFLAGS) -c $< -o $@
$(SRC_DIR)/counters_option.h: $(SRC_DIR)/counters_option.sh
sh ./$(SRC_DIR)/counters_option.sh > $(SRC_DIR)/counters_option.h
$(SRC_DIR)/memory_option.h: $(SRC_DIR)/memory_option.sh
sh ./$(SRC_DIR)/memory_option.sh > $(SRC_DIR)/memory_option.h
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
......@@ -59,8 +68,8 @@ $(BIN_DIR):
debug: CFLAGS = $(CPPFLAGS) -DDEBUG -g -Og
debug: $(BIN)
tests:
$(CC) $(CPPFLAGS) $(TESTS_DIR)/main.c $(SRC_DIR)/util.c -o $(TESTS_DIR)/run
tests: $(OBJ_DIR)/util.o $(OBJ_DIR)/info_reader.o
$(CC) $(CPPFLAGS) $(OBJ_DIR)/util.o $(OBJ_DIR)/info_reader.o $(TESTS_DIR)/main.c -o $(TESTS_DIR)/run
$(TESTS_DIR)/run
format:
......@@ -71,11 +80,12 @@ format:
clean:
\rm -f $(OBJ_DIR)/* $(BIN_DIR)/* \
$(SRC_DIR)/counters_option.h \
$(SRC_DIR)/memory_option.h \
$(TESTS_DIR)/run \
$(DOC_DIR)/test_main_ex \
$(DOC_DIR)/info_reader_ex
readme: $(BIN)
readme:
sh ./tools/update-readme-usage.sh
man: $(BIN)
......
......@@ -201,7 +201,7 @@ void debug_print_amd_rapl(AmdRapl *rapl)
unsigned int get_nb_cpu()
{
char filename[BUFFER_SIZE];
int cpy_errno;
int cpy_errno;
unsigned int n_cpu = 0;
for (;; n_cpu++) {
......@@ -215,22 +215,22 @@ unsigned int get_nb_cpu()
close(fd);
}
if (n_cpu == 0) {
perror("open()");
fprintf(stderr, "on the file: '%s'\n", filename);
switch (cpy_errno) {
case ENOENT:
fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n");
exit(99);
case EACCES:
fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n");
exit(98);
default:
fprintf(stderr, "Unexpected error\n");
exit(97);
}
}
// n_cpu > 0
if (n_cpu == 0) {
perror("open()");
fprintf(stderr, "on the file: '%s'\n", filename);
switch (cpy_errno) {
case ENOENT:
fprintf(stderr, "Amd rapl works with msr module, try to run 'sudo modprobe msr', then retry.\n");
exit(99);
case EACCES:
fprintf(stderr, "Amd rapl must be executed with the administrator privilege, try with 'sudo'.\n");
exit(98);
default:
fprintf(stderr, "Unexpected error\n");
exit(97);
}
}
// n_cpu > 0
return n_cpu;
}
......
#include "memory_option.h"
#include "util.h"
#include <fcntl.h>
#include <info_reader.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *path = "/proc/meminfo";
typedef struct {
KeyFinder *keys;
unsigned int count;
FILE *file;
} MemoryCounters;
GenericPointer long_allocator(char *s)
{
long value = atol(s);
return (GenericPointer)value;
}
KeyFinder *build_keyfinder(unsigned int count, unsigned int *indexes)
{
KeyFinder *keys = (KeyFinder *)calloc(count, sizeof(KeyFinder));
for (unsigned int i = 0; i < count; i++) {
unsigned int idx = indexes[i];
KeyFinder key = {.key = memory_counters[idx],
.delimiter = ":",
.copy = long_allocator,
.set = setter_functions[i]
};
memcpy(&keys[i], &key, sizeof(KeyFinder));
}
return keys;
}
void memory_list(char *memory_string, unsigned int *count,
unsigned int *indexes)
{
char *token;
*count = 0;
while ((token = strtok(memory_string, ",")) != NULL) {
memory_string = NULL;
unsigned int i;
for (i = 0; i < NB_COUNTERS; i++) {
if (strcmp(memory_counters[i], token) == 0) {
(*count)++;
indexes[*count - 1] = i;
break;
}
}
if (i == NB_COUNTERS) {
fprintf(stderr, "Unknown memory counter: %s\n", token);
exit(EXIT_FAILURE);
}
if ((*count) > NB_COUNTERS) {
fprintf(stderr, "Too much counters, there are probably duplicates\n");
exit(EXIT_FAILURE);
}
}
}
unsigned int init_memory_counters(char *args, void **ptr)
{
unsigned int indexes[NB_COUNTERS];
unsigned int count = 0;
memory_list(args, &count, indexes);
KeyFinder *keys = build_keyfinder(count, indexes);
FILE *file = fopen(path, "r");
MemoryCounters *counters = calloc(1, sizeof(MemoryCounters));
counters->keys = keys;
counters->count = count;
counters->file = file;
*ptr = (void *)counters;
return count;
}
unsigned int get_memory_counters(uint64_t *results, void *ptr)
{
MemoryCounters *counters = (MemoryCounters *)ptr;
fseek(counters->file, 0, SEEK_SET);
Parser parser = {.storage = (GenericPointer)results,
.capacity = 1,
.nb_stored = 0,
.storage_struct_size = sizeof(uint64_t) * counters->count,
.keys = counters->keys,
.nb_keys = counters->count,
.file = counters->file
};
parse(&parser);
return counters->count;
}
void label_memory_counters(char **labels, void *ptr)
{
MemoryCounters *counters = (MemoryCounters *)ptr;
for (unsigned int i = 0; i < counters->count; i++) {
labels[i] = counters->keys[i].key;
}
}
void clean_memory_counters(void *ptr)
{
MemoryCounters *counters = (MemoryCounters *)ptr;
fclose(counters->file);
free(counters->keys);
free(ptr);
}
void *show_all_memory_counters(void *none1, size_t none2)
{
for (unsigned int i = 0; i < NB_COUNTERS; i++) {
printf("%s\n", memory_counters[i]);
}
UNUSED(none1);
UNUSED(none2);
exit(EXIT_SUCCESS);
return NULL; /* not reached */
}
/*******************************************************
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_counters(char *args, void **ptr);
unsigned int get_memory_counters(uint64_t *results, void *ptr);
void label_memory_counters(char **labels, void *ptr);
void clean_memory_counters(void *ptr);
void *show_all_memory_counters(void *, size_t);
Sensor memory_counters = {
.init = init_memory_counters,
.get = get_memory_counters,
.clean = clean_memory_counters,
.label = label_memory_counters,
.nb_opt = 2,
};
Optparse memory_counters_opt[2] = {
{
.longname = "memory-counters",
.shortname = 'M',
.argtype = OPTPARSE_REQUIRED,
.usage_arg = "<memory_list>",
.usage_msg =
"memory counters\n"
"\tmemory_list is a coma separated list of memory counters.\n"
"\tEx: Zswap,Zswapped",
},
{
.longname = "memory-list",
.shortname = 'L',
.argtype = OPTPARSE_NONE,
.usage_arg = NULL,
.usage_msg = "list the available memory counters and quit",
.fn = show_all_memory_counters,
},
};
#!/bin/sh
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2018-2023 Georges Da Costa <georges.da-costa@irit.fr>
meminfo_path=/proc/meminfo
function_template="void set_result_offset%s(GenericPointer ptr, GenericPointer data)
{
uint64_t* result = (uint64_t *) ptr;
result[%s] = (uint64_t) data;
}\n\n"
nb_counters=0
echo '#include <inttypes.h>'
echo '#include <info_reader.h>'
echo
echo 'static char *memory_counters[] = {'
while read line; do
: $((nb_counters += 1))
echo "$line" | awk -F ':' '{printf(" \"%s\",\n", $1)}'
done < "$meminfo_path"
echo '};'
echo
echo "#define NB_COUNTERS $nb_counters"
echo
count=0
while [ $count -lt $nb_counters ]; do
printf "$function_template" $count $count
: $((count += 1))
done
echo 'static void (*setter_functions[])(GenericPointer, GenericPointer) = {'
count=0
while [ $count -lt $nb_counters ]; do
echo " set_result_offset$count,"
: $((count += 1))
done
echo '};'
echo
......@@ -159,9 +159,9 @@ unsigned int init_network(char *dev, void **ptr)
/* compare dev name to the previously saved one */
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 (strncmp(start_of_dev, state->devs[i], s - start_of_dev) == 0) {
newdev = 0;
}
}
if (newdev) {
if (state->ndev >= NB_MAX_DEV) {
......
......@@ -169,28 +169,36 @@ TFUNCTION(test_start_with, {
})
#define NONE 0
#define INIT_KEYFINDER(__key_finder, __key, __delimiter, __copy, __set) \
do { \
__key_finder = (KeyFinder) { \
.key = __key, \
.delimiter = __delimiter, \
.copy = __copy, \
.set = __set \
}; \
} while (0);
#define DUMMY_KEYFINDER(__key_finder, __key, __delimiter) \
do { \
__key_finder = (KeyFinder) { \
.key = __key, \
.delimiter = __delimiter, \
.copy = NONE, \
.set = NONE \
}; \
INIT_KEYFINDER(__key_finder, __key, __delimiter, NONE, NONE) \
#define INIT_PARSER(__parser, __storage, __nb_stored, __capacity, \
__storage_struct_size, __keys, __nb_keys, __file) \
do { \
__parser = (Parser) { \
.storage = __storage, \
.nb_stored = __nb_stored, \
.capacity = __capacity, \
.storage_struct_size = __storage_struct_size, \
.keys = __keys, \
.nb_keys = __nb_keys, \
.file = __file \
}; \
} 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);
INIT_PARSER(__parser, NONE, NONE, NONE, NONE, __keys, __nb_keys, NONE)
TFUNCTION(test_match, {
......@@ -275,10 +283,58 @@ TFUNCTION(test_match, {
TEST_STR(raw_value, NULL);
})
#define __NB_KEYS 4
typedef struct {
int values[__NB_KEYS];
} IntArray;
GenericPointer __test_file_int_allocator(char *s)
{
unsigned int value = atoi(s);
return (GenericPointer) value;
}
void __test_file_set_int(GenericPointer storage, GenericPointer data)
{
IntArray *array = (IntArray *) storage;
int i = (int) data;
array->values[i] = i;
}
TFUNCTION(test_dummy_file, {
KeyFinder keys[__NB_KEYS];
INIT_KEYFINDER(keys[0], "int0", " : ", __test_file_int_allocator, __test_file_set_int);
INIT_KEYFINDER(keys[1], "int1", " ", __test_file_int_allocator, __test_file_set_int);
INIT_KEYFINDER(keys[2], "int2", " -> ", __test_file_int_allocator, __test_file_set_int);
INIT_KEYFINDER(keys[3], "int3", "--", __test_file_int_allocator, __test_file_set_int);
IntArray results;
IntArray expected;
expected.values[0] = 0;
expected.values[1] = 1;
expected.values[2] = 2;
expected.values[3] = 3;
Parser parser;
FILE *file = fopen("./tests/info_reader_test.txt", "r");
INIT_PARSER(parser, (GenericPointer) &results, 0, 1, sizeof(IntArray), keys, __NB_KEYS, file);
parse(&parser);
for (unsigned int i = 0; i < __NB_KEYS; i++)
{
TEST_INT(&(results.values[i]), &(expected.values[i]));
}
fclose(file);
})
TFILE_ENTRY_POINT(test_info_reader, {
CALL_TFUNCTION(test_replace_first);
CALL_TFUNCTION(test_split_on_delimiter);
CALL_TFUNCTION(test_start_with);
CALL_TFUNCTION(test_match);
CALL_TFUNCTION(test_dummy_file);
})
noise:
int0 : 0
noise--
int1 1
int2 -> 2
noise->
int3--3
noise----->>ss<<
noiseee
......@@ -270,8 +270,8 @@ int test(char *file, int line, unsigned int __indentation_level, const void *res
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);
char *fmt_expected = interface->format(buffer_expected, expected);
char *fmt_result = interface->format(buffer_result, result);
if (!is_equal) {
INDENTED_PRINT("%s:%d: failed, expected <%s>, got <%s>\n", file, line, fmt_expected, fmt_result);
}
......
......@@ -78,45 +78,45 @@ TFUNCTION(test_modulo_substraction, {
})
TFUNCTION(test_max, {
int expected = 0;
int result = 0;
int expected = 0;
int result = 0;
expected = 10;
result = MAX(expected, 9);
TEST_INT(&result, &expected);
expected = 10;
result = MAX(expected, 9);
TEST_INT(&result, &expected);
expected = -15;
result = MAX(expected, -16);
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 = 0;
result = MAX(expected, -1);
TEST_INT(&result, &expected);
expected = 1;
result = MAX(expected, 0);
TEST_INT(&result, &expected);
expected = 1;
result = MAX(expected, 0);
TEST_INT(&result, &expected);
})
TFUNCTION(test_min, {
int expected = 0;
int result = 0;
int expected = 0;
int result = 0;
expected = 9;
result = MIN(expected, 10);
TEST_INT(&result, &expected);
expected = 9;
result = MIN(expected, 10);
TEST_INT(&result, &expected);
expected = -16;
result = MIN(expected, -15);
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 = -1;
result = MIN(expected, 0);
TEST_INT(&result, &expected);
expected = 0;
result = MIN(expected, 1);
TEST_INT(&result, &expected);
expected = 0;
result = MIN(expected, 1);
TEST_INT(&result, &expected);
})
TFILE_ENTRY_POINT(test_util, {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment