Single header and move lib functions to libovni
This commit is contained in:
		
							parent
							
								
									f8e4c0a0a4
								
							
						
					
					
						commit
						cfc4eb7527
					
				
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,12 +1,17 @@ | ||||
| CFLAGS=-fPIC | ||||
| 
 | ||||
| # Debug CFLAGS
 | ||||
| #CFLAGS+=-fsanitize=address
 | ||||
| #LDFLAGS+=-fsanitize=address
 | ||||
| #CFLAGS+=-g -O0
 | ||||
| 
 | ||||
| # Performance CFLAGS
 | ||||
| CFLAGS+=-O3 | ||||
| CFLAGS+=-fstack-protector-explicit | ||||
| CFLAGS+=-flto | ||||
| 
 | ||||
| BIN=dump libovni.a prvth test_speed | ||||
| BIN=dump libovni.a test_speed ovni2prv | ||||
| #BIN=dump libovni.a prvth test_speed emu
 | ||||
| 
 | ||||
| all: $(BIN) | ||||
| 
 | ||||
| @ -17,5 +22,9 @@ dump: ovni.o dump.o | ||||
| 
 | ||||
| test_speed: test_speed.c ovni.o | ||||
| 
 | ||||
| emu: emu.c ovni.o | ||||
| 
 | ||||
| ovni2prv: ovni2prv.c ovni.o | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f *.o $(BIN) | ||||
|  | ||||
							
								
								
									
										116
									
								
								def.h
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								def.h
									
									
									
									
									
								
							| @ -1,121 +1,5 @@ | ||||
| #ifndef OVNI_DEF_H | ||||
| #define OVNI_DEF_H | ||||
| 
 | ||||
| #define MAX_CPU 256 | ||||
| #define MAX_PROC 32 | ||||
| #define MAX_THR 32 | ||||
| #define MAX_LOOM 4 | ||||
| #define TRACEDIR "ovni" | ||||
| 
 | ||||
| #define MAX_EV (16*1024) /* 16 kev per thread */ | ||||
| //#define MAX_EV (16) /* 16 ev per thread */
 | ||||
| 
 | ||||
| /* ----------------------- common ------------------------ */ | ||||
| 
 | ||||
| enum thread_state { | ||||
| 	ST_THREAD_UNINIT = 0, | ||||
| 	ST_THREAD_INIT = 1 | ||||
| }; | ||||
| 
 | ||||
| struct __attribute__((__packed__)) event { | ||||
| 	uint64_t clock; | ||||
| 	uint8_t fsm; | ||||
| 	uint8_t event; | ||||
| 	uint16_t a; | ||||
| 	uint16_t b; | ||||
| }; | ||||
| 
 | ||||
| /* ----------------------- runtime ------------------------ */ | ||||
| 
 | ||||
| /* State of each thread on runtime */ | ||||
| struct rthread { | ||||
| 	/* Current cpu the thread is running on. Set to -1 if unbounded or
 | ||||
| 	 * unknown */ | ||||
| 	int cpu; | ||||
| 
 | ||||
| 	/* Current thread id */ | ||||
| 	pid_t tid; | ||||
| 
 | ||||
| 	/* Clock value of the events being emitted */ | ||||
| 	uint64_t clockvalue; | ||||
| 
 | ||||
| 	/* Stream trace file descriptor */ | ||||
| 	int streamfd; | ||||
| 
 | ||||
| 	int ready; | ||||
| 
 | ||||
| 	/* Buffer to write events */ | ||||
| 	int nevents; | ||||
| 	struct event events[MAX_EV]; | ||||
| }; | ||||
| 
 | ||||
| /* State of each process on runtime */ | ||||
| struct rproc { | ||||
| 	/* Path of the process tracedir */ | ||||
| 	char dir[PATH_MAX]; | ||||
| 
 | ||||
| 	int proc; | ||||
| 	int loom; | ||||
| 	int ncpus; | ||||
| 	clockid_t clockid; | ||||
| 	char procdir[PATH_MAX]; | ||||
| 
 | ||||
| 	int ready; | ||||
| }; | ||||
| 
 | ||||
| /* ----------------------- emulated ------------------------ */ | ||||
| 
 | ||||
| /* State of each thread on post-process */ | ||||
| struct ethread { | ||||
| 	/* Emulated thread tid */ | ||||
| 	pid_t tid; | ||||
| 
 | ||||
| 	/* Stream file */ | ||||
| 	FILE *f; | ||||
| 
 | ||||
| 	/* Thread stream */ | ||||
| 	struct stream *stream; | ||||
| }; | ||||
| 
 | ||||
| /* State of each process on post-process */ | ||||
| struct eproc { | ||||
| 	/* Monotonic counter for process index */ | ||||
| 	/* TODO: Use pid? */ | ||||
| 	int proc; | ||||
| 
 | ||||
| 	/* Path of the process tracedir */ | ||||
| 	char dir[PATH_MAX]; | ||||
| 
 | ||||
| 	/* Threads */ | ||||
| 	size_t nthreads; | ||||
| 	struct ethread thread[MAX_THR]; | ||||
| }; | ||||
| 
 | ||||
| /* ----------------------- trace ------------------------ */ | ||||
| 
 | ||||
| /* State of each loom on post-process */ | ||||
| struct loom { | ||||
| 	size_t nprocs; | ||||
| 	struct eproc proc[MAX_PROC]; | ||||
| }; | ||||
| 
 | ||||
| struct stream { | ||||
| 	FILE *f; | ||||
| 	int tid; | ||||
| 	int thread; | ||||
| 	int proc; | ||||
| 	int loom; | ||||
| 	int loaded; | ||||
| 	int active; | ||||
| 	struct event last; | ||||
| 	uint64_t lastclock; | ||||
| }; | ||||
| 
 | ||||
| struct trace { | ||||
| 	int nlooms; | ||||
| 	struct loom loom[MAX_LOOM]; | ||||
| 	int nstreams; | ||||
| 	struct stream *stream; | ||||
| }; | ||||
| 
 | ||||
| #endif /* OVNI_DEF_H */ | ||||
|  | ||||
							
								
								
									
										275
									
								
								dump.c
									
									
									
									
									
								
							
							
						
						
									
										275
									
								
								dump.c
									
									
									
									
									
								
							| @ -8,238 +8,76 @@ | ||||
| #include <stdatomic.h> | ||||
| #include <dirent.h>  | ||||
| 
 | ||||
| #include "def.h" | ||||
| #include "ovni.h" | ||||
| 
 | ||||
| int load_proc(struct eproc *proc, char *procdir) | ||||
| { | ||||
| 	struct dirent *dirent; | ||||
| 	DIR *dir; | ||||
| 	char path[PATH_MAX]; | ||||
| 	char *p; | ||||
| 	struct ethread *thread; | ||||
| #define ENABLE_DEBUG | ||||
| 
 | ||||
| 	if((dir = opendir(procdir)) == NULL) | ||||
| #ifdef ENABLE_DEBUG | ||||
| #define dbg(...) fprintf(stderr, __VA_ARGS__); | ||||
| #else | ||||
| #define dbg(...) | ||||
| #endif | ||||
| 
 | ||||
| #define err(...) fprintf(stderr, __VA_ARGS__); | ||||
| 
 | ||||
| 
 | ||||
| static void | ||||
| hexdump(uint8_t *buf, size_t size) | ||||
| { | ||||
| 		fprintf(stderr, "opendir %s failed: %s\n", | ||||
| 				procdir, strerror(errno)); | ||||
| 		return -1; | ||||
| 	int i, j; | ||||
| 
 | ||||
| 	//printf("writing %ld bytes in cpu=%d\n", size, rthread.cpu);
 | ||||
| 
 | ||||
| 	for(i=0; i<size; i+=16) | ||||
| 	{ | ||||
| 		for(j=0; j<16 && i+j < size; j++) | ||||
| 		{ | ||||
| 			fprintf(stderr, "%02x ", buf[i+j]); | ||||
| 		} | ||||
| 
 | ||||
| 	while((dirent = readdir(dir)) != NULL) | ||||
| 	{ | ||||
| 		if(dirent->d_name[0] != 't') | ||||
| 			continue; | ||||
| 		p = strchr(dirent->d_name, '.'); | ||||
| 		if(p == NULL) | ||||
| 			continue; | ||||
| 		p++; | ||||
| 		if(*p == '\0') | ||||
| 		{ | ||||
| 			fprintf(stderr, "bad thread stream file: %s\n", | ||||
| 					dirent->d_name); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		thread = &proc->thread[proc->nthreads++]; | ||||
| 		thread->tid = atoi(p); | ||||
| 
 | ||||
| 		sprintf(path, "%s/%s", procdir, dirent->d_name); | ||||
| 		thread->f = fopen(path, "r"); | ||||
| 
 | ||||
| 		if(thread->f == NULL) | ||||
| 		{ | ||||
| 			fprintf(stderr, "fopen %s failed: %s\n", | ||||
| 					path, strerror(errno)); | ||||
| 			return -1; | ||||
| 		fprintf(stderr, "\n"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	closedir(dir); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int load_loom(struct loom *loom, char *loomdir) | ||||
| { | ||||
| 	int proc; | ||||
| 	char path[PATH_MAX]; | ||||
| 	struct stat st; | ||||
| 
 | ||||
| 	for(proc=0; proc<MAX_PROC; proc++) | ||||
| 	{ | ||||
| 		sprintf(path, "%s/proc.%d", loomdir, proc); | ||||
| 
 | ||||
| 		if(stat(path, &st) != 0) | ||||
| 		{ | ||||
| 			/* No more proc.N directories */ | ||||
| 			if(errno == ENOENT) | ||||
| 				break; | ||||
| 
 | ||||
| 			fprintf(stderr, "cannot stat %s: %s\n", path, | ||||
| 					strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if(!S_ISDIR(st.st_mode)) | ||||
| 		{ | ||||
| 			fprintf(stderr, "not a dir %s\n", path); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if(load_proc(&loom->proc[proc], path)) | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	loom->nprocs = proc; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int load_trace(struct trace *trace, char *tracedir) | ||||
| { | ||||
| 	int loom, nlooms; | ||||
| 	char path[PATH_MAX]; | ||||
| 
 | ||||
| 	/* TODO: For now only one loom */ | ||||
| 	nlooms = 1; | ||||
| 	loom = 0; | ||||
| 
 | ||||
| 	sprintf(path, "%s/loom.%d", tracedir, loom); | ||||
| 
 | ||||
| 	if(load_loom(&trace->loom[loom], path)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	trace->nlooms = nlooms; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Populates the streams in a single array */ | ||||
| int load_streams(struct trace *trace) | ||||
| { | ||||
| 	int i, j, k, s; | ||||
| 	struct loom *loom; | ||||
| 	struct eproc *proc; | ||||
| 	struct ethread *thread; | ||||
| 	struct stream *stream; | ||||
| 
 | ||||
| 	trace->nstreams = 0; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 			for(k=0; k<proc->nthreads; k++) | ||||
| 			{ | ||||
| 				trace->nstreams++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	trace->stream = calloc(trace->nstreams, sizeof(struct stream)); | ||||
| 
 | ||||
| 	if(trace->stream == NULL) | ||||
| 	{ | ||||
| 		perror("calloc"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(stderr, "loaded %d streams\n", trace->nstreams); | ||||
| 
 | ||||
| 	for(s=0, i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 			for(k=0; k<proc->nthreads; k++) | ||||
| 			{ | ||||
| 				thread = &proc->thread[k]; | ||||
| 				stream = &trace->stream[s++]; | ||||
| 
 | ||||
| 				stream->f = thread->f; | ||||
| 				stream->tid = thread->tid; | ||||
| 				stream->proc = j; | ||||
| 				stream->loom = i; | ||||
| 				stream->active = 1; | ||||
| 				stream->lastclock = 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int load_first_event(struct trace *trace) | ||||
| { | ||||
| 	int i; | ||||
| 	struct stream *stream; | ||||
| 	struct event *ev; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nstreams; i++) | ||||
| 	{ | ||||
| 		stream = &trace->stream[i]; | ||||
| 		ev = &stream->last; | ||||
| 		if(fread(ev, sizeof(*ev), 1, stream->f) != 1) | ||||
| 		{ | ||||
| 			fprintf(stderr, "failed to read and event\n"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(stderr, "ev clock %u\n", ev->clock); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void emit(struct stream *stream, struct event *ev) | ||||
| void emit(struct ovni_stream *stream, struct ovni_ev *ev) | ||||
| { | ||||
| 	int64_t delta; | ||||
| 	uint64_t clock; | ||||
| 	int i, payloadsize; | ||||
| 
 | ||||
| 	delta = ev->clock - stream->lastclock; | ||||
| 	//printf("sizeof(*ev) = %d\n", sizeof(*ev));
 | ||||
| 	//hexdump((uint8_t *) ev, sizeof(*ev));
 | ||||
| 
 | ||||
| 	printf("%d.%d.%d %c %c % 6u % 6u % 20lu % 15ld\n", | ||||
| 	clock = ovni_ev_get_clock(ev); | ||||
| 
 | ||||
| 	delta = clock - stream->lastclock; | ||||
| 
 | ||||
| 	printf("%d.%d.%d %c %c %c % 20lu % 15ld ", | ||||
| 			stream->loom, stream->proc, stream->tid, | ||||
| 			ev->fsm, ev->event, ev->a, ev->b, ev->clock, delta); | ||||
| 			ev->model, ev->class, ev->value, clock, delta); | ||||
| 
 | ||||
| 	stream->lastclock = ev->clock; | ||||
| } | ||||
| 
 | ||||
| void load_next_event(struct stream *stream) | ||||
| 	payloadsize = ovni_payload_size(ev); | ||||
| 	for(i=0; i<payloadsize; i++) | ||||
| 	{ | ||||
| 	int i; | ||||
| 	size_t n; | ||||
| 	struct event *ev; | ||||
| 		printf("%d ", ev->payload.payload_u8[i]); | ||||
| 	} | ||||
| 	printf("\n"); | ||||
| 
 | ||||
| 	if(!stream->active) | ||||
| 		return; | ||||
| 
 | ||||
| 	ev = &stream->last; | ||||
| 	if((n = fread(ev, sizeof(*ev), 1, stream->f)) != 1) | ||||
| 	{ | ||||
| 		//fprintf(stderr, "failed to read an event, n=%ld\n", n);
 | ||||
| 		stream->active = 0; | ||||
| 		return; | ||||
| 	stream->lastclock = clock; | ||||
| } | ||||
| 
 | ||||
| 	stream->active = 1; | ||||
| } | ||||
| 
 | ||||
| void dump_events(struct trace *trace) | ||||
| void dump_events(struct ovni_trace *trace) | ||||
| { | ||||
| 	int i, f; | ||||
| 	uint64_t minclock, lastclock; | ||||
| 	struct event *ev; | ||||
| 	struct stream *stream; | ||||
| 	struct ovni_ev *ev; | ||||
| 	struct ovni_stream *stream; | ||||
| 
 | ||||
| 	/* Load events */ | ||||
| 	for(i=0; i<trace->nstreams; i++) | ||||
| 	{ | ||||
| 		stream = &trace->stream[i]; | ||||
| 		load_next_event(stream); | ||||
| 		ovni_load_next_event(stream); | ||||
| 	} | ||||
| 
 | ||||
| 	lastclock = 0; | ||||
| @ -258,10 +96,10 @@ void dump_events(struct trace *trace) | ||||
| 				continue; | ||||
| 
 | ||||
| 			ev = &stream->last; | ||||
| 			if(f < 0 || ev->clock < minclock) | ||||
| 			if(f < 0 || ovni_ev_get_clock(ev) < minclock) | ||||
| 			{ | ||||
| 				f = i; | ||||
| 				minclock = ev->clock; | ||||
| 				minclock = ovni_ev_get_clock(ev); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| @ -272,19 +110,19 @@ void dump_events(struct trace *trace) | ||||
| 
 | ||||
| 		stream = &trace->stream[f]; | ||||
| 
 | ||||
| 		if(lastclock > stream->last.clock) | ||||
| 		if(lastclock > ovni_ev_get_clock(&stream->last)) | ||||
| 		{ | ||||
| 			fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n", | ||||
| 					lastclock, stream->last.clock); | ||||
| 					lastclock, ovni_ev_get_clock(&stream->last)); | ||||
| 		} | ||||
| 
 | ||||
| 		/* Emit current event */ | ||||
| 		emit(stream, &stream->last); | ||||
| 
 | ||||
| 		lastclock = stream->last.clock; | ||||
| 		lastclock = ovni_ev_get_clock(&stream->last); | ||||
| 
 | ||||
| 		/* Read the next one */ | ||||
| 		load_next_event(stream); | ||||
| 		ovni_load_next_event(stream); | ||||
| 
 | ||||
| 		/* Unset the index */ | ||||
| 		f = -1; | ||||
| @ -293,15 +131,10 @@ void dump_events(struct trace *trace) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void free_streams(struct trace *trace) | ||||
| { | ||||
| 	free(trace->stream); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| 	char *tracedir; | ||||
| 	struct trace trace; | ||||
| 	struct ovni_trace trace; | ||||
| 
 | ||||
| 	if(argc != 2) | ||||
| 	{ | ||||
| @ -311,15 +144,15 @@ int main(int argc, char *argv[]) | ||||
| 
 | ||||
| 	tracedir = argv[1]; | ||||
| 
 | ||||
| 	if(load_trace(&trace, tracedir)) | ||||
| 	if(ovni_load_trace(&trace, tracedir)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if(load_streams(&trace)) | ||||
| 	if(ovni_load_streams(&trace)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	dump_events(&trace); | ||||
| 
 | ||||
| 	free_streams(&trace); | ||||
| 	ovni_free_streams(&trace); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										400
									
								
								ovni.c
									
									
									
									
									
								
							
							
						
						
									
										400
									
								
								ovni.c
									
									
									
									
									
								
							| @ -14,18 +14,29 @@ | ||||
| #include <unistd.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include <dirent.h> | ||||
| 
 | ||||
| #include "ovni.h" | ||||
| #include "def.h" | ||||
| 
 | ||||
| #define ENABLE_DEBUG | ||||
| 
 | ||||
| #ifdef ENABLE_DEBUG | ||||
| #define dbg(...) fprintf(stderr, __VA_ARGS__); | ||||
| #else | ||||
| #define dbg(...) | ||||
| #endif | ||||
| 
 | ||||
| #define err(...) fprintf(stderr, __VA_ARGS__); | ||||
| 
 | ||||
| //#define ENABLE_SLOW_CHECKS
 | ||||
| 
 | ||||
| //#define USE_RDTSC
 | ||||
| 
 | ||||
| /* Data per process */ | ||||
| struct rproc rproc = {0}; | ||||
| struct ovni_rproc rproc = {0}; | ||||
| 
 | ||||
| /* Data per thread */ | ||||
| _Thread_local struct rthread rthread = {0}; | ||||
| _Thread_local struct ovni_rthread rthread = {0}; | ||||
| 
 | ||||
| static int | ||||
| create_trace_dirs(char *tracedir, int loom, int proc) | ||||
| @ -102,7 +113,7 @@ ovni_proc_init(int loom, int proc) | ||||
| 	/* By default we use the monotonic clock */ | ||||
| 	rproc.clockid = CLOCK_MONOTONIC; | ||||
| 
 | ||||
| 	if(create_trace_dirs(TRACEDIR, loom, proc)) | ||||
| 	if(create_trace_dirs(OVNI_TRACEDIR, loom, proc)) | ||||
| 		abort(); | ||||
| 
 | ||||
| 	rproc.ready = 1; | ||||
| @ -135,7 +146,14 @@ ovni_thread_init(pid_t tid) | ||||
| 
 | ||||
| 	rthread.tid = tid; | ||||
| 	rthread.cpu = -666; | ||||
| 	rthread.nevents = 0; | ||||
| 	rthread.evlen = 0; | ||||
| 
 | ||||
| 	rthread.evbuf = malloc(OVNI_MAX_EV_BUF); | ||||
| 	if(rthread.evbuf == NULL) | ||||
| 	{ | ||||
| 		perror("malloc"); | ||||
| 		abort(); | ||||
| 	} | ||||
| 
 | ||||
| 	if(create_trace_stream(tid)) | ||||
| 		abort(); | ||||
| @ -145,6 +163,13 @@ ovni_thread_init(pid_t tid) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_thread_free() | ||||
| { | ||||
| 	assert(rthread.ready); | ||||
| 	free(rthread.evbuf); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_thread_isready() | ||||
| { | ||||
| @ -157,25 +182,48 @@ ovni_cpu_set(int cpu) | ||||
| 	rthread.cpu = cpu; | ||||
| } | ||||
| 
 | ||||
| /* Sets the current time so that all subsequent events have the new
 | ||||
|  * timestamp */ | ||||
| void | ||||
| ovni_clock_update() | ||||
| static inline | ||||
| uint64_t rdtsc(void) | ||||
| { | ||||
|     uint32_t lo, hi; | ||||
| 
 | ||||
|     // RDTSC copies contents of 64-bit TSC into EDX:EAX
 | ||||
|     asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); | ||||
|     return (uint64_t) hi << 32 | lo; | ||||
| } | ||||
| 
 | ||||
| uint64_t | ||||
| ovni_get_clock() | ||||
| { | ||||
| 	struct timespec tp; | ||||
| 	uint64_t ns = 1000LL * 1000LL * 1000LL; | ||||
| 	uint64_t raw; | ||||
| 	int ret; | ||||
| 
 | ||||
| #ifdef USE_RDTSC | ||||
| 	raw = rdtsc(); | ||||
| #else | ||||
| 
 | ||||
| 	ret = clock_gettime(rproc.clockid, &tp); | ||||
| 
 | ||||
| #ifdef ENABLE_SLOW_CHECKS | ||||
| 	if(ret) abort(); | ||||
| #endif | ||||
| #endif /* ENABLE_SLOW_CHECKS */ | ||||
| 
 | ||||
| 	raw = tp.tv_sec * ns + tp.tv_nsec; | ||||
| 	//raw = raw >> 6;
 | ||||
| 	rthread.clockvalue = (uint64_t) raw; | ||||
| 
 | ||||
| #endif /* USE_RDTSC */ | ||||
| 
 | ||||
| 	return raw; | ||||
| } | ||||
| 
 | ||||
| /* Sets the current time so that all subsequent events have the new
 | ||||
|  * timestamp */ | ||||
| void | ||||
| ovni_clock_update() | ||||
| { | ||||
| 	rthread.clockvalue = ovni_get_clock(); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -217,61 +265,329 @@ ovni_write(uint8_t *buf, size_t size) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| flush_evbuf() | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	assert(rthread.ready); | ||||
| 	assert(rproc.ready); | ||||
| 
 | ||||
| 	ret = ovni_write(rthread.evbuf, rthread.evlen); | ||||
| 
 | ||||
| 	rthread.evlen = 0; | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| ovni_ev_set_clock(struct ovni_ev *ev) | ||||
| { | ||||
| 	ev->clock_lo = (uint32_t) (rthread.clockvalue & 0xffffffff); | ||||
| 	ev->clock_hi = (uint16_t) ((rthread.clockvalue >> 32) & 0xffff); | ||||
| } | ||||
| 
 | ||||
| uint64_t | ||||
| ovni_ev_get_clock(struct ovni_ev *ev) | ||||
| { | ||||
| 	uint64_t clock; | ||||
| 
 | ||||
| 	clock = ((uint64_t) ev->clock_hi) << 32 | ((uint64_t) ev->clock_lo); | ||||
| 	return clock; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv) | ||||
| { | ||||
| 	ev->model = mcv[0]; | ||||
| 	ev->class = mcv[1]; | ||||
| 	ev->value = mcv[2]; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_thread_flush() | ||||
| ovni_payload_size(struct ovni_ev *ev) | ||||
| { | ||||
| 	return ev->flags & 0x0f; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size) | ||||
| { | ||||
| 	/* Ensure we have room */ | ||||
| 	assert(ovni_payload_size(ev) + size < 16); | ||||
| 
 | ||||
| 	ev->flags = ev->flags & 0xf0 | size & 0x0f; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_ev_size(struct ovni_ev *ev) | ||||
| { | ||||
| 	return sizeof(*ev) - sizeof(ev->payload) + | ||||
| 		ovni_payload_size(ev); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void | ||||
| ovni_ev_add(struct ovni_ev *ev) | ||||
| { | ||||
| 	int size;	 | ||||
| 
 | ||||
| 	ovni_ev_set_clock(ev); | ||||
| 	 | ||||
| 	size = ovni_ev_size(ev); | ||||
| 
 | ||||
| 
 | ||||
| 	memcpy(&rthread.evbuf[rthread.evlen], ev, size); | ||||
| 	rthread.evlen += size; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ovni_ev(struct ovni_ev *ev) | ||||
| { | ||||
| 	ovni_ev_set_clock(ev); | ||||
| 	ovni_ev_add(ev); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_flush() | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	struct event pre={0}, post={0}; | ||||
| 	struct ovni_ev pre={0}, post={0}; | ||||
| 
 | ||||
| 	assert(rthread.ready); | ||||
| 	assert(rproc.ready); | ||||
| 
 | ||||
| 	ovni_clock_update(); | ||||
| 	pre.clock = rthread.clockvalue; | ||||
| 	pre.fsm  = 'F'; | ||||
| 	pre.event = '['; | ||||
| 	ovni_ev_set_clock(&pre); | ||||
| 	ovni_ev_set_mcv(&pre, "OF["); | ||||
| 
 | ||||
| 	ret = ovni_write((uint8_t *) rthread.events, rthread.nevents * sizeof(struct event)); | ||||
| 	rthread.nevents = 0; | ||||
| 	ret = flush_evbuf(); | ||||
| 
 | ||||
| 	ovni_clock_update(); | ||||
| 	post.clock = rthread.clockvalue; | ||||
| 	post.fsm = 'F'; | ||||
| 	post.event = ']'; | ||||
| 	ovni_ev_set_clock(&post); | ||||
| 	ovni_ev_set_mcv(&post, "OF]"); | ||||
| 
 | ||||
| 	/* Also emit the two flush events */ | ||||
| 	memcpy(&rthread.events[rthread.nevents++], &pre, sizeof(struct event));; | ||||
| 	memcpy(&rthread.events[rthread.nevents++], &post, sizeof(struct event));; | ||||
| 	/* Add the two flush events */ | ||||
| 	ovni_ev_add(&pre); | ||||
| 	ovni_ev_add(&post); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int | ||||
| load_proc(struct ovni_eproc *proc, char *procdir) | ||||
| { | ||||
| 	struct dirent *dirent; | ||||
| 	DIR *dir; | ||||
| 	char path[PATH_MAX]; | ||||
| 	char *p; | ||||
| 	struct ovni_ethread *thread; | ||||
| 
 | ||||
| 	if((dir = opendir(procdir)) == NULL) | ||||
| 	{ | ||||
| 		fprintf(stderr, "opendir %s failed: %s\n", | ||||
| 				procdir, strerror(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	while((dirent = readdir(dir)) != NULL) | ||||
| 	{ | ||||
| 		if(dirent->d_name[0] != 't') | ||||
| 			continue; | ||||
| 		p = strchr(dirent->d_name, '.'); | ||||
| 		if(p == NULL) | ||||
| 			continue; | ||||
| 		p++; | ||||
| 		if(*p == '\0') | ||||
| 		{ | ||||
| 			fprintf(stderr, "bad thread stream file: %s\n", | ||||
| 					dirent->d_name); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		thread = &proc->thread[proc->nthreads++]; | ||||
| 		thread->tid = atoi(p); | ||||
| 
 | ||||
| 		sprintf(path, "%s/%s", procdir, dirent->d_name); | ||||
| 		thread->f = fopen(path, "r"); | ||||
| 
 | ||||
| 		if(thread->f == NULL) | ||||
| 		{ | ||||
| 			fprintf(stderr, "fopen %s failed: %s\n", | ||||
| 					path, strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	closedir(dir); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| ovni_ev(uint8_t fsm, uint8_t event, uint16_t a, uint16_t b) | ||||
| load_loom(struct ovni_loom *loom, char *loomdir) | ||||
| { | ||||
| 	struct event *ev; | ||||
| 	int ret = 0; | ||||
| 	int proc; | ||||
| 	char path[PATH_MAX]; | ||||
| 	struct stat st; | ||||
| 
 | ||||
| 	ev = &rthread.events[rthread.nevents++]; | ||||
| 	for(proc=0; proc<OVNI_MAX_PROC; proc++) | ||||
| 	{ | ||||
| 		sprintf(path, "%s/proc.%d", loomdir, proc); | ||||
| 
 | ||||
| 	ev->clock = rthread.clockvalue; | ||||
| 	ev->fsm = fsm; | ||||
| 	ev->event = event; | ||||
| 	ev->a = a; | ||||
| 	ev->b = b; | ||||
| 		if(stat(path, &st) != 0) | ||||
| 		{ | ||||
| 			/* No more proc.N directories */ | ||||
| 			if(errno == ENOENT) | ||||
| 				break; | ||||
| 
 | ||||
| 	/* Flush */ | ||||
| 	if(rthread.nevents >= MAX_EV) | ||||
| 		ret = ovni_thread_flush(); | ||||
| 			fprintf(stderr, "cannot stat %s: %s\n", path, | ||||
| 					strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 	return ret; | ||||
| 		if(!S_ISDIR(st.st_mode)) | ||||
| 		{ | ||||
| 			fprintf(stderr, "not a dir %s\n", path); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if(load_proc(&loom->proc[proc], path)) | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	loom->nprocs = proc; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| ovni_thread_ev(uint8_t fsm, uint8_t event, uint16_t a, uint16_t b) | ||||
| ovni_load_trace(struct ovni_trace *trace, char *tracedir) | ||||
| { | ||||
| 	assert(rthread.ready); | ||||
| 	assert(rproc.ready); | ||||
| 	return ovni_ev(fsm, event, a, b); | ||||
| 	int loom, nlooms; | ||||
| 	char path[PATH_MAX]; | ||||
| 
 | ||||
| 	/* TODO: For now only one loom */ | ||||
| 	nlooms = 1; | ||||
| 	loom = 0; | ||||
| 
 | ||||
| 	sprintf(path, "%s/loom.%d", tracedir, loom); | ||||
| 
 | ||||
| 	if(load_loom(&trace->loom[loom], path)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	trace->nlooms = nlooms; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Populates the streams in a single array */ | ||||
| int | ||||
| ovni_load_streams(struct ovni_trace *trace) | ||||
| { | ||||
| 	int i, j, k, s; | ||||
| 	struct ovni_loom *loom; | ||||
| 	struct ovni_eproc *proc; | ||||
| 	struct ovni_ethread *thread; | ||||
| 	struct ovni_stream *stream; | ||||
| 
 | ||||
| 	trace->nstreams = 0; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 			for(k=0; k<proc->nthreads; k++) | ||||
| 			{ | ||||
| 				trace->nstreams++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	trace->stream = calloc(trace->nstreams, sizeof(struct ovni_stream)); | ||||
| 
 | ||||
| 	if(trace->stream == NULL) | ||||
| 	{ | ||||
| 		perror("calloc"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(stderr, "loaded %d streams\n", trace->nstreams); | ||||
| 
 | ||||
| 	for(s=0, i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 			for(k=0; k<proc->nthreads; k++) | ||||
| 			{ | ||||
| 				thread = &proc->thread[k]; | ||||
| 				stream = &trace->stream[s++]; | ||||
| 
 | ||||
| 				stream->f = thread->f; | ||||
| 				stream->tid = thread->tid; | ||||
| 				stream->thread = k; | ||||
| 				stream->proc = j; | ||||
| 				stream->loom = i; | ||||
| 				stream->active = 1; | ||||
| 				stream->lastclock = 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ovni_free_streams(struct ovni_trace *trace) | ||||
| { | ||||
| 	free(trace->stream); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| ovni_load_next_event(struct ovni_stream *stream) | ||||
| { | ||||
| 	int i; | ||||
| 	size_t n, size; | ||||
| 	struct ovni_ev *ev; | ||||
| 	uint8_t flags; | ||||
| 
 | ||||
| 	if(!stream->active) | ||||
| 		return; | ||||
| 
 | ||||
| 	ev = &stream->last; | ||||
| 	if((n = fread(&ev->flags, sizeof(ev->flags), 1, stream->f)) != 1) | ||||
| 	{ | ||||
| 		dbg("stream is empty\n"); | ||||
| 		stream->active = 0; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	//dbg("flags = %d\n", ev->flags);
 | ||||
| 
 | ||||
| 	size = ovni_ev_size(ev) - sizeof(ev->flags); | ||||
| 	//dbg("ev size = %d\n", size);
 | ||||
| 
 | ||||
| 
 | ||||
| 	/* Clean payload from previous event */ | ||||
| 	memset(&ev->payload, 0, sizeof(ev->payload)); | ||||
| 
 | ||||
| 	if((n = fread(((uint8_t *) ev) + sizeof(ev->flags), 1, size, stream->f)) != size) | ||||
| 	{ | ||||
| 		err("warning: garbage found at the end of the stream\n"); | ||||
| 		stream->active = 0; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	//dbg("loaded next event:\n");
 | ||||
| 	//hexdump((uint8_t *) ev, ovni_ev_size(ev));
 | ||||
| 	//dbg("---------\n");
 | ||||
| 
 | ||||
| 	stream->active = 1; | ||||
| 
 | ||||
| } | ||||
|  | ||||
							
								
								
									
										198
									
								
								ovni.h
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								ovni.h
									
									
									
									
									
								
							| @ -1,22 +1,196 @@ | ||||
| #ifndef OVNI_H | ||||
| #define OVNI_H | ||||
| 
 | ||||
| int | ||||
| ovni_proc_init(int loom, int proc); | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <linux/limits.h> | ||||
| 
 | ||||
| int | ||||
| ovni_thread_init(pid_t tid); | ||||
| #include "ovni.h" | ||||
| 
 | ||||
| int | ||||
| ovni_thread_isready(); | ||||
| #define OVNI_MAX_CPU 256 | ||||
| #define OVNI_MAX_PROC 32 | ||||
| #define OVNI_MAX_THR 32 | ||||
| #define OVNI_MAX_LOOM 4 | ||||
| #define OVNI_TRACEDIR "ovni" | ||||
| 
 | ||||
| void | ||||
| ovni_clock_update(); | ||||
| /* Reserved buffer for event allocation */ | ||||
| #define OVNI_MAX_EV_BUF (16 * 1024LL * 1024LL * 1024LL) | ||||
| 
 | ||||
| int | ||||
| ovni_thread_ev(uint8_t fsm, uint8_t event, uint16_t a, uint16_t b); | ||||
| /* ----------------------- common ------------------------ */ | ||||
| 
 | ||||
| int | ||||
| ovni_thread_flush(); | ||||
| struct __attribute__((__packed__)) ovni_ev { | ||||
| 	/* first 4 bits reserved, last 4 for payload size */ | ||||
| 	uint8_t flags; | ||||
| 	uint8_t model; | ||||
| 	uint8_t class; | ||||
| 	uint8_t value; | ||||
| 	uint16_t clock_hi; | ||||
| 	uint32_t clock_lo; | ||||
| 	union { | ||||
| 		uint8_t payload_u8[16]; | ||||
| 		uint16_t payload_u16[8]; | ||||
| 		uint32_t payload_u32[4]; | ||||
| 		uint64_t payload_u64[2]; | ||||
| 	} payload; | ||||
| }; | ||||
| 
 | ||||
| /* ----------------------- runtime ------------------------ */ | ||||
| 
 | ||||
| /* State of each thread on runtime */ | ||||
| struct ovni_rthread { | ||||
| 	/* Current cpu the thread is running on. Set to -1 if unbounded or
 | ||||
| 	 * unknown */ | ||||
| 	int cpu; | ||||
| 
 | ||||
| 	/* Current thread id */ | ||||
| 	pid_t tid; | ||||
| 
 | ||||
| 	/* Clock value of the events being emitted */ | ||||
| 	uint64_t clockvalue; | ||||
| 
 | ||||
| 	/* Stream trace file descriptor */ | ||||
| 	int streamfd; | ||||
| 
 | ||||
| 	int ready; | ||||
| 
 | ||||
| 	/* The number of bytes filled with events */ | ||||
| 	size_t evlen; | ||||
| 
 | ||||
| 	/* Buffer to write events */ | ||||
| 	uint8_t *evbuf; | ||||
| }; | ||||
| 
 | ||||
| /* State of each process on runtime */ | ||||
| struct ovni_rproc { | ||||
| 	/* Path of the process tracedir */ | ||||
| 	char dir[PATH_MAX]; | ||||
| 
 | ||||
| 	int proc; | ||||
| 	int loom; | ||||
| 	int ncpus; | ||||
| 	clockid_t clockid; | ||||
| 	char procdir[PATH_MAX]; | ||||
| 
 | ||||
| 	int ready; | ||||
| }; | ||||
| 
 | ||||
| /* ----------------------- emulated ------------------------ */ | ||||
| 
 | ||||
| struct ovni_cpu; | ||||
| 
 | ||||
| /* State of each thread on post-process */ | ||||
| struct ovni_ethread { | ||||
| 	/* Emulated thread tid */ | ||||
| 	pid_t tid; | ||||
| 
 | ||||
| 	/* Stream file */ | ||||
| 	FILE *f; | ||||
| 
 | ||||
| 	/* Thread stream */ | ||||
| 	struct ovni_stream *stream; | ||||
| 
 | ||||
| 	/* Current cpu */ | ||||
| 	struct ovni_cpu *cpu; | ||||
| }; | ||||
| 
 | ||||
| /* State of each process on post-process */ | ||||
| struct ovni_eproc { | ||||
| 	/* Monotonic counter for process index */ | ||||
| 	/* TODO: Use pid? */ | ||||
| 	int proc; | ||||
| 
 | ||||
| 	/* Path of the process tracedir */ | ||||
| 	char dir[PATH_MAX]; | ||||
| 
 | ||||
| 	/* Threads */ | ||||
| 	size_t nthreads; | ||||
| 	struct ovni_ethread thread[OVNI_MAX_THR]; | ||||
| }; | ||||
| 
 | ||||
| /* ----------------------- trace ------------------------ */ | ||||
| 
 | ||||
| /* State of each loom on post-process */ | ||||
| struct ovni_loom { | ||||
| 	size_t nprocs; | ||||
| 	struct ovni_eproc proc[OVNI_MAX_PROC]; | ||||
| }; | ||||
| 
 | ||||
| struct ovni_stream { | ||||
| 	FILE *f; | ||||
| 	int tid; | ||||
| 	int thread; | ||||
| 	int proc; | ||||
| 	int loom; | ||||
| 	int loaded; | ||||
| 	int active; | ||||
| 	struct ovni_ev last; | ||||
| 	uint64_t lastclock; | ||||
| }; | ||||
| 
 | ||||
| struct ovni_trace { | ||||
| 	int nlooms; | ||||
| 	struct ovni_loom loom[OVNI_MAX_LOOM]; | ||||
| 	int nstreams; | ||||
| 	struct ovni_stream *stream; | ||||
| }; | ||||
| 
 | ||||
| struct ovni_cpu { | ||||
| 	/* The thread the cpu is currently running */ | ||||
| 	struct ovni_ethread *thread; | ||||
| }; | ||||
| 
 | ||||
| struct ovni_evhead { | ||||
| 	struct ovni_stream *stream; | ||||
| 
 | ||||
| 	struct ovni_loom *loom; | ||||
| 	struct ovni_eproc *proc; | ||||
| 	struct ovni_ethread *thread; | ||||
| }; | ||||
| 
 | ||||
| struct ovni_emulator { | ||||
| 	struct ovni_trace trace; | ||||
| 	struct ovni_cpu cpu[OVNI_MAX_CPU]; | ||||
| 
 | ||||
| 	struct ovni_evhead head; | ||||
| 	uint64_t lastclock; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int ovni_proc_init(int loom, int proc); | ||||
| 
 | ||||
| int ovni_thread_init(pid_t tid); | ||||
| 
 | ||||
| int ovni_thread_isready(); | ||||
| 
 | ||||
| void ovni_clock_update(); | ||||
| 
 | ||||
| void ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv); | ||||
| 
 | ||||
| uint64_t ovni_ev_get_clock(struct ovni_ev *ev); | ||||
| 
 | ||||
| void ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size); | ||||
| 
 | ||||
| int ovni_ev_size(struct ovni_ev *ev); | ||||
| 
 | ||||
| int ovni_payload_size(struct ovni_ev *ev); | ||||
| 
 | ||||
| /* Set the current clock in the event and queue it */ | ||||
| void ovni_ev(struct ovni_ev *ev); | ||||
| 
 | ||||
| int ovni_flush(); | ||||
| 
 | ||||
| int ovni_load_trace(struct ovni_trace *trace, char *tracedir); | ||||
| 
 | ||||
| int ovni_load_streams(struct ovni_trace *trace); | ||||
| 
 | ||||
| void ovni_free_streams(struct ovni_trace *trace); | ||||
| 
 | ||||
| void ovni_load_next_event(struct ovni_stream *stream); | ||||
| 
 | ||||
| #endif /* OVNI_H */ | ||||
|  | ||||
							
								
								
									
										126
									
								
								ovni2prv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								ovni2prv.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <linux/limits.h> | ||||
| #include <errno.h> | ||||
| #include <sys/stat.h> | ||||
| #include <stdatomic.h> | ||||
| #include <dirent.h>  | ||||
| 
 | ||||
| #include "ovni.h" | ||||
| 
 | ||||
| void emit(struct ovni_stream *stream, struct ovni_ev *ev) | ||||
| { | ||||
| 	static uint64_t firstclock = 0; | ||||
| 	int64_t delta; | ||||
| 	int task; | ||||
| 
 | ||||
| 	if(firstclock == 0) | ||||
| 		firstclock = ovni_ev_get_clock(ev); | ||||
| 
 | ||||
| 	delta = ovni_ev_get_clock(ev) - firstclock; | ||||
| 
 | ||||
| 	//#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1)
 | ||||
| 	//2:0:1:1:7:1540663:6400010:1
 | ||||
| 	//2:0:1:1:7:1540663:6400015:1
 | ||||
| 	//2:0:1:1:7:1540663:6400017:0
 | ||||
| 	//2:0:1:1:7:1542091:6400010:1
 | ||||
| 	//2:0:1:1:7:1542091:6400015:1
 | ||||
| 	//2:0:1:1:7:1542091:6400025:1
 | ||||
| 	//2:0:1:1:7:1542091:6400017:0
 | ||||
| 
 | ||||
| 	printf("2:0:1:1:%d:%ld:%d:%d\n", stream->thread+1, delta, ev->class, ev->value); | ||||
| } | ||||
| 
 | ||||
| void dump_events(struct ovni_trace *trace) | ||||
| { | ||||
| 	int i, f; | ||||
| 	uint64_t minclock, lastclock; | ||||
| 	struct ovni_ev *ev; | ||||
| 	struct ovni_stream *stream; | ||||
| 
 | ||||
| 	/* Load events */ | ||||
| 	for(i=0; i<trace->nstreams; i++) | ||||
| 	{ | ||||
| 		stream = &trace->stream[i]; | ||||
| 		ovni_load_next_event(stream); | ||||
| 	} | ||||
| 
 | ||||
| 	lastclock = 0; | ||||
| 
 | ||||
| 	while(1) | ||||
| 	{ | ||||
| 		f = -1; | ||||
| 		minclock = 0; | ||||
| 
 | ||||
| 		/* Select next event based on the clock */ | ||||
| 		for(i=0; i<trace->nstreams; i++) | ||||
| 		{ | ||||
| 			stream = &trace->stream[i]; | ||||
| 
 | ||||
| 			if(!stream->active) | ||||
| 				continue; | ||||
| 
 | ||||
| 			ev = &stream->last; | ||||
| 			if(f < 0 || ovni_ev_get_clock(ev) < minclock) | ||||
| 			{ | ||||
| 				f = i; | ||||
| 				minclock = ovni_ev_get_clock(ev); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		//fprintf(stderr, "f=%d minclock=%u\n", f, minclock);
 | ||||
| 
 | ||||
| 		if(f < 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		stream = &trace->stream[f]; | ||||
| 
 | ||||
| 		if(lastclock >= ovni_ev_get_clock(&stream->last)) | ||||
| 		{ | ||||
| 			fprintf(stderr, "warning: backwards jump in time\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		/* Emit current event */ | ||||
| 		emit(stream, &stream->last); | ||||
| 
 | ||||
| 		lastclock = ovni_ev_get_clock(&stream->last); | ||||
| 
 | ||||
| 		/* Read the next one */ | ||||
| 		ovni_load_next_event(stream); | ||||
| 
 | ||||
| 		/* Unset the index */ | ||||
| 		f = -1; | ||||
| 		minclock = 0; | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| 	char *tracedir; | ||||
| 	struct ovni_trace trace; | ||||
| 
 | ||||
| 	if(argc != 2) | ||||
| 	{ | ||||
| 		fprintf(stderr, "missing tracedir\n"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	tracedir = argv[1]; | ||||
| 
 | ||||
| 	if(ovni_load_trace(&trace, tracedir)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if(ovni_load_streams(&trace)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", trace.nstreams); | ||||
| 
 | ||||
| 	dump_events(&trace); | ||||
| 
 | ||||
| 	ovni_free_streams(&trace); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										336
									
								
								prvth.c
									
									
									
									
									
								
							
							
						
						
									
										336
									
								
								prvth.c
									
									
									
									
									
								
							| @ -1,336 +0,0 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <linux/limits.h> | ||||
| #include <errno.h> | ||||
| #include <sys/stat.h> | ||||
| #include <stdatomic.h> | ||||
| #include <dirent.h>  | ||||
| 
 | ||||
| #include "def.h" | ||||
| 
 | ||||
| int load_proc(struct eproc *proc, char *procdir) | ||||
| { | ||||
| 	struct dirent *dirent; | ||||
| 	DIR *dir; | ||||
| 	char path[PATH_MAX]; | ||||
| 	char *p; | ||||
| 	struct ethread *thread; | ||||
| 
 | ||||
| 	if((dir = opendir(procdir)) == NULL) | ||||
| 	{ | ||||
| 		fprintf(stderr, "opendir %s failed: %s\n", | ||||
| 				procdir, strerror(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	while((dirent = readdir(dir)) != NULL) | ||||
| 	{ | ||||
| 		if(dirent->d_name[0] != 't') | ||||
| 			continue; | ||||
| 		p = strchr(dirent->d_name, '.'); | ||||
| 		if(p == NULL) | ||||
| 			continue; | ||||
| 		p++; | ||||
| 		if(*p == '\0') | ||||
| 		{ | ||||
| 			fprintf(stderr, "bad thread stream file: %s\n", | ||||
| 					dirent->d_name); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		thread = &proc->thread[proc->nthreads++]; | ||||
| 		thread->tid = atoi(p); | ||||
| 
 | ||||
| 		sprintf(path, "%s/%s", procdir, dirent->d_name); | ||||
| 		thread->f = fopen(path, "r"); | ||||
| 
 | ||||
| 		if(thread->f == NULL) | ||||
| 		{ | ||||
| 			fprintf(stderr, "fopen %s failed: %s\n", | ||||
| 					path, strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	closedir(dir); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int load_loom(struct loom *loom, char *loomdir) | ||||
| { | ||||
| 	int proc; | ||||
| 	char path[PATH_MAX]; | ||||
| 	struct stat st; | ||||
| 
 | ||||
| 	for(proc=0; proc<MAX_PROC; proc++) | ||||
| 	{ | ||||
| 		sprintf(path, "%s/proc.%d", loomdir, proc); | ||||
| 
 | ||||
| 		if(stat(path, &st) != 0) | ||||
| 		{ | ||||
| 			/* No more proc.N directories */ | ||||
| 			if(errno == ENOENT) | ||||
| 				break; | ||||
| 
 | ||||
| 			fprintf(stderr, "cannot stat %s: %s\n", path, | ||||
| 					strerror(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if(!S_ISDIR(st.st_mode)) | ||||
| 		{ | ||||
| 			fprintf(stderr, "not a dir %s\n", path); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		if(load_proc(&loom->proc[proc], path)) | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	loom->nprocs = proc; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int load_trace(struct trace *trace, char *tracedir) | ||||
| { | ||||
| 	int loom, nlooms; | ||||
| 	char path[PATH_MAX]; | ||||
| 
 | ||||
| 	/* TODO: For now only one loom */ | ||||
| 	nlooms = 1; | ||||
| 	loom = 0; | ||||
| 
 | ||||
| 	sprintf(path, "%s/loom.%d", tracedir, loom); | ||||
| 
 | ||||
| 	if(load_loom(&trace->loom[loom], path)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	trace->nlooms = nlooms; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Populates the streams in a single array */ | ||||
| int load_streams(struct trace *trace) | ||||
| { | ||||
| 	int i, j, k, s; | ||||
| 	struct loom *loom; | ||||
| 	struct eproc *proc; | ||||
| 	struct ethread *thread; | ||||
| 	struct stream *stream; | ||||
| 
 | ||||
| 	trace->nstreams = 0; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 			for(k=0; k<proc->nthreads; k++) | ||||
| 			{ | ||||
| 				trace->nstreams++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	trace->stream = calloc(trace->nstreams, sizeof(struct stream)); | ||||
| 
 | ||||
| 	if(trace->stream == NULL) | ||||
| 	{ | ||||
| 		perror("calloc"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(stderr, "loaded %d streams\n", trace->nstreams); | ||||
| 
 | ||||
| 	for(s=0, i=0; i<trace->nlooms; i++) | ||||
| 	{ | ||||
| 		loom = &trace->loom[i]; | ||||
| 		for(j=0; j<loom->nprocs; j++) | ||||
| 		{ | ||||
| 			proc = &loom->proc[j]; | ||||
| 			for(k=0; k<proc->nthreads; k++) | ||||
| 			{ | ||||
| 				thread = &proc->thread[k]; | ||||
| 				stream = &trace->stream[s++]; | ||||
| 
 | ||||
| 				stream->f = thread->f; | ||||
| 				stream->tid = thread->tid; | ||||
| 				stream->thread = k; | ||||
| 				stream->proc = j; | ||||
| 				stream->loom = i; | ||||
| 				stream->active = 1; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int load_first_event(struct trace *trace) | ||||
| { | ||||
| 	int i; | ||||
| 	struct stream *stream; | ||||
| 	struct event *ev; | ||||
| 
 | ||||
| 	for(i=0; i<trace->nstreams; i++) | ||||
| 	{ | ||||
| 		stream = &trace->stream[i]; | ||||
| 		ev = &stream->last; | ||||
| 		if(fread(ev, sizeof(*ev), 1, stream->f) != 1) | ||||
| 		{ | ||||
| 			fprintf(stderr, "failed to read and event\n"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(stderr, "ev clock %u\n", ev->clock); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void emit(struct stream *stream, struct event *ev) | ||||
| { | ||||
| 	static uint64_t firstclock = 0; | ||||
| 	int64_t delta; | ||||
| 	int task; | ||||
| 
 | ||||
| 	if(firstclock == 0) | ||||
| 		firstclock = ev->clock; | ||||
| 
 | ||||
| 	delta = ev->clock - firstclock; | ||||
| 
 | ||||
| 	//#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1)
 | ||||
| 	//2:0:1:1:7:1540663:6400010:1
 | ||||
| 	//2:0:1:1:7:1540663:6400015:1
 | ||||
| 	//2:0:1:1:7:1540663:6400017:0
 | ||||
| 	//2:0:1:1:7:1542091:6400010:1
 | ||||
| 	//2:0:1:1:7:1542091:6400015:1
 | ||||
| 	//2:0:1:1:7:1542091:6400025:1
 | ||||
| 	//2:0:1:1:7:1542091:6400017:0
 | ||||
| 
 | ||||
| 	printf("2:0:1:1:%d:%ld:%d:%d\n", stream->thread+1, delta, ev->fsm, ev->event); | ||||
| } | ||||
| 
 | ||||
| void load_next_event(struct stream *stream) | ||||
| { | ||||
| 	int i; | ||||
| 	size_t n; | ||||
| 	struct event *ev; | ||||
| 
 | ||||
| 	if(!stream->active) | ||||
| 		return; | ||||
| 
 | ||||
| 	ev = &stream->last; | ||||
| 	if((n = fread(ev, sizeof(*ev), 1, stream->f)) != 1) | ||||
| 	{ | ||||
| 		//fprintf(stderr, "failed to read an event, n=%ld\n", n);
 | ||||
| 		stream->active = 0; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	stream->active = 1; | ||||
| } | ||||
| 
 | ||||
| void dump_events(struct trace *trace) | ||||
| { | ||||
| 	int i, f; | ||||
| 	uint64_t minclock, lastclock; | ||||
| 	struct event *ev; | ||||
| 	struct stream *stream; | ||||
| 
 | ||||
| 	/* Load events */ | ||||
| 	for(i=0; i<trace->nstreams; i++) | ||||
| 	{ | ||||
| 		stream = &trace->stream[i]; | ||||
| 		load_next_event(stream); | ||||
| 	} | ||||
| 
 | ||||
| 	lastclock = 0; | ||||
| 
 | ||||
| 	while(1) | ||||
| 	{ | ||||
| 		f = -1; | ||||
| 		minclock = 0; | ||||
| 
 | ||||
| 		/* Select next event based on the clock */ | ||||
| 		for(i=0; i<trace->nstreams; i++) | ||||
| 		{ | ||||
| 			stream = &trace->stream[i]; | ||||
| 
 | ||||
| 			if(!stream->active) | ||||
| 				continue; | ||||
| 
 | ||||
| 			ev = &stream->last; | ||||
| 			if(f < 0 || ev->clock < minclock) | ||||
| 			{ | ||||
| 				f = i; | ||||
| 				minclock = ev->clock; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		//fprintf(stderr, "f=%d minclock=%u\n", f, minclock);
 | ||||
| 
 | ||||
| 		if(f < 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		stream = &trace->stream[f]; | ||||
| 
 | ||||
| 		if(lastclock >= stream->last.clock) | ||||
| 		{ | ||||
| 			fprintf(stderr, "warning: backwards jump in time\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		/* Emit current event */ | ||||
| 		emit(stream, &stream->last); | ||||
| 
 | ||||
| 		lastclock = stream->last.clock; | ||||
| 
 | ||||
| 		/* Read the next one */ | ||||
| 		load_next_event(stream); | ||||
| 
 | ||||
| 		/* Unset the index */ | ||||
| 		f = -1; | ||||
| 		minclock = 0; | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void free_streams(struct trace *trace) | ||||
| { | ||||
| 	free(trace->stream); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| 	char *tracedir; | ||||
| 	struct trace trace; | ||||
| 
 | ||||
| 	if(argc != 2) | ||||
| 	{ | ||||
| 		fprintf(stderr, "missing tracedir\n"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	tracedir = argv[1]; | ||||
| 
 | ||||
| 	if(load_trace(&trace, tracedir)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if(load_streams(&trace)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", trace.nstreams); | ||||
| 
 | ||||
| 	dump_events(&trace); | ||||
| 
 | ||||
| 	free_streams(&trace); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										10
									
								
								test_speed.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								test_speed.c
									
									
									
									
									
								
							| @ -2,25 +2,29 @@ | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <linux/limits.h> | ||||
| 
 | ||||
| #include "ovni.h" | ||||
| 
 | ||||
| #define N 1000 | ||||
| #define N 100000 | ||||
| 
 | ||||
| int main() | ||||
| { | ||||
| 	struct ovni_ev ev = {0}; | ||||
| 	int i; | ||||
| 
 | ||||
| 	ovni_proc_init(0, 0); | ||||
| 	ovni_thread_init(1); | ||||
| 
 | ||||
| 	ovni_ev_set_mcv(&ev, "OB."); | ||||
| 
 | ||||
| 	for(i=0; i<N; i++) | ||||
| 	{ | ||||
| 		ovni_clock_update(); | ||||
| 		ovni_thread_ev('B', '.', 0, 0); | ||||
| 		ovni_ev(&ev); | ||||
| 	} | ||||
| 
 | ||||
| 	ovni_thread_flush(); | ||||
| 	ovni_flush(); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user