V10/cmd/trace/trace1.c

Compare this file to the similar file:
Show the results in this format:

#include <stdio.h>
#include <signal.h>
#include "trace.h"
#include "trace.d"

#if 0
#define debug(s1, s2, s3, s4, s5)	printf(s1, s2, s3, s4, s5)
#else
#define debug(s1, s2, s3, s4, s5)	
#endif

 struct TBL       *tbl;
 struct LBT	  *lbt;
 struct MBOX      *mbox;
 struct MNAME     *fullname;

 struct REVPOL **expr;
 struct PROCSTACK **procstack;

 struct VARPARS	  *procpars;
 struct TBLPARS	  *tblpars;
 struct LOCVARS   *tblvars;
 struct TBLPARS   *tablpars;

 struct QUEUE     **starter, **head, **tail;
 struct QUEUE     *s_first, *s_last;

/*
 * reftasks : mapping of logic reftask id to table number
 * processes: mapping of logic process id to table number
 * basics   : initial process table
 */

 int *state, *reftasks, *processes, *basics;
 int *qsize, *globvars, *inits, *xob;

 /*
  * the state-set of an assertion table is mapped
  * onto the global variables (to simplify state checking)
  * the first global that is an element from the state set
  * is given by integer `abase'
  */

 int abase = -1;		/* base of assertion table state set */
 int ebase = -1;		/* base of error table state set */
 int assertbl = -1;		/* table used for assertion checking */
 int errortbl = -1;		/* table used for assertion checking */
 int msgbase = -1, maxlevel = -1, maxreached = -1;

 int maxcol=0, nrtbl=0, nrqs=0, nrprocs=0, nrrefs=0;
 int nrinit=0, nrvars=0, nexpr=0, nrmesgs=0, linecode=0;
 int QMAX=2;

 char qoverride = 0;
 char noshortcut = 0;		/* disable timeout heuristics */
 char prbyq = 2;		/* controls output format     */
 char blast = 0;		/* blast search mode   */
 char qandirty = 0;		/* scatter search mode */
 char lockplus = 0;		/* report both buffer locks and loops */
 char firstlock = 0;		/* stop at first buffer lock found    */
 char maxxed = 0;		/* bound on search depth  */
 char prefix = 0;		/* print all prefixes too */
 char timedd = 0;		/* verbose mode    */
 char completed = 0;		/* not interrupted */
 char muststore = 0;		/* must perform loop check and store state */
 char sensible = 0;		/* default mode: try a sensible partial search */

 double zapper = (double) 30000;
 double tryswiff=0, noswiff=0, cannot=0;

 long zapped = 0, locksf = 0, loopsf = 0;
 long normf = 0, callno = 0;

 int *effnrstates;	/* effective nr of table states per process */
 int aperiod = 120;

 char *topofmem, *sbrk(), *Smalloc();
 char fname[64];

 FILE *mb;

 extern double iseen, ireseen, painful, kurshan;

onalarm()
{	float t;
	struct { long u, p, cu, cp; } tim;

	times(&tim);
	t = (float) (tim.u  + tim.p)/ (float) 60.0;

	if (++callno%10 == 1)
	{	fprintf(stderr, " seconds  depth  states   zapped");
		fprintf(stderr, "  prefix terms loops locks   memory\n");
	}
	fprintf(stderr, "%8.2f %6d ", t, maxreached);
	fprintf(stderr, "%6g %8ld %7g ", iseen+ireseen, zapped, kurshan);
	fprintf(stderr, "%5ld %5ld ", normf, loopsf);
	fprintf(stderr, "%5ld %8u\n", locksf, sbrk(0) - topofmem);
	signal(SIGALRM, onalarm);
	alarm(aperiod);
}

postlude()
{	struct { long u, p, cu, cp; } tim;
	extern double COUNT;
	float u, s;

	fflush(stdout);
	if (!completed)
		fprintf(stderr, "trace: interrupted\n");

	if (timedd)
	{	times(&tim);
		u = (float) tim.u / (float) 60.0;
		s = (float) tim.p / (float) 60.0;

		fprintf(stderr, "\ttime: %.2fs u + ", u);
		fprintf(stderr, "%.2fs sys = %.2fs\n\n", s, u+s);
		fprintf(stderr, "\t%g states cached, ", iseen+ireseen);
		fprintf(stderr, "%ld states zapped\n",  zapped);
		fprintf(stderr, "\tsearch depth reached: %d; ", maxreached);
		fprintf(stderr, "memory used: %u\n\t", sbrk(0) - topofmem );
		fprintf(stderr, "%ld deadlocks, ", locksf);
		fprintf(stderr, "%ld loops, ", loopsf);
		fprintf(stderr, "%ld terminating executions, and ", normf);
		fprintf(stderr, "%g prefixes\n", kurshan);
		fprintf(stderr, "\t%g edges traversed", COUNT);
		fprintf(stderr, ", %g states analyzed twice\n", painful);
		if (cannot > 0)
		fprintf(stderr, "\t%g cache replacements failed\n", cannot);
		if (tryswiff > 0)
		fprintf(stderr, "\ttryswiff  %5g noswiff  %g\n",tryswiff,noswiff);
	}
	exit(completed == 0);
}

wisdom()
{
	if (sensible)
	{	timedd = firstlock = qandirty = 1;
		fprintf(stderr, "default search: ");
		fprintf(stderr, "-vxjqm %d %d\n", QMAX, maxlevel);
	} else
	{	fprintf(stderr, "%s search, ", (blast) ? "blast" :
					(qandirty) ? "scatter" : "exhaustive");
		fprintf(stderr, "depth bound %d\n", maxlevel);
	}
}

main(argc, argv)
	char **argv;
{
	char c;
	int  i=1, j, base=2;

	strcpy(fname, "pret.out");
	if (argc > 1 && argv[1][0] == '-')
	{	base++;
		while ((c = argv[1][i++]) != '\0')
			switch (c) {
			case 'a': prefix = 1;	break;
			case 'b': blast = qandirty = 1;	break;
			case 'c': if (argc >= base)
				  {	sscanf(argv[base-1], "%d", &j);
					base++;
				  } else
				  	usage("missing argument for `c' flag");
				  firstlock = lockplus = timedd = 1;
				  switch (j) {
					case 0: blast = qandirty = 1; break;
					case 1: maxxed = 3;	/* fall through */
					case 2: qandirty = 1; break;
					case 3: maxxed = 2; break; /* 1{ x effnr */
					case 4: maxxed = 3;	   /* 2 x effnr  */
					case 5: break;		   /* 8 x effnr  */
					default: usage("unknown validation class");
				  }
				  break;
			case 'f': prbyq = 1; break;
			case 'F': prbyq = 0; break;
			case 'j': firstlock = 1; break;
			case 'k': if (argc >= base)
				  {	sscanf(argv[base-1], "%d", &j);
					zapper = (double) (j * 1000);
					base++;
				  } else
				  	usage("missing argument for `k' flag");
				  break;
			case 'l': lockplus = 1;	break;
			case 'm': maxxed = 1;
				  if (argc >= base)
				  {	sscanf(argv[base-1], "%d", &maxlevel);
					base++;
				  } else
				  	usage("missing argument for `m' flag");
				  break;
			case 'n': noshortcut = 1; break;
			case 'q': qoverride = 1;
				  if (argc >= base)
				  {	sscanf(argv[base-1], "%d", &QMAX);
					base++;
				  } else
				  	usage("missing argument for `q' flag");
				  break;
			case 'r': if (argc >= base)
				  {	sscanf(argv[base-1], "%d", &j);
					base++;
				  } else
				  	usage("missing argument for `r' flag");
				  signal(SIGALRM, postlude);
				  aperiod = 0;
				  alarm(j*60);
				  break;
			case 'R': if (argc >= base)
				  {	sscanf(argv[base-1], "%d", &j);
					base++;
				  } else
				  	usage("missing argument for `R' flag");
				  aperiod = j*60;
				  break;
			case 's': setup(); showtables(timedd); exit(0);
				  break;
			case 'v': timedd = 1;	break;
			case 'x': qandirty = 1; break;
			default : usage("unknown option");
			}
	} else
	{	sensible = qoverride = 1;
	}

	if (argc >= base-1)
		sscanf(argv[base-1], "%s", fname);
	else
		strcpy(fname, "pret.out");

	setup();
	init();
	topofmem = sbrk(0);

	if (maxxed != 1)
	{
		for (j = maxlevel = 0; j < nrprocs; j++)
			maxlevel += effnrstates[processes[j]];

		switch (maxxed) {
			case 3: maxlevel *= 2; break;
			case 2: maxlevel = (3*maxlevel)/2; break;
			case 0: if (sensible)
					maxlevel *= 2;
				else
					maxlevel *= 8;	/* avoid pathetic cases */
				break;
			default: whoops("cannot happen - main");
		}
		maxxed = 1;
	}
	if (aperiod > 0)
	{	signal(SIGALRM, onalarm);
		alarm(aperiod);
	} signal(SIGINT, postlude);

	wisdom();
	muststore = 1;	/* must always store initial state */
	FSE(0);
	completed = 1;
	postlude();
}

setup()
{
	if ((mb = fopen(fname, "r")) == NULL)
	{	fprintf(stderr, "cannot find `%s'\n", fname);
		exit(1);
	}

	getglobals();
	gettables();
	getexprs();

	fclose(mb);
}

getglobals()
{ register int i, j;
  int a, b, c, x, y, z;

	if (fscanf(mb, "%d linecode\n", &linecode) != 1)
		badinput("linecode");
	a = fscanf(mb, "%d procedures (assert %d/%d)\n", &x, &assertbl, &errortbl);
	if (a != 3)
		badinput("procedures");
	if (fscanf(mb, "%d processes\n", &y) != 1)
		badinput("processes");
	if (fscanf(mb, "%d queues:\n", &z) != 1)
		badinput("queues");

	debug("%d procs, %d functions, %d queues, assert %d\n", y, x, z, assertbl);

	nrtbl = x + y;
	nrqs = z;
	alloc1(x, y, z);

	getmesnames();

	for (i = 0; i < z; i++)
	{	if (fscanf(mb, "%s\t%d/%d/%d: ", mbox[i].qname, &b, &a, &c) != 4)
			badinput("queue sorts");
		alloc2(i, a, b);
		for (j = 0; j < c; j++)
		{	fscanf(mb, "%d,", &b);
			xob[b] = i;
		}
	}

	if (fscanf(mb, "%d inits:\n", &nrinit) != 1)
		badinput("queue inits");

	alloc3(nrinit);
	for (i = 0; i < nrinit; i++)
		fscanf(mb, "%d,", &(inits[i]));

	if (fscanf(mb, "%d g-variables: ", &nrvars) != 1)
		badinput("g-variables");

	alloc4(nrvars);

	for (i = 0; i < nrvars; i++)
		if (fscanf(mb, "%d,", &a) != 1)
			badinput("g-var-inits");
		else
		{	if ((b = determine(a)) == 1 || b == 2)
				badinput("g-var bad init");
			else
				globvars[i] = (short) a;
		}
}

getmesnames()
{ register int i;
	if (fscanf(mb, "%d messages, base %d:\n", &nrmesgs, &msgbase) != 2)
		badinput("messages");

	alloc45(nrmesgs);

	for (i = 0; i < nrmesgs; i++)
		if (fscanf(mb, "%s ", fullname[i].mname) != 1)
			badinput("mesg");
}

gettables()
{ register int i, j;
  int a, b, c, d;
  char name[32];

	processes[0] = -1;
	if (nrtbl >= 64)
		badinput("too many process tables...");
	for (i = 0; i < nrtbl; i++)
	{	if ((j = fscanf(mb, "%s %d:%d/%d:", name, &a, &b, &c)) != 4)
		{	printf("matched %d: %s %d\n", j, name, a);
			badinput("table header");
		}

		debug("table %d: %s (%d) ", i, name, a, 0);
		debug("r/c: %d/%d\n", b, c, 0, 0);

		if (b >= 1024)
			badinput("too many states");
		if ((tbl[i].nrrows = b) == 0)
			badinput("empty table");
		tbl[i].nrcols = c;

		if (strcmp(name, "REF") == 0)
		{	reftasks[a] = i;
			nrrefs++;
		} else
		{	processes[a] = basics[a] = i;
			nrprocs++;
			effnrstates[i] = b;
		}

		if (b > 0)
		{	alloc5(i);
			for (j = 0; j < c; j++)
			{	if (fscanf(mb, "%d(%d),", &b, &d) != 2)
					badinput("column header");

				debug("%d(%d),\n", b, d, 0, 0);

				tbl[i].coltyp[j] = d;
				tbl[i].colmap[j] = b;
				if (d != FCT && d != SPN && d != CND)
					tbl[i].colorg[j] = whichq(b);
				else
					tbl[i].colorg[j] = -1;
			}
			getrows(i);
			getspecials(i);
			getcalls(i);
			getparams(a, i);
			getlocvars(a, i);
}	}	}

getrows(nn)
{ int a, b, c;
  int n = nn;
  char tmp[128];

	for (;;)
	{	if (fscanf(mb, "%d/%d (%d) ", &a, &b, &c) != 3)
			badinput("row");

		if (a == 0 && b == 0 && c == 0)
			break;

		debug("row %d, col %d, size %d:\n", a, b, c, 0);

		if (c == 0)
			continue;

		tbl[n].deadrow[a] = 0;
		getentries(n, a, b, c);
	}
	if (!linecode) return;

	if (fscanf(mb, "%s\n", tmp) != 1 || strcmp(tmp, "rownames:") != 0)
		badinput("rownames");
	for (a = 0; a < tbl[n].nrrows; a++)
	{	for (b = 0; (tbl[n].rowname[a][b] = getc(mb)) != '\n'; b++) ;
		tbl[n].rowname[a][b] = '\0';
	}
}

getentries(nn, m, p, q)
{ register int i;
  int x, y, n = nn;

	tbl[n].ptr[m][p].nrpils = (short) q;

	alloc6(n, m, p, q);

	for (i = 0; i < q; i++)
	{	if (fscanf(mb, "[%d,%d] ", &x, &y) != 2)
			badinput("table entry");
		tbl[n].ptr[m][p].one[i].transf   = (short) x;
		tbl[n].ptr[m][p].one[i].valtrans = (short) y;

		debug("\t[%d,%d] \n", x, y, 0, 0);
	}
}

getspecials(in)
{ register int i;
  int n, m;
  char stri[64];
	if (fscanf(mb, "ENDSTATES %d: ", &n) != 1)
		badinput("endstates");

	for (i = 0; i < n; i++)
	{	if (fscanf(mb, "%d,", &m) != 1 || m < 0 || m >= tbl[in].nrrows)
			badinput("endstate");
		tbl[in].endrow[m] = 1;
	}
	if ((m = fscanf(mb, "%s %d: ", stri, &n)) != 2 ||
		strcmp(stri, "BADSTATES") != 0)
	{	printf("read %s %d\n", stri, n);
		badinput("badstates");
	}

	for (i = 0; i < n; i++)
	{	if (fscanf(mb, "%d,", &m) != 1 || m < 0 || m >= tbl[in].nrrows)
			badinput("badstate");
		tbl[in].badrow[m] = 1;
	}

	if ((m = fscanf(mb, "%s %d: ", stri, &n)) != 2 ||
		strcmp(stri, "LABSTATES") != 0)
	{	printf("read %s %d\n", stri, n);
		badinput("labstates");
	}

	for (i = 0; i < n; i++)
	{	if (fscanf(mb, "%d,", &m) != 1 || m < 0 || m >= tbl[in].nrrows)
			badinput("labstate");
		tbl[in].labrow[m] = 1;
	}
	debug("specials:\n", 0, 0, 0, 0);
	for (i = 0; i < tbl[in].nrrows; i++)
	{	n = tbl[in].endrow[i];
		m = tbl[in].badrow[i];
		debug("\t%d: %d/%d/%d\n", i, n, m, tbl[in].labrow[i]);
	}
}

getparams(pr, tb)
{ int  n, m;
  char stri[64];
	if (fscanf(mb, "%s %d/%d", stri, &n, &m) != 3)
	{	printf("read %s %d/%d\n", stri, n, m);
		badinput("parameters");
	}

	tblpars[tb].nrms = (short) n;		/* required sizes  */
	tblpars[tb].nrvs = (short) m;

	if (processes[pr] == tb)
		alloc8(pr, 2*n, 2*m);		/* avalaible sizes */
}

getlocvars(p, tb)
{ register int i;
  int n, m;
	if (fscanf(mb, "%d l-variables: ", &n) != 1)
		badinput("l-variables");

	if (processes[p] != tb)
	{	tblvars[tb].nrlvars = (short) n;	/* required size */
		if (n > 0)
			tblvars[tb].lvarvals = (short *)
				Smalloc(n * sizeof(short));
		for (i = 0; i < n; i++)
			if (fscanf(mb, "%d,", &m) != 1)
				badinput("l-vars");
			else
				tblvars[tb].lvarvals[i] = (short) m;
	} else
	{	tablpars[p].nrlvars = (short) (2*n);	/* available size */
		procpars[p].nrlvars = (short) n;	/* actually used  */
		if (n > 0)
			procpars[p].lvarvals = (short *)
				Emalloc((2*n) * sizeof(short));
		for (i = 0; i < n; i++)
			if (fscanf(mb, "%d,", &m) != 1)
				badinput("lvar-inits");
			else
				procpars[p].lvarvals[i] = (short) m;
	}
}

getcalls(in)
{ register int i, j;
  int k, n, m, a, b, N;
  char stri[64];
	if (fscanf(mb, "%s %d", stri, &n) != 2)		/* FCTS */
	{	printf("read %s %d\n", stri, n);
		badinput("function calls");
	}
	alloc9(in, n);
	for (i = 0, N = n; i < N; i++)
	{	if (fscanf(mb, "%d-%d/%d: ", &n, &m, &k) != 3)
			badinput("fct call");

		alloc10(in, i, n, m, k);

		effnrstates[in] += tbl[reftasks[n]].nrrows;

		for (j = m+k, a = b = 0; j > 0; j--)
		{	if (fscanf(mb, "%d/%d", &n, &m) != 2)
				badinput("fct call entry");
			if (n == 0)
				tbl[in].calls[i].ms[a++] = (short) m;
			else
				tbl[in].calls[i].vs[b++] = (short) m;
	}	}
}

getexprs()
{ int i, j, a, b, c;
  char name[32];

	if (fscanf(mb, "%s %d\n", name, &nexpr) != 2)
		badinput("nexpr");
	if (strcmp(name, "EXPR") != 0)
		badinput("expressions");

	expr = (struct REVPOL **)
		Smalloc(nexpr * sizeof(struct REVPOL *));

	for (i = 0; i < nexpr; i++)
	{	fscanf(mb, "%d: ", &a);

		expr[i] = (struct REVPOL *)
			Smalloc(a * sizeof(struct REVPOL));

		for (j = 0; j < a; j++)
		{	fscanf(mb, "%d/%d: %d\n", &b, &c);
			expr[i][j].toktyp = b;
			expr[i][j].tokval = c;
	}	}
}

showtables(how)
{ register int i, j;
  int k, n, m, p;
  char table[2*MAXPROC][64];

	for (i = 0; i < nrprocs; i++)
	{	j = processes[i];
		sprintf(table[j], "process %d", i);
	}
	for (i = 0; i < nrrefs; i++)
	{	j = reftasks[i];
		sprintf(table[j], "reftask %d", i);
	}

	for (i = 0; i < nrtbl; i++)
	{
		printf("\n%s (table %d):\n", table[i], i);
		if (how && linecode)
		{	for (j = 2+strlen(tbl[i].rowname[0]); j > 0; j--)
				putchar(' ');
		} else	printf("  ");
		putchar('\t');
		for (k = 0; k < tbl[i].nrcols; k++)
		{	switch(tbl[i].coltyp[k]) {
				case INP:  printf("I:"); break;
				case DFL:  printf("D:"); break;
				case TMO:  printf("T:"); break;
				case OUTP: printf("O:"); break;
				case SPN:  printf("S:"); break;
				case CND:  printf("C:"); break;
				case FCT:  printf("F:"); break;
			}
			if (tbl[i].colorg[k] != -1)
			printf("%d/%d\t", tbl[i].colmap[k], tbl[i].colorg[k]);
			else
				printf("%d  \t", tbl[i].colmap[k]);
		}

		for (j = 0; j < tbl[i].nrrows; j++)
		{	if (!how || !linecode)
				printf("\n%2d\t", j);
			else
				printf("\n%2d/%s\t", j, tbl[i].rowname[j]);
			for (k = 0; k < tbl[i].nrcols; k++)
			{	if (how)
				{
				for (p = 0; p < tbl[i].ptr[j][k].nrpils; p++)
				{	n = (int) tbl[i].ptr[j][k].one[p].transf;
					printf("%d,", n);
				}
				} else
				{
				if (tbl[i].ptr[j][k].nrpils > 0)
				{	n = (int) tbl[i].ptr[j][k].one[0].transf;
					m = (int) tbl[i].ptr[j][k].one[0].valtrans;
					printf("%d(%d)", n, m);
				}
				if (tbl[i].ptr[j][k].nrpils > 1)
					putchar('+');
				}
				putchar('\t');
			}
	}	}
	putchar('\n');
}

whichq(n)
{ int i;
	if (n < 0 || n >= MANY)
		return -1;

	if ((i = xob[n]) == -1)
		badinput("mbox sort incomplete");

	return i;
}

init()
{ register int i, m;
	state = (int *)
		Smalloc(nrprocs * sizeof(int));
	qsize = (int *)
		Smalloc(nrqs * sizeof(int));
	head = (struct QUEUE **)
		Smalloc(nrqs * sizeof(struct QUEUE *));
	tail = (struct QUEUE **)
		Smalloc(nrqs * sizeof(struct QUEUE *));
	starter = (struct QUEUE **)
		Smalloc(nrqs * sizeof(struct QUEUE *));


	for (i = 0; i < nrqs; i++)
	{	starter[i] = (struct QUEUE *)
			Smalloc(sizeof(struct QUEUE));
		starter[i]->next = NULL;
		qsize[i] = 0;
		head[i] = tail[i] = starter[i];
	}

	decode();
	initable();	/* do not change the order of inits */
	iniqtable();
	inihash();

	for (i = 0; i < nrprocs; i++)
	{	state[i] = 0;
		procstack[i] = NULL;

		lbt[i].mapcol = (int *)
			Smalloc(maxcol * sizeof(int));
		lbt[i].orgcol = (int *)
			Smalloc(maxcol * sizeof(int));
		fiddler(i);
	}

	s_last = NULL;

	for (i = 0; i < nrinit; i++)
	{	m = inits[i];
		if (send(m, whichq(m), NONE, NONE, 0) == 0)
			badinput("qsize too small for initial string...");
	}
	if (assertbl != NONE)
	{	assertbl = reftasks[assertbl];

		abase = nrvars;
		nrvars += tbl[assertbl].nrrows;

		if (abase > 0)
			globvars = (int *)
				Realloc(globvars, nrvars * sizeof(int));
		else
			globvars = (int *)
				Smalloc(nrvars * sizeof(int));

		globvars[abase] = 1;
		for (i = abase+1; i < nrvars; i++)
			globvars[i] = 0;
	}
	if (errortbl != NONE)
	{	errortbl = reftasks[errortbl];

		ebase = nrvars;
		nrvars += tbl[errortbl].nrrows;

		if (ebase > 0)
			globvars = (int *)
				Realloc(globvars, nrvars * sizeof(int));
		else
			globvars = (int *)
				Smalloc(nrvars * sizeof(int));

		globvars[ebase] = 1;
		for (i = ebase+1; i < nrvars; i++)
			globvars[i] = 0;
	}
}

decode()
{ register int i, j, m;

	for (i = 0; i < nrvars; i++)
	{	m = convert(globvars[i], NONE);
		globvars[i] = (short) m;
	}
	for (i = 0; i < nrprocs; i++)
	for (j = 0; j < procpars[i].nrlvars; j++)
	{	m = convert(procpars[i].lvarvals[j], i);
		procpars[i].lvarvals[j] = (short) m;
	}
}