628 lines · 10.3 KB · C
RawDownload
/*   timeit - an in-memory timestamp utility library   Copyright (C) 2011, IBM Corporation,  		John (EBo) David (ebo@users.sourceforge.net)   Notes:      optionally uses atexit to automatically dump timestamps */ enum{	TIMIT_DEFAULT=0x0,	TIMIT_FLOAT=0x1,	TIMIT_DT=0x2,	TIMIT_SILENT=0x4,	TIMIT_END,	TIMIT_USED=0x8,}; typedef struct Tentry Tentry;struct Tentry {	uvlong stamp;	double dt;	long pid;	char *tag;	int flag;}; typedef struct TimeIt TimeIt;struct TimeIt {	int max_entries;	int n;	long last_pid;	Tentry *ent;	TimeIt *next;	TimeIt *prev;}; static TimeIt *root = nil;static TimeIt *current = nil;static max_entries = 1024;static int timeit_fd = 1;static int default_flag=0;static int silent=0; static int use_cycles=0;static uvlong sec_cnv=1000000000LL;  static voidtslice(uvlong *t){	if(use_cycles){		sec_cnv = 850000000LL;		cycles(t);	}else{		sec_cnv = 1000000000LL;		*t = nsec();	}} voidtimeit_setcycles(int flag){	use_cycles=flag;} doubletimeit_cnv_sec(uvlong t){	double dt = ((double) t);	double ct = ((double) sec_cnv); 	return dt/ct;} static TimeIt *timeit_new(int num); voidtimeit_setsilent(int flag){	silent=flag;	} inttimeit_settype(int flag){	if(flag>=TIMIT_DEFAULT && flag<TIMIT_END)		default_flag=flag; 	return default_flag;} inttimeit_setmax(int num){	if(num >= 0)		return -1; 	max_entries = num; 	return 0;} voidtimeit_setfd(int fd){	timeit_fd = fd;} voidtimeit_setout(char *outfile){	if(root==nil) return;	if(outfile==nil) return; 	int fd = create(outfile, OWRITE, 0666);	if (fd > 0)		timeit_fd = fd;	else		DPRINT(DERR, "*ERROR*: timeit_setout could not open output file (%s)\n", outfile);} QLock timelck; inttimit_ent_cmp(void *v1, void *v2){	Tentry *e1 = (Tentry*) v1;	Tentry *e2 = (Tentry*) v2; //if((e1->pid-e2->pid) < 0)//	print("(swap) %d %d\n", e1->pid,e2->pid); 		return (int)e1->pid-e2->pid;//	else//		return (int)e1->stamp-e2->stamp;} voidtimeit_dump(void){	int i;	TimeIt *t;	if(silent) return;	if(root==nil) return; 	qlock(&timelck);	for(t=root; t!=nil; t=t->next){		for (i=0; i<t->n; i++){			if(t->ent[i].flag & TIMIT_USED)				continue;			if(t->ent[i].pid != t->last_pid){				fprint(timeit_fd, "\n");				t->last_pid = t->ent[i].pid;			}			if(t->ent[i].flag & (TIMIT_FLOAT|TIMIT_DT)){				fprint(timeit_fd, "%p %lud %f %s\n",				       root, t->ent[i].pid, t->ent[i].dt, t->ent[i].tag);			}else{				fprint(timeit_fd, "%p %lud %llud %s\n",				       root, t->ent[i].pid, t->ent[i].stamp, t->ent[i].tag);			}			t->ent[i].flag |= TIMIT_USED;		}	}	qunlock(&timelck);} voidtimeit_dump_ordered(void){	TimeIt *t;	if(silent) return;	if(root==nil) return; 	qlock(&timelck);	for(t=root; t!=nil; t=t->next)		qsort(t->ent, t->n -1, sizeof(Tentry), timit_ent_cmp); 	qunlock(&timelck); 	timeit_dump();	} static Tentry *add_stamp(vlong s, char *tag, int pid){	Tentry *e; 	if(root==nil || current==nil) return nil;	qlock(&timelck);	e = &current->ent[current->n];	e->stamp = s;	e->dt = 0.0;	e->pid = pid;	e->tag = tag;	e->flag = default_flag; 	/* ensure that the next one is always valid */	current->n++;	if(current->n >= max_entries){		current->next = timeit_new(max_entries);		current->next->prev = current;	}	qunlock(&timelck); 	return e;} Tentry *stamp(char *tag){	uvlong ticks;	tslice(&ticks); 	if(root==nil) return nil;	return add_stamp(ticks, tag, getpid());} vlongtimeit_ent_dt(Tentry *e1, Tentry *e2){	if(root==nil) return 0;	if(e1==nil || e2==nil)		return 0;	if(e2->stamp > e1->stamp)		return e2->stamp - e1->stamp;	else		return e1->stamp - e2->stamp;} Tentry *timeit_index(int num){	TimeIt *t=root;	Tentry *e;	int i; 	if(root==nil) return nil;	if(num < 0)		goto err; 	qlock(&timelck);	for(i=0; num >= 0; num--, i--){		if(i >= t->n){			t = t->next;			if(t == nil)				goto err;			i = 0;			if(t->n == 0)				goto err;		}		if(num==0)			break;	} 	e = &t->ent[i];	qunlock(&timelck); 	return e; err:	qunlock(&timelck);	DPRINT(DERR, "*ERROR*: timeit_index attemped to access non existant element\n");	stamp("*ERROR*: timeit_index attemped to access non existant element");	return nil;} Tentry *timeit_find(char *tag, int pid){	TimeIt *t=root;	int i; 	if(root==nil) return nil;	if(tag==nil)		goto err; 	qlock(&timelck);	for(i=t->n-1; i>=0; i--)		if(t->ent[i].pid == pid)			if(!strcmp(t->ent[i].tag, tag)){				qunlock(&timelck);				return  &t->ent[i];			}	qunlock(&timelck); err:	DPRINT(DERR, "*ERROR*: timeit_find tag=(%s) not found\n", 	       (tag==nil)?"<nil>":tag);	stamp("*ERROR*: timeit_find tag not found");	return nil;} /*Tentry *timeit_find(char *tag){	TimeIt *t=root;	int i; 	if(tag==nil)		goto err; 	for(i=t->n-1; i>=0; i--)		if(!strcmp(t->ent[i].tag, tag))			return  &t->ent[i]; err:	DPRINT(DERR, "*ERROR*: timeit_find tag=(%s) not found\n", 	       (tag==nil)?"<nil>":tag);	stamp("*ERROR*: timeit_find tag not found");	return nil;}*/ Tentry *timeit_last(void){	if(root==nil) return nil;	if(current==nil || current->n==0)		goto err; 	return &current->ent[current->n -1]; err:	DPRINT(DERR, "*ERROR*: timeit_last attemped to access non existant element\n");	stamp("*ERROR*: timeit_last attemped to access non existant element");	return nil;} inttimeit_last_index(void){	int i, pid=getpid(); 	if(root==nil) return -1;	if(current==nil || current->n==0)		goto err; 	for(i=current->n-1; i>=0; i--)		if(current->ent[i].pid == pid)			return i; err:	DPRINT(DERR, "*ERROR*: timeit_last_pid attemped to access non existant element\n");	stamp("*ERROR*: timeit_last_pid attemped to access non existant element");	return -1;} Tentry *timeit_last_pid(void){	if(root==nil) return nil;	int i=timeit_last_index();	if(current==nil || current->n==0 || i<0)		goto err; 	return &current->ent[i]; err:	DPRINT(DERR, "*ERROR*: timeit_last_pid attemped to access non existant element\n");	stamp("*ERROR*: timeit_last_pid attemped to access non existant element");	return nil;} Tentry *timeit_offset(Tentry *s, int num){	TimeIt *t;	Tentry *e;	int b, p;	int ds;	int pid; 	if(root==nil) return nil;	if(s == nil)		return nil;	if(num == 0)		return s; 	pid = s->pid; 	// find the element in the list	qlock(&timelck);	for(b=0,t=root; t!=nil; b++){		if(b >= t->n){			t = t->next;			b = 0;			if(t==nil || t->n==0)				goto err;		}		if(&t->ent[b] == s)			break;	} 	ds = -1;	if(num<0)		ds = 1; 	for(p=b-ds,num+=ds; num!=0; p-=ds){		if(p >= t->n){			t = t->next;			if(t == nil)				goto err;			if(t->n == 0)				goto err;			p = 0;		}		if(p < 0){			t = t->prev;			if(t == nil)				goto err;			if(t->n == 0)				goto err;			p = t->n -1;		}		if(pid == t->ent[p].pid)			num+=ds;		if(num==0)			break;	} 	// termination sanity check	if(p>=t->n || p<0){		goto err;	} 	e = &t->ent[p];	qunlock(&timelck); 	return e; err:	qunlock(&timelck);	DPRINT(DERR, "*ERROR*: timeit_offset attemped to access non existant element\n");	stamp("*ERROR*: timeit_offset attemped to access non existant element");	return nil;	} voidtimeit_dt(int num, char *tag){	Tentry *e1, *e2; 	if(root==nil) return; 	e1 = timeit_last_pid();	e2 = timeit_offset(e1, num);	if(e1==nil || e2==nil)		goto err; 	Tentry *e = stamp(tag); 	e->dt = (double) timeit_ent_dt(e1,e2);	e->flag = TIMIT_DT; 	return;  err:	DPRINT(DERR, "*ERROR*: timeit_dt attemped to access non existant element\n");	stamp("*ERROR*: timeit_dt attemped to access non existant element");	return;} voidtimeit_dt_last_sec(char *tag){	int i; 	if(root==nil) return; 	i = timeit_last_index();	if(i<0)		goto err; 	Tentry *e = stamp(tag); 	e->dt = timeit_cnv_sec(e->stamp - current->ent[i].stamp);	e->flag = TIMIT_FLOAT | TIMIT_DT;  	return;  err:	DPRINT(DERR, "*ERROR*: timeit_dt attemped to access non existant element\n");	stamp("*ERROR*: timeit_dt attemped to access non existant element");	return;}   static voidtimeit_atexit(void){	timeit_dump_ordered();}

Lines 1–500 of 628.