Store CPU list in a metadata.json file
This allows early access to the CPU list in order to emit the PRV header before consuming events from the streams.
This commit is contained in:
		
							parent
							
								
									763bcf7c33
								
							
						
					
					
						commit
						60862db890
					
				
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							| @ -17,16 +17,16 @@ all: $(BIN) | |||||||
| libovni.a: ovni.o | libovni.a: ovni.o | ||||||
| 	ar -crs $@ $^ | 	ar -crs $@ $^ | ||||||
| 
 | 
 | ||||||
| dump: ovni.o dump.o | dump: ovni.o dump.o parson.o | ||||||
| 
 | 
 | ||||||
| test_speed: test_speed.c ovni.o | test_speed: test_speed.c ovni.o parson.o | ||||||
| 
 | 
 | ||||||
| emu: emu.o emu_ovni.o emu_nosv.o ovni.o prv.o | emu: emu.o emu_ovni.o emu_nosv.o ovni.o prv.o parson.o | ||||||
| 
 | 
 | ||||||
| libovni.so: ovni.o | libovni.so: ovni.o parson.o | ||||||
| 	$(LINK.c) -shared $^ -o $@ | 	$(LINK.c) -shared $^ -o $@ | ||||||
| 
 | 
 | ||||||
| ovni2prv: ovni2prv.c ovni.o | ovni2prv: ovni2prv.c ovni.o parson.o | ||||||
| 
 | 
 | ||||||
| ovnisync: ovnisync.c | ovnisync: ovnisync.c | ||||||
| 	mpicc -lm $^ -o $@ | 	mpicc -lm $^ -o $@ | ||||||
|  | |||||||
							
								
								
									
										120
									
								
								emu.c
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								emu.c
									
									
									
									
									
								
							| @ -190,6 +190,7 @@ emulate(struct ovni_emu *emu) | |||||||
| 		ovni_load_next_event(stream); | 		ovni_load_next_event(stream); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 	emu->lastclock = 0; | 	emu->lastclock = 0; | ||||||
| 
 | 
 | ||||||
| 	/* Then process all events */ | 	/* Then process all events */ | ||||||
| @ -237,6 +238,112 @@ emu_get_thread(struct ovni_emu *emu, int tid) | |||||||
| 	return thread; | 	return thread; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void | ||||||
|  | add_new_cpu(struct ovni_emu *emu, struct ovni_loom *loom, int i, int phyid) | ||||||
|  | { | ||||||
|  | 	/* The logical id must match our index */ | ||||||
|  | 	assert(i == loom->ncpus); | ||||||
|  | 
 | ||||||
|  | 	assert(loom->cpu[i].state == CPU_ST_UNKNOWN); | ||||||
|  | 
 | ||||||
|  | 	loom->cpu[loom->ncpus].state = CPU_ST_READY; | ||||||
|  | 	loom->cpu[loom->ncpus].i = i; | ||||||
|  | 	loom->cpu[loom->ncpus].phyid = phyid; | ||||||
|  | 	loom->cpu[loom->ncpus].gindex = emu->total_cpus++; | ||||||
|  | 
 | ||||||
|  | 	dbg("new cpu %d at phyid=%d\n", i, phyid); | ||||||
|  | 
 | ||||||
|  | 	loom->ncpus++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | proc_load_cpus(struct ovni_emu *emu, struct ovni_loom *loom, struct ovni_eproc *proc) | ||||||
|  | { | ||||||
|  | 	JSON_Array *cpuarray; | ||||||
|  | 	JSON_Object *cpu; | ||||||
|  | 	JSON_Object *meta; | ||||||
|  | 	int i, index, phyid; | ||||||
|  | 
 | ||||||
|  | 	meta = json_value_get_object(proc->meta); | ||||||
|  | 
 | ||||||
|  | 	assert(meta); | ||||||
|  | 
 | ||||||
|  | 	cpuarray = json_object_get_array(meta, "cpus"); | ||||||
|  | 
 | ||||||
|  | 	/* This process doesn't have the cpu list */ | ||||||
|  | 	if(cpuarray == NULL) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	assert(loom->ncpus == 0); | ||||||
|  | 
 | ||||||
|  | 	for(i = 0; i < json_array_get_count(cpuarray); i++) | ||||||
|  | 	{ | ||||||
|  | 		cpu = json_array_get_object(cpuarray, i); | ||||||
|  | 
 | ||||||
|  | 		index = (int) json_object_get_number(cpu, "index"); | ||||||
|  | 		phyid = (int) json_object_get_number(cpu, "phyid"); | ||||||
|  | 
 | ||||||
|  | 		add_new_cpu(emu, loom, index, phyid); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Obtain CPUs in the metadata files and other data */ | ||||||
|  | static int | ||||||
|  | load_metadata(struct ovni_emu *emu) | ||||||
|  | { | ||||||
|  | 	int i, j, k, s; | ||||||
|  | 	struct ovni_loom *loom; | ||||||
|  | 	struct ovni_eproc *proc; | ||||||
|  | 	struct ovni_ethread *thread; | ||||||
|  | 	struct ovni_stream *stream; | ||||||
|  | 	struct ovni_trace *trace; | ||||||
|  | 
 | ||||||
|  | 	trace = &emu->trace; | ||||||
|  | 
 | ||||||
|  | 	for(i=0; i<trace->nlooms; i++) | ||||||
|  | 	{ | ||||||
|  | 		loom = &trace->loom[i]; | ||||||
|  | 		for(j=0; j<loom->nprocs; j++) | ||||||
|  | 		{ | ||||||
|  | 			proc = &loom->proc[j]; | ||||||
|  | 
 | ||||||
|  | 			proc_load_cpus(emu, loom, proc); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* One of the process must have the list of CPUs */ | ||||||
|  | 		/* FIXME: The CPU list should be at the loom dir */ | ||||||
|  | 		assert(loom->ncpus > 0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | destroy_metadata(struct ovni_emu *emu) | ||||||
|  | { | ||||||
|  | 	int i, j, k, s; | ||||||
|  | 	struct ovni_loom *loom; | ||||||
|  | 	struct ovni_eproc *proc; | ||||||
|  | 	struct ovni_ethread *thread; | ||||||
|  | 	struct ovni_stream *stream; | ||||||
|  | 	struct ovni_trace *trace; | ||||||
|  | 
 | ||||||
|  | 	trace = &emu->trace; | ||||||
|  | 
 | ||||||
|  | 	for(i=0; i<trace->nlooms; i++) | ||||||
|  | 	{ | ||||||
|  | 		loom = &trace->loom[i]; | ||||||
|  | 		for(j=0; j<loom->nprocs; j++) | ||||||
|  | 		{ | ||||||
|  | 			proc = &loom->proc[j]; | ||||||
|  | 
 | ||||||
|  | 			assert(proc->meta); | ||||||
|  | 			json_value_free(proc->meta); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| @ -256,16 +363,23 @@ main(int argc, char *argv[]) | |||||||
| 	memset(&emu, 0, sizeof(emu)); | 	memset(&emu, 0, sizeof(emu)); | ||||||
| 
 | 
 | ||||||
| 	if(ovni_load_trace(&emu.trace, tracedir)) | 	if(ovni_load_trace(&emu.trace, tracedir)) | ||||||
| 		return 1; | 		abort(); | ||||||
| 
 | 
 | ||||||
| 	if(ovni_load_streams(&emu.trace)) | 	if(ovni_load_streams(&emu.trace)) | ||||||
| 		return 1; | 		abort(); | ||||||
| 
 | 
 | ||||||
| 	printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", 10); | 	if(load_metadata(&emu) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", emu.total_cpus); | ||||||
| 
 | 
 | ||||||
| 	emulate(&emu); | 	emulate(&emu); | ||||||
| 
 | 
 | ||||||
|  | 	destroy_metadata(&emu); | ||||||
|  | 
 | ||||||
| 	ovni_free_streams(&emu.trace); | 	ovni_free_streams(&emu.trace); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								emu.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								emu.h
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ | |||||||
| 
 | 
 | ||||||
| #include "ovni.h" | #include "ovni.h" | ||||||
| #include "uthash.h" | #include "uthash.h" | ||||||
|  | #include "parson.h" | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| 
 | 
 | ||||||
| /* Debug macros */ | /* Debug macros */ | ||||||
| @ -91,6 +92,8 @@ struct ovni_eproc { | |||||||
| 	size_t nthreads; | 	size_t nthreads; | ||||||
| 	struct ovni_ethread thread[OVNI_MAX_THR]; | 	struct ovni_ethread thread[OVNI_MAX_THR]; | ||||||
| 
 | 
 | ||||||
|  | 	JSON_Value *meta; | ||||||
|  | 
 | ||||||
| 	/* ------ Subsystem specific data --------*/ | 	/* ------ Subsystem specific data --------*/ | ||||||
| 	/* TODO: Use dynamic allocation */ | 	/* TODO: Use dynamic allocation */ | ||||||
| 
 | 
 | ||||||
| @ -189,7 +192,7 @@ struct ovni_emu { | |||||||
| 	/* Total counters */ | 	/* Total counters */ | ||||||
| 	int total_thread; | 	int total_thread; | ||||||
| 	int total_proc; | 	int total_proc; | ||||||
| 	int total_cpu; | 	int total_cpus; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Emulator function declaration */ | /* Emulator function declaration */ | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								emu_ovni.c
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								emu_ovni.c
									
									
									
									
									
								
							| @ -243,74 +243,6 @@ ev_affinity(struct ovni_emu *emu) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void |  | ||||||
| ev_cpu_count(struct ovni_emu *emu) |  | ||||||
| { |  | ||||||
| 	int i, max_ncpus, max_phyid; |  | ||||||
| 	struct ovni_loom *loom; |  | ||||||
| 
 |  | ||||||
| 	loom = emu->cur_loom; |  | ||||||
| 	max_ncpus = emu->cur_ev->payload.i32[0]; |  | ||||||
| 	max_phyid = emu->cur_ev->payload.i32[1]; |  | ||||||
| 
 |  | ||||||
| 	assert(max_ncpus < OVNI_MAX_CPU); |  | ||||||
| 	assert(max_phyid < OVNI_MAX_CPU); |  | ||||||
| 
 |  | ||||||
| 	for(i=0; i<OVNI_MAX_CPU; i++) |  | ||||||
| 	{ |  | ||||||
| 		loom->cpu[i].state = CPU_ST_UNKNOWN; |  | ||||||
| 		loom->cpu[i].i = -1; |  | ||||||
| 		loom->cpu[i].phyid = -1; |  | ||||||
| 		loom->cpu[i].gindex = -1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	loom->ncpus = 0; |  | ||||||
| 	loom->max_ncpus = max_ncpus; |  | ||||||
| 	loom->max_phyid = max_phyid; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| ev_cpu_id(struct ovni_emu *emu) |  | ||||||
| { |  | ||||||
| 	int i, phyid; |  | ||||||
| 	struct ovni_loom *loom; |  | ||||||
| 
 |  | ||||||
| 	loom = emu->cur_loom; |  | ||||||
| 	i = emu->cur_ev->payload.i32[0]; |  | ||||||
| 	phyid = emu->cur_ev->payload.i32[1]; |  | ||||||
| 
 |  | ||||||
| 	/* The logical id must match our index */ |  | ||||||
| 	assert(i == loom->ncpus); |  | ||||||
| 
 |  | ||||||
| 	assert(0 <= phyid && phyid <= loom->max_phyid); |  | ||||||
| 
 |  | ||||||
| 	assert(loom->cpu[i].state == CPU_ST_UNKNOWN); |  | ||||||
| 
 |  | ||||||
| 	loom->cpu[loom->ncpus].state = CPU_ST_READY; |  | ||||||
| 	loom->cpu[loom->ncpus].i = i; |  | ||||||
| 	loom->cpu[loom->ncpus].phyid = phyid; |  | ||||||
| 	loom->cpu[loom->ncpus].gindex = emu->total_cpu++; |  | ||||||
| 
 |  | ||||||
| 	dbg("new cpu %d at phyid=%d\n", i, phyid); |  | ||||||
| 
 |  | ||||||
| 	loom->ncpus++; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| ev_cpu(struct ovni_emu *emu) |  | ||||||
| { |  | ||||||
| 	switch(emu->cur_ev->header.value) |  | ||||||
| 	{ |  | ||||||
| 		case 'n': ev_cpu_count(emu); break; |  | ||||||
| 		case 'i': ev_cpu_id(emu); break; |  | ||||||
| 		default: |  | ||||||
| 			dbg("unknown cpu event value %c\n", |  | ||||||
| 					emu->cur_ev->header.value); |  | ||||||
| 			break; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void | void | ||||||
| hook_pre_ovni(struct ovni_emu *emu) | hook_pre_ovni(struct ovni_emu *emu) | ||||||
| { | { | ||||||
| @ -320,7 +252,6 @@ hook_pre_ovni(struct ovni_emu *emu) | |||||||
| 	{ | 	{ | ||||||
| 		case 'H': ev_thread(emu); break; | 		case 'H': ev_thread(emu); break; | ||||||
| 		case 'A': ev_affinity(emu); break; | 		case 'A': ev_affinity(emu); break; | ||||||
| 		case 'C': ev_cpu(emu); break; |  | ||||||
| 		case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break; | 		case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break; | ||||||
| 		default: | 		default: | ||||||
| 			dbg("unknown ovni event class %c\n", | 			dbg("unknown ovni event class %c\n", | ||||||
| @ -410,7 +341,6 @@ hook_emit_ovni(struct ovni_emu *emu) | |||||||
| 			emit_thread_state(emu); | 			emit_thread_state(emu); | ||||||
| 			/* falltrough */ | 			/* falltrough */ | ||||||
| 		case 'A': | 		case 'A': | ||||||
| 		case 'C': |  | ||||||
| 			emit_thread_count(emu); | 			emit_thread_count(emu); | ||||||
| 			//emit_current_pid(emu);
 | 			//emit_current_pid(emu);
 | ||||||
| 			break; | 			break; | ||||||
|  | |||||||
							
								
								
									
										130
									
								
								ovni.c
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								ovni.c
									
									
									
									
									
								
							| @ -19,6 +19,7 @@ | |||||||
| 
 | 
 | ||||||
| #include "ovni.h" | #include "ovni.h" | ||||||
| #include "ovni_trace.h" | #include "ovni_trace.h" | ||||||
|  | #include "parson.h" | ||||||
| 
 | 
 | ||||||
| #define ENABLE_DEBUG | #define ENABLE_DEBUG | ||||||
| 
 | 
 | ||||||
| @ -93,8 +94,113 @@ create_trace_stream() | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int | ||||||
|  | proc_metadata_init(struct ovni_rproc *proc) | ||||||
|  | { | ||||||
|  | 	JSON_Value *meta; | ||||||
|  | 
 | ||||||
|  | 	proc->meta = json_value_init_object(); | ||||||
|  | 
 | ||||||
|  | 	if(proc->meta == NULL) | ||||||
|  | 	{ | ||||||
|  | 		err("failed to create json object\n"); | ||||||
|  | 		abort(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | proc_metadata_store(struct ovni_rproc *proc) | ||||||
|  | { | ||||||
|  | 	char path[PATH_MAX]; | ||||||
|  |         | ||||||
|  | 	snprintf(path, PATH_MAX, "%s/metadata.json", proc->dir); | ||||||
|  | 
 | ||||||
|  | 	assert(proc->meta != NULL); | ||||||
|  | 
 | ||||||
|  | 	puts(json_serialize_to_string_pretty(proc->meta)); | ||||||
|  | 
 | ||||||
|  | 	if(json_serialize_to_file_pretty(proc->meta, path) != JSONSuccess) | ||||||
|  | 	{ | ||||||
|  | 		err("failed to write proc metadata\n"); | ||||||
|  | 		abort(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | ovni_add_cpu(int index, int phyid) | ||||||
|  | { | ||||||
|  | 	JSON_Array *cpuarray; | ||||||
|  | 	JSON_Object *cpu; | ||||||
|  | 	JSON_Object *meta; | ||||||
|  | 	JSON_Value *valcpu, *valcpuarray; | ||||||
|  | 	int append = 0; | ||||||
|  | 
 | ||||||
|  | 	assert(rproc.ready == 1); | ||||||
|  | 	assert(rproc.meta != NULL); | ||||||
|  | 
 | ||||||
|  | 	meta = json_value_get_object(rproc.meta); | ||||||
|  | 
 | ||||||
|  | 	assert(meta); | ||||||
|  | 
 | ||||||
|  | 	/* Find the CPU array and create it if needed  */ | ||||||
|  | 	cpuarray = json_object_dotget_array(meta, "cpus"); | ||||||
|  | 
 | ||||||
|  | 	if(cpuarray == NULL) | ||||||
|  | 	{ | ||||||
|  | 		valcpuarray = json_value_init_array(); | ||||||
|  | 		assert(valcpuarray); | ||||||
|  | 
 | ||||||
|  | 		cpuarray = json_array(valcpuarray); | ||||||
|  | 		assert(cpuarray); | ||||||
|  | 		append = 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	valcpuarray = json_array_get_wrapping_value(cpuarray); | ||||||
|  | 	assert(valcpuarray); | ||||||
|  | 
 | ||||||
|  | 	valcpu = json_value_init_object(); | ||||||
|  | 	assert(valcpu); | ||||||
|  | 
 | ||||||
|  | 	cpu = json_object(valcpu); | ||||||
|  | 	assert(cpu); | ||||||
|  | 
 | ||||||
|  | 	if(json_object_set_number(cpu, "index", index) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
|  | 	if(json_object_set_number(cpu, "phyid", phyid) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
|  | 	if(json_array_append_value(cpuarray, valcpu) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
|  | 	if(append && json_object_set_value(meta, "cpus", valcpuarray) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
|  | 	//puts(json_serialize_to_string_pretty(rproc.meta));
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | proc_set_app(int appid) | ||||||
|  | { | ||||||
|  | 	JSON_Object *meta; | ||||||
|  | 
 | ||||||
|  | 	assert(rproc.ready == 1); | ||||||
|  | 	assert(rproc.meta != NULL); | ||||||
|  | 
 | ||||||
|  | 	meta = json_value_get_object(rproc.meta); | ||||||
|  | 
 | ||||||
|  | 	assert(meta); | ||||||
|  | 
 | ||||||
|  | 	if(json_object_set_number(meta, "app_id", appid) != 0) | ||||||
|  | 		abort(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int | int | ||||||
| ovni_proc_init(char *loom, int proc) | ovni_proc_init(int app, char *loom, int proc) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| @ -105,6 +211,7 @@ ovni_proc_init(char *loom, int proc) | |||||||
| 	/* FIXME: strcpy is insecure */ | 	/* FIXME: strcpy is insecure */ | ||||||
| 	strcpy(rproc.loom, loom); | 	strcpy(rproc.loom, loom); | ||||||
| 	rproc.proc = proc; | 	rproc.proc = proc; | ||||||
|  | 	rproc.app = app; | ||||||
| 
 | 
 | ||||||
| 	/* By default we use the monotonic clock */ | 	/* By default we use the monotonic clock */ | ||||||
| 	rproc.clockid = CLOCK_MONOTONIC; | 	rproc.clockid = CLOCK_MONOTONIC; | ||||||
| @ -112,8 +219,22 @@ ovni_proc_init(char *loom, int proc) | |||||||
| 	if(create_trace_dirs(OVNI_TRACEDIR, loom, proc)) | 	if(create_trace_dirs(OVNI_TRACEDIR, loom, proc)) | ||||||
| 		abort(); | 		abort(); | ||||||
| 
 | 
 | ||||||
|  | 	if(proc_metadata_init(&rproc) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
| 	rproc.ready = 1; | 	rproc.ready = 1; | ||||||
| 
 | 
 | ||||||
|  | 	proc_set_app(app); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | ovni_proc_fini() | ||||||
|  | { | ||||||
|  | 	if(proc_metadata_store(&rproc) != 0) | ||||||
|  | 		abort(); | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -511,6 +632,11 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir) | |||||||
| 	proc->index = index; | 	proc->index = index; | ||||||
| 	proc->gindex = total_procs++; | 	proc->gindex = total_procs++; | ||||||
| 
 | 
 | ||||||
|  | 	sprintf(path, "%s/%s", procdir, "metadata.json"); | ||||||
|  | 	proc->meta = json_parse_file_with_comments(path); | ||||||
|  | 
 | ||||||
|  | 	assert(proc->meta); | ||||||
|  | 
 | ||||||
| 	if((dir = opendir(procdir)) == NULL) | 	if((dir = opendir(procdir)) == NULL) | ||||||
| 	{ | 	{ | ||||||
| 		fprintf(stderr, "opendir %s failed: %s\n", | 		fprintf(stderr, "opendir %s failed: %s\n", | ||||||
| @ -545,6 +671,8 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir) | |||||||
| 
 | 
 | ||||||
| 	closedir(dir); | 	closedir(dir); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								ovni.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								ovni.h
									
									
									
									
									
								
							| @ -8,6 +8,8 @@ | |||||||
| #include <linux/limits.h> | #include <linux/limits.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| 
 | 
 | ||||||
|  | #include "parson.h" | ||||||
|  | 
 | ||||||
| #define OVNI_MAX_CPU 256 | #define OVNI_MAX_CPU 256 | ||||||
| #define OVNI_MAX_PROC 32 | #define OVNI_MAX_PROC 32 | ||||||
| #define OVNI_MAX_THR 32 | #define OVNI_MAX_THR 32 | ||||||
| @ -93,6 +95,7 @@ struct ovni_rproc { | |||||||
| 	/* Path of the process tracedir */ | 	/* Path of the process tracedir */ | ||||||
| 	char dir[PATH_MAX]; | 	char dir[PATH_MAX]; | ||||||
| 
 | 
 | ||||||
|  | 	int app; | ||||||
| 	int proc; | 	int proc; | ||||||
| 	char loom[HOST_NAME_MAX]; | 	char loom[HOST_NAME_MAX]; | ||||||
| 	int ncpus; | 	int ncpus; | ||||||
| @ -100,9 +103,13 @@ struct ovni_rproc { | |||||||
| 	char procdir[PATH_MAX]; | 	char procdir[PATH_MAX]; | ||||||
| 
 | 
 | ||||||
| 	int ready; | 	int ready; | ||||||
|  | 
 | ||||||
|  | 	JSON_Value *meta; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int ovni_proc_init(char *loom, int proc); | int ovni_proc_init(int app, char *loom, int proc); | ||||||
|  | 
 | ||||||
|  | int ovni_proc_fini(); | ||||||
| 
 | 
 | ||||||
| int ovni_thread_init(pid_t tid); | int ovni_thread_init(pid_t tid); | ||||||
| 
 | 
 | ||||||
| @ -120,6 +127,8 @@ int ovni_ev_size(struct ovni_ev *ev); | |||||||
| 
 | 
 | ||||||
| int ovni_payload_size(struct ovni_ev *ev); | int ovni_payload_size(struct ovni_ev *ev); | ||||||
| 
 | 
 | ||||||
|  | void ovni_add_cpu(int index, int phyid); | ||||||
|  | 
 | ||||||
| /* Set the current clock in the event and queue it */ | /* Set the current clock in the event and queue it */ | ||||||
| void ovni_ev(struct ovni_ev *ev); | void ovni_ev(struct ovni_ev *ev); | ||||||
| void ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize); | void ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize); | ||||||
|  | |||||||
							
								
								
									
										250
									
								
								parson.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								parson.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,250 @@ | |||||||
|  | /*
 | ||||||
|  |  SPDX-License-Identifier: MIT | ||||||
|  | 
 | ||||||
|  |  Parson 1.1.3 ( http://kgabis.github.com/parson/ )
 | ||||||
|  |  Copyright (c) 2012 - 2021 Krzysztof Gabis | ||||||
|  | 
 | ||||||
|  |  Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  in the Software without restriction, including without limitation the rights | ||||||
|  |  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  furnished to do so, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  |  The above copyright notice and this permission notice shall be included in | ||||||
|  |  all copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  |  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  THE SOFTWARE. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef parson_parson_h | ||||||
|  | #define parson_parson_h | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" | ||||||
|  | { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include <stddef.h>   /* size_t */ | ||||||
|  | 
 | ||||||
|  | /* Types and enums */ | ||||||
|  | typedef struct json_object_t JSON_Object; | ||||||
|  | typedef struct json_array_t  JSON_Array; | ||||||
|  | typedef struct json_value_t  JSON_Value; | ||||||
|  | 
 | ||||||
|  | enum json_value_type { | ||||||
|  |     JSONError   = -1, | ||||||
|  |     JSONNull    = 1, | ||||||
|  |     JSONString  = 2, | ||||||
|  |     JSONNumber  = 3, | ||||||
|  |     JSONObject  = 4, | ||||||
|  |     JSONArray   = 5, | ||||||
|  |     JSONBoolean = 6 | ||||||
|  | }; | ||||||
|  | typedef int JSON_Value_Type; | ||||||
|  | 
 | ||||||
|  | enum json_result_t { | ||||||
|  |     JSONSuccess = 0, | ||||||
|  |     JSONFailure = -1 | ||||||
|  | }; | ||||||
|  | typedef int JSON_Status; | ||||||
|  | 
 | ||||||
|  | typedef void * (*JSON_Malloc_Function)(size_t); | ||||||
|  | typedef void   (*JSON_Free_Function)(void *); | ||||||
|  | 
 | ||||||
|  | /* Call only once, before calling any other function from parson API. If not called, malloc and free
 | ||||||
|  |    from stdlib will be used for all allocations */ | ||||||
|  | void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun); | ||||||
|  | 
 | ||||||
|  | /* Sets if slashes should be escaped or not when serializing JSON. By default slashes are escaped.
 | ||||||
|  |  This function sets a global setting and is not thread safe. */ | ||||||
|  | void json_set_escape_slashes(int escape_slashes); | ||||||
|  | 
 | ||||||
|  | /* Parses first JSON value in a file, returns NULL in case of error */ | ||||||
|  | JSON_Value * json_parse_file(const char *filename); | ||||||
|  | 
 | ||||||
|  | /* Parses first JSON value in a file and ignores comments (/ * * / and //),
 | ||||||
|  |    returns NULL in case of error */ | ||||||
|  | JSON_Value * json_parse_file_with_comments(const char *filename); | ||||||
|  | 
 | ||||||
|  | /*  Parses first JSON value in a string, returns NULL in case of error */ | ||||||
|  | JSON_Value * json_parse_string(const char *string); | ||||||
|  | 
 | ||||||
|  | /*  Parses first JSON value in a string and ignores comments (/ * * / and //),
 | ||||||
|  |     returns NULL in case of error */ | ||||||
|  | JSON_Value * json_parse_string_with_comments(const char *string); | ||||||
|  | 
 | ||||||
|  | /* Serialization */ | ||||||
|  | size_t      json_serialization_size(const JSON_Value *value); /* returns 0 on fail */ | ||||||
|  | JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); | ||||||
|  | JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename); | ||||||
|  | char *      json_serialize_to_string(const JSON_Value *value); | ||||||
|  | 
 | ||||||
|  | /* Pretty serialization */ | ||||||
|  | size_t      json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */ | ||||||
|  | JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes); | ||||||
|  | JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename); | ||||||
|  | char *      json_serialize_to_string_pretty(const JSON_Value *value); | ||||||
|  | 
 | ||||||
|  | void        json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */ | ||||||
|  | 
 | ||||||
|  | /* Comparing */ | ||||||
|  | int  json_value_equals(const JSON_Value *a, const JSON_Value *b); | ||||||
|  | 
 | ||||||
|  | /* Validation
 | ||||||
|  |    This is *NOT* JSON Schema. It validates json by checking if object have identically | ||||||
|  |    named fields with matching types. | ||||||
|  |    For example schema {"name":"", "age":0} will validate | ||||||
|  |    {"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"}, | ||||||
|  |    but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}. | ||||||
|  |    In case of arrays, only first value in schema is checked against all values in tested array. | ||||||
|  |    Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays, | ||||||
|  |    null validates values of every type. | ||||||
|  |  */ | ||||||
|  | JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * JSON Object | ||||||
|  |  */ | ||||||
|  | JSON_Value  * json_object_get_value  (const JSON_Object *object, const char *name); | ||||||
|  | const char  * json_object_get_string (const JSON_Object *object, const char *name); | ||||||
|  | size_t        json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ | ||||||
|  | JSON_Object * json_object_get_object (const JSON_Object *object, const char *name); | ||||||
|  | JSON_Array  * json_object_get_array  (const JSON_Object *object, const char *name); | ||||||
|  | double        json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ | ||||||
|  | int           json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ | ||||||
|  | 
 | ||||||
|  | /* dotget functions enable addressing values with dot notation in nested objects,
 | ||||||
|  |  just like in structs or c++/java/c# objects (e.g. objectA.objectB.value). | ||||||
|  |  Because valid names in JSON can contain dots, some values may be inaccessible | ||||||
|  |  this way. */ | ||||||
|  | JSON_Value  * json_object_dotget_value  (const JSON_Object *object, const char *name); | ||||||
|  | const char  * json_object_dotget_string (const JSON_Object *object, const char *name); | ||||||
|  | size_t        json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */ | ||||||
|  | JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name); | ||||||
|  | JSON_Array  * json_object_dotget_array  (const JSON_Object *object, const char *name); | ||||||
|  | double        json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */ | ||||||
|  | int           json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */ | ||||||
|  | 
 | ||||||
|  | /* Functions to get available names */ | ||||||
|  | size_t        json_object_get_count   (const JSON_Object *object); | ||||||
|  | const char  * json_object_get_name    (const JSON_Object *object, size_t index); | ||||||
|  | JSON_Value  * json_object_get_value_at(const JSON_Object *object, size_t index); | ||||||
|  | JSON_Value  * json_object_get_wrapping_value(const JSON_Object *object); | ||||||
|  | 
 | ||||||
|  | /* Functions to check if object has a value with a specific name. Returned value is 1 if object has
 | ||||||
|  |  * a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */ | ||||||
|  | int json_object_has_value        (const JSON_Object *object, const char *name); | ||||||
|  | int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); | ||||||
|  | 
 | ||||||
|  | int json_object_dothas_value        (const JSON_Object *object, const char *name); | ||||||
|  | int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type); | ||||||
|  | 
 | ||||||
|  | /* Creates new name-value pair or frees and replaces old value with a new one.
 | ||||||
|  |  * json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||||
|  | JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value); | ||||||
|  | JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string); | ||||||
|  | JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len);  /* length shouldn't include last null character */ | ||||||
|  | JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number); | ||||||
|  | JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean); | ||||||
|  | JSON_Status json_object_set_null(JSON_Object *object, const char *name); | ||||||
|  | 
 | ||||||
|  | /* Works like dotget functions, but creates whole hierarchy if necessary.
 | ||||||
|  |  * json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||||
|  | JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value); | ||||||
|  | JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string); | ||||||
|  | JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */ | ||||||
|  | JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number); | ||||||
|  | JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean); | ||||||
|  | JSON_Status json_object_dotset_null(JSON_Object *object, const char *name); | ||||||
|  | 
 | ||||||
|  | /* Frees and removes name-value pair */ | ||||||
|  | JSON_Status json_object_remove(JSON_Object *object, const char *name); | ||||||
|  | 
 | ||||||
|  | /* Works like dotget function, but removes name-value pair only on exact match. */ | ||||||
|  | JSON_Status json_object_dotremove(JSON_Object *object, const char *key); | ||||||
|  | 
 | ||||||
|  | /* Removes all name-value pairs in object */ | ||||||
|  | JSON_Status json_object_clear(JSON_Object *object); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *JSON Array | ||||||
|  |  */ | ||||||
|  | JSON_Value  * json_array_get_value  (const JSON_Array *array, size_t index); | ||||||
|  | const char  * json_array_get_string (const JSON_Array *array, size_t index); | ||||||
|  | size_t        json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */ | ||||||
|  | JSON_Object * json_array_get_object (const JSON_Array *array, size_t index); | ||||||
|  | JSON_Array  * json_array_get_array  (const JSON_Array *array, size_t index); | ||||||
|  | double        json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */ | ||||||
|  | int           json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */ | ||||||
|  | size_t        json_array_get_count  (const JSON_Array *array); | ||||||
|  | JSON_Value  * json_array_get_wrapping_value(const JSON_Array *array); | ||||||
|  | 
 | ||||||
|  | /* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
 | ||||||
|  |  * Order of values in array may change during execution.  */ | ||||||
|  | JSON_Status json_array_remove(JSON_Array *array, size_t i); | ||||||
|  | 
 | ||||||
|  | /* Frees and removes from array value at given index and replaces it with given one.
 | ||||||
|  |  * Does nothing and returns JSONFailure if index doesn't exist. | ||||||
|  |  * json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||||
|  | JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value); | ||||||
|  | JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string); | ||||||
|  | JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */ | ||||||
|  | JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number); | ||||||
|  | JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean); | ||||||
|  | JSON_Status json_array_replace_null(JSON_Array *array, size_t i); | ||||||
|  | 
 | ||||||
|  | /* Frees and removes all values from array */ | ||||||
|  | JSON_Status json_array_clear(JSON_Array *array); | ||||||
|  | 
 | ||||||
|  | /* Appends new value at the end of array.
 | ||||||
|  |  * json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */ | ||||||
|  | JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value); | ||||||
|  | JSON_Status json_array_append_string(JSON_Array *array, const char *string); | ||||||
|  | JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len); /* length shouldn't include last null character */ | ||||||
|  | JSON_Status json_array_append_number(JSON_Array *array, double number); | ||||||
|  | JSON_Status json_array_append_boolean(JSON_Array *array, int boolean); | ||||||
|  | JSON_Status json_array_append_null(JSON_Array *array); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *JSON Value | ||||||
|  |  */ | ||||||
|  | JSON_Value * json_value_init_object (void); | ||||||
|  | JSON_Value * json_value_init_array  (void); | ||||||
|  | JSON_Value * json_value_init_string (const char *string); /* copies passed string */ | ||||||
|  | JSON_Value * json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */ | ||||||
|  | JSON_Value * json_value_init_number (double number); | ||||||
|  | JSON_Value * json_value_init_boolean(int boolean); | ||||||
|  | JSON_Value * json_value_init_null   (void); | ||||||
|  | JSON_Value * json_value_deep_copy   (const JSON_Value *value); | ||||||
|  | void         json_value_free        (JSON_Value *value); | ||||||
|  | 
 | ||||||
|  | JSON_Value_Type json_value_get_type   (const JSON_Value *value); | ||||||
|  | JSON_Object *   json_value_get_object (const JSON_Value *value); | ||||||
|  | JSON_Array  *   json_value_get_array  (const JSON_Value *value); | ||||||
|  | const char  *   json_value_get_string (const JSON_Value *value); | ||||||
|  | size_t          json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */ | ||||||
|  | double          json_value_get_number (const JSON_Value *value); | ||||||
|  | int             json_value_get_boolean(const JSON_Value *value); | ||||||
|  | JSON_Value  *   json_value_get_parent (const JSON_Value *value); | ||||||
|  | 
 | ||||||
|  | /* Same as above, but shorter */ | ||||||
|  | JSON_Value_Type json_type   (const JSON_Value *value); | ||||||
|  | JSON_Object *   json_object (const JSON_Value *value); | ||||||
|  | JSON_Array  *   json_array  (const JSON_Value *value); | ||||||
|  | const char  *   json_string (const JSON_Value *value); | ||||||
|  | size_t          json_string_len(const JSON_Value *value); /* doesn't account for last null character */ | ||||||
|  | double          json_number (const JSON_Value *value); | ||||||
|  | int             json_boolean(const JSON_Value *value); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -13,7 +13,7 @@ int main() | |||||||
| 	struct ovni_ev ev = {0}; | 	struct ovni_ev ev = {0}; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	ovni_proc_init(0, 0); | 	ovni_proc_init(0, "test", 0); | ||||||
| 	ovni_thread_init(1); | 	ovni_thread_init(1); | ||||||
| 
 | 
 | ||||||
| 	ovni_ev_set_mcv(&ev, "OB."); | 	ovni_ev_set_mcv(&ev, "OB."); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user