Add clock offset parser
This commit is contained in:
		
							parent
							
								
									894e972a65
								
							
						
					
					
						commit
						fe5f16bb7a
					
				
							
								
								
									
										138
									
								
								src/emu/clkoff.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/emu/clkoff.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,138 @@ | ||||
| #include "clkoff.h" | ||||
| 
 | ||||
| #include "common.h" | ||||
| #include <errno.h> | ||||
| 
 | ||||
| static struct clkoff_entry * | ||||
| cfind(struct clkoff *off, const char *name) | ||||
| { | ||||
| 	struct clkoff_entry *entry = NULL; | ||||
| 
 | ||||
| 	HASH_FIND_STR(off->entries, name, entry); | ||||
| 	return entry; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| cadd(struct clkoff *table, struct clkoff_entry e) | ||||
| { | ||||
| 	if (cfind(table, e.name) != NULL) { | ||||
| 		err("entry with name '%s' already exists\n", e.name); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	struct clkoff_entry *entry = calloc(1, sizeof(struct clkoff_entry)); | ||||
| 	if (entry == NULL) { | ||||
| 		err("calloc failed\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(entry, &e, sizeof(*entry)); | ||||
| 	 | ||||
| 	HASH_ADD_STR(table->entries, name, entry); | ||||
| 	table->nentries++; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| cparse(struct clkoff *table, FILE *file) | ||||
| { | ||||
| 	/* Ignore header line */ | ||||
| 	char buf[1024]; | ||||
| 	if (fgets(buf, 1024, file) == NULL) { | ||||
| 		err("missing header line in clock offset\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	for (int line = 1; ; line++) { | ||||
| 		errno = 0; | ||||
| 		struct clkoff_entry e = { 0 }; | ||||
| 
 | ||||
| 		if (fgets(buf, 1024, file) == NULL) | ||||
| 			break; | ||||
| 
 | ||||
| 		/* Empty line */ | ||||
| 		if (buf[0] == '\n') | ||||
| 			continue; | ||||
| 
 | ||||
| 		int ret = sscanf(buf, "%ld %s %lf %lf %lf", | ||||
| 				&e.index, e.name, | ||||
| 				&e.median, &e.mean, &e.stdev); | ||||
| 
 | ||||
| 		if (ret == EOF && errno == 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		if (ret == EOF && errno != 0) { | ||||
| 			err("fscanf() failed in line %d\n", line); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (ret != 5) { | ||||
| 			err("fscanf() read %d instead of 5 fields in line %d\n", | ||||
| 					ret, line); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cadd(table, e) != 0) { | ||||
| 			err("cannot add entry of line %d\n", | ||||
| 					line); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| cindex(struct clkoff *table) | ||||
| { | ||||
| 	if (table->nentries < 1) { | ||||
| 		err("no entries\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	table->index = calloc(table->nentries, sizeof(struct clkoff_entry *)); | ||||
| 
 | ||||
| 	if (table->index == NULL) { | ||||
| 		err("calloc failed\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	struct clkoff_entry *e; | ||||
| 	int i = 0; | ||||
| 	for (e = table->entries; e; e = e->hh.next) | ||||
| 		table->index[i++] = e; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| clkoff_init(struct clkoff *table, FILE *file) | ||||
| { | ||||
| 	memset(table, 0, sizeof(struct clkoff)); | ||||
| 
 | ||||
| 	if (cparse(table, file) != 0) { | ||||
| 		err("clkoff_init: failed parsing clock table\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Create index array */ | ||||
| 	if (cindex(table) != 0) { | ||||
| 		err("clkoff_init: failed indexing table\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| clkoff_count(struct clkoff *table) | ||||
| { | ||||
| 	return table->nentries; | ||||
| } | ||||
| 
 | ||||
| struct clkoff_entry * | ||||
| clkoff_get(struct clkoff *table, int i) | ||||
| { | ||||
| 	return table->index[i]; | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/emu/clkoff.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/emu/clkoff.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| /* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
 | ||||
|  * SPDX-License-Identifier: GPL-3.0-or-later */ | ||||
| 
 | ||||
| #ifndef CLKOFF_H | ||||
| #define CLKOFF_H | ||||
| 
 | ||||
| #include "uthash.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <linux/limits.h> | ||||
| 
 | ||||
| struct clkoff_entry { | ||||
| 	int64_t index; | ||||
| 	char name[PATH_MAX]; | ||||
| 	double median; | ||||
| 	double mean; | ||||
| 	double stdev; | ||||
| 	UT_hash_handle hh; | ||||
| }; | ||||
| 
 | ||||
| struct clkoff { | ||||
| 	int nentries; | ||||
| 	struct clkoff_entry *entries; | ||||
| 	struct clkoff_entry **index; | ||||
| }; | ||||
| 
 | ||||
| int clkoff_init(struct clkoff *table, FILE *file); | ||||
| int clkoff_count(struct clkoff *table); | ||||
| struct clkoff_entry *clkoff_get(struct clkoff *table, int i); | ||||
| 
 | ||||
| #endif /* CLKOFF_H */ | ||||
| @ -17,3 +17,4 @@ unit_test(prv.c) | ||||
| #unit_test(ovni_model.c) | ||||
| unit_test(emu_trace.c) | ||||
| unit_test(emu.c) | ||||
| unit_test(clkoff.c) | ||||
|  | ||||
							
								
								
									
										73
									
								
								test/unit/clkoff.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								test/unit/clkoff.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| #define _POSIX_C_SOURCE 200809L | ||||
| 
 | ||||
| #include "emu/clkoff.h" | ||||
| #include "common.h" | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| static int | ||||
| test_ok(void) | ||||
| { | ||||
| 	char table_str[] = | ||||
| 	"rank       hostname             offset_median        offset_mean          offset_std\n" | ||||
| 	"0          s09r2b21             0                    0.000000             0.000000\n" | ||||
| 	"1          s09r2b22             -451607967           -451608083.500000    316.087397\n" | ||||
| 	"2          s09r2b23             4526                 4542.200000          124.33432\n" | ||||
| 	"3          s09r2b24             342455               342462.300000        342.39755\n"; | ||||
| 
 | ||||
| 	FILE *f = fmemopen(table_str, ARRAYLEN(table_str), "r"); | ||||
| 
 | ||||
| 	if (f == NULL) | ||||
| 		die("fmemopen failed\n"); | ||||
| 
 | ||||
| 	struct clkoff table; | ||||
| 	clkoff_init(&table); | ||||
| 	if (clkoff_load(&table, f) != 0) | ||||
| 		die("clkoff_load failed\n"); | ||||
| 
 | ||||
| 	if (clkoff_count(&table) != 4) | ||||
| 		die("clkoff_count failed\n"); | ||||
| 
 | ||||
| 	struct clkoff_entry *entry = clkoff_get(&table, 3); | ||||
| 	if (entry == NULL) | ||||
| 		die("clkoff_get returned NULL\n"); | ||||
| 
 | ||||
| 	if (entry->index != 3) | ||||
| 		die("clkoff_get returned wrong index\n"); | ||||
| 
 | ||||
| 	fclose(f); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| test_dup(void) | ||||
| { | ||||
| 	static char table_str[] = | ||||
| 	"rank       hostname             offset_median        offset_mean          offset_std\n" | ||||
| 	"0          s09r2b21             0                    0.000000             0.000000\n" | ||||
| 	"1          s09r2b22             -451607967           -451608083.500000    316.087397\n" | ||||
| 	"2          s09r2b23             4526                 4542.200000          124.33432\n" | ||||
| 	"3          s09r2b23             342455               342462.300000        342.39755\n"; | ||||
| 
 | ||||
| 	FILE *f = fmemopen(table_str, ARRAYLEN(table_str), "r"); | ||||
| 
 | ||||
| 	if (f == NULL) | ||||
| 		die("fmemopen failed\n"); | ||||
| 
 | ||||
| 	struct clkoff table; | ||||
| 
 | ||||
| 	clkoff_init(&table); | ||||
| 	if (clkoff_load(&table, f) == 0) | ||||
| 		die("clkoff_load didn't fail\n"); | ||||
| 
 | ||||
| 	fclose(f); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int main(void) | ||||
| { | ||||
| 	test_ok(); | ||||
| 	test_dup(); | ||||
| 	return 0; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user