diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/spin/mesg.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/spin/mesg.c')
-rwxr-xr-x | sys/src/cmd/spin/mesg.c | 644 |
1 files changed, 644 insertions, 0 deletions
diff --git a/sys/src/cmd/spin/mesg.c b/sys/src/cmd/spin/mesg.c new file mode 100755 index 000000000..4b2806b40 --- /dev/null +++ b/sys/src/cmd/spin/mesg.c @@ -0,0 +1,644 @@ +/***** spin: mesg.c *****/ + +/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* All Rights Reserved. This software is for educational purposes only. */ +/* No guarantee whatsoever is expressed or implied by the distribution of */ +/* this code. Permission is given to distribute this code provided that */ +/* this introductory message is not removed and no monies are exchanged. */ +/* Software written by Gerard J. Holzmann. For tool documentation see: */ +/* http://spinroot.com/ */ +/* Send all bug-reports and/or questions to: bugs@spinroot.com */ + +#include "spin.h" +#include "y.tab.h" + +#ifndef MAXQ +#define MAXQ 2500 /* default max # queues */ +#endif + +extern RunList *X; +extern Symbol *Fname; +extern Lextok *Mtype; +extern int verbose, TstOnly, s_trail, analyze, columns; +extern int lineno, depth, xspin, m_loss, jumpsteps; +extern int nproc, nstop; +extern short Have_claim; + +Queue *qtab = (Queue *) 0; /* linked list of queues */ +Queue *ltab[MAXQ]; /* linear list of queues */ +int nqs = 0, firstrow = 1; +char Buf[4096]; + +static Lextok *n_rem = (Lextok *) 0; +static Queue *q_rem = (Queue *) 0; + +static int a_rcv(Queue *, Lextok *, int); +static int a_snd(Queue *, Lextok *); +static int sa_snd(Queue *, Lextok *); +static int s_snd(Queue *, Lextok *); +extern void sr_buf(int, int); +extern void sr_mesg(FILE *, int, int); +extern void putarrow(int, int); +static void sr_talk(Lextok *, int, char *, char *, int, Queue *); + +int +cnt_mpars(Lextok *n) +{ Lextok *m; + int i=0; + + for (m = n; m; m = m->rgt) + i += Cnt_flds(m); + return i; +} + +int +qmake(Symbol *s) +{ Lextok *m; + Queue *q; + int i; + + if (!s->ini) + return 0; + + if (nqs >= MAXQ) + { lineno = s->ini->ln; + Fname = s->ini->fn; + fatal("too many queues (%s)", s->name); + } + if (analyze && nqs >= 255) + { fatal("too many channel types", (char *)0); + } + + if (s->ini->ntyp != CHAN) + return eval(s->ini); + + q = (Queue *) emalloc(sizeof(Queue)); + q->qid = ++nqs; + q->nslots = s->ini->val; + q->nflds = cnt_mpars(s->ini->rgt); + q->setat = depth; + + i = max(1, q->nslots); /* 0-slot qs get 1 slot minimum */ + + q->contents = (int *) emalloc(q->nflds*i*sizeof(int)); + q->fld_width = (int *) emalloc(q->nflds*sizeof(int)); + q->stepnr = (int *) emalloc(i*sizeof(int)); + + for (m = s->ini->rgt, i = 0; m; m = m->rgt) + { if (m->sym && m->ntyp == STRUCT) + i = Width_set(q->fld_width, i, getuname(m->sym)); + else + q->fld_width[i++] = m->ntyp; + } + q->nxt = qtab; + qtab = q; + ltab[q->qid-1] = q; + + return q->qid; +} + +int +qfull(Lextok *n) +{ int whichq = eval(n->lft)-1; + + if (whichq < MAXQ && whichq >= 0 && ltab[whichq]) + return (ltab[whichq]->qlen >= ltab[whichq]->nslots); + return 0; +} + +int +qlen(Lextok *n) +{ int whichq = eval(n->lft)-1; + + if (whichq < MAXQ && whichq >= 0 && ltab[whichq]) + return ltab[whichq]->qlen; + return 0; +} + +int +q_is_sync(Lextok *n) +{ int whichq = eval(n->lft)-1; + + if (whichq < MAXQ && whichq >= 0 && ltab[whichq]) + return (ltab[whichq]->nslots == 0); + return 0; +} + +int +qsend(Lextok *n) +{ int whichq = eval(n->lft)-1; + + if (whichq == -1) + { printf("Error: sending to an uninitialized chan\n"); + whichq = 0; + return 0; + } + if (whichq < MAXQ && whichq >= 0 && ltab[whichq]) + { ltab[whichq]->setat = depth; + if (ltab[whichq]->nslots > 0) + return a_snd(ltab[whichq], n); + else + return s_snd(ltab[whichq], n); + } + return 0; +} + +int +qrecv(Lextok *n, int full) +{ int whichq = eval(n->lft)-1; + + if (whichq == -1) + { if (n->sym && !strcmp(n->sym->name, "STDIN")) + { Lextok *m; + + if (TstOnly) return 1; + + for (m = n->rgt; m; m = m->rgt) + if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL) + { int c = getchar(); + (void) setval(m->lft, c); + } else + fatal("invalid use of STDIN", (char *)0); + + whichq = 0; + return 1; + } + printf("Error: receiving from an uninitialized chan %s\n", + n->sym?n->sym->name:""); + whichq = 0; + return 0; + } + if (whichq < MAXQ && whichq >= 0 && ltab[whichq]) + { ltab[whichq]->setat = depth; + return a_rcv(ltab[whichq], n, full); + } + return 0; +} + +static int +sa_snd(Queue *q, Lextok *n) /* sorted asynchronous */ +{ Lextok *m; + int i, j, k; + int New, Old; + + for (i = 0; i < q->qlen; i++) + for (j = 0, m = n->rgt; m && j < q->nflds; m = m->rgt, j++) + { New = cast_val(q->fld_width[j], eval(m->lft), 0); + Old = q->contents[i*q->nflds+j]; + if (New == Old) continue; + if (New > Old) break; /* inner loop */ + if (New < Old) goto found; + } +found: + for (j = q->qlen-1; j >= i; j--) + for (k = 0; k < q->nflds; k++) + { q->contents[(j+1)*q->nflds+k] = + q->contents[j*q->nflds+k]; /* shift up */ + if (k == 0) + q->stepnr[j+1] = q->stepnr[j]; + } + return i*q->nflds; /* new q offset */ +} + +void +typ_ck(int ft, int at, char *s) +{ + if ((verbose&32) && ft != at + && (ft == CHAN || at == CHAN)) + { char buf[128], tag1[64], tag2[64]; + (void) sputtype(tag1, ft); + (void) sputtype(tag2, at); + sprintf(buf, "type-clash in %s, (%s<-> %s)", s, tag1, tag2); + non_fatal("%s", buf); + } +} + +static int +a_snd(Queue *q, Lextok *n) +{ Lextok *m; + int i = q->qlen*q->nflds; /* q offset */ + int j = 0; /* q field# */ + + if (q->nslots > 0 && q->qlen >= q->nslots) + return m_loss; /* q is full */ + + if (TstOnly) return 1; + + if (n->val) i = sa_snd(q, n); /* sorted insert */ + + q->stepnr[i/q->nflds] = depth; + + for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++) + { int New = eval(m->lft); + q->contents[i+j] = cast_val(q->fld_width[j], New, 0); + if ((verbose&16) && depth >= jumpsteps) + sr_talk(n, New, "Send ", "->", j, q); + typ_ck(q->fld_width[j], Sym_typ(m->lft), "send"); + } + if ((verbose&16) && depth >= jumpsteps) + { for (i = j; i < q->nflds; i++) + sr_talk(n, 0, "Send ", "->", i, q); + if (j < q->nflds) + printf("%3d: warning: missing params in send\n", + depth); + if (m) + printf("%3d: warning: too many params in send\n", + depth); + } + q->qlen++; + return 1; +} + +static int +a_rcv(Queue *q, Lextok *n, int full) +{ Lextok *m; + int i=0, oi, j, k; + extern int Rvous; + + if (q->qlen == 0) + return 0; /* q is empty */ +try_slot: + /* test executability */ + for (m = n->rgt, j=0; m && j < q->nflds; m = m->rgt, j++) + if ((m->lft->ntyp == CONST + && q->contents[i*q->nflds+j] != m->lft->val) + || (m->lft->ntyp == EVAL + && q->contents[i*q->nflds+j] != eval(m->lft->lft))) + { if (n->val == 0 /* fifo recv */ + || n->val == 2 /* fifo poll */ + || ++i >= q->qlen) /* last slot */ + return 0; /* no match */ + goto try_slot; + } + if (TstOnly) return 1; + + if (verbose&8) + { if (j < q->nflds) + printf("%3d: warning: missing params in next recv\n", + depth); + else if (m) + printf("%3d: warning: too many params in next recv\n", + depth); + } + + /* set the fields */ + if (Rvous) + { n_rem = n; + q_rem = q; + } + + oi = q->stepnr[i]; + for (m = n->rgt, j = 0; m && j < q->nflds; m = m->rgt, j++) + { if (columns && !full) /* was columns == 1 */ + continue; + if ((verbose&8) && !Rvous && depth >= jumpsteps) + { sr_talk(n, q->contents[i*q->nflds+j], + (full && n->val < 2)?"Recv ":"[Recv] ", "<-", j, q); + } + if (!full) + continue; /* test */ + if (m && m->lft->ntyp != CONST && m->lft->ntyp != EVAL) + { (void) setval(m->lft, q->contents[i*q->nflds+j]); + typ_ck(q->fld_width[j], Sym_typ(m->lft), "recv"); + } + if (n->val < 2) /* not a poll */ + for (k = i; k < q->qlen-1; k++) + { q->contents[k*q->nflds+j] = + q->contents[(k+1)*q->nflds+j]; + if (j == 0) + q->stepnr[k] = q->stepnr[k+1]; + } + } + + if ((!columns || full) + && (verbose&8) && !Rvous && depth >= jumpsteps) + for (i = j; i < q->nflds; i++) + { sr_talk(n, 0, + (full && n->val < 2)?"Recv ":"[Recv] ", "<-", i, q); + } + if (columns == 2 && full && !Rvous && depth >= jumpsteps) + putarrow(oi, depth); + + if (full && n->val < 2) + q->qlen--; + return 1; +} + +static int +s_snd(Queue *q, Lextok *n) +{ Lextok *m; + RunList *rX, *sX = X; /* rX=recvr, sX=sendr */ + int i, j = 0; /* q field# */ + + for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++) + { q->contents[j] = cast_val(q->fld_width[j], eval(m->lft), 0); + typ_ck(q->fld_width[j], Sym_typ(m->lft), "rv-send"); + } + q->qlen = 1; + if (!complete_rendez()) + { q->qlen = 0; + return 0; + } + if (TstOnly) + { q->qlen = 0; + return 1; + } + q->stepnr[0] = depth; + if ((verbose&16) && depth >= jumpsteps) + { m = n->rgt; + rX = X; X = sX; + for (j = 0; m && j < q->nflds; m = m->rgt, j++) + sr_talk(n, eval(m->lft), "Sent ", "->", j, q); + for (i = j; i < q->nflds; i++) + sr_talk(n, 0, "Sent ", "->", i, q); + if (j < q->nflds) + printf("%3d: warning: missing params in rv-send\n", + depth); + else if (m) + printf("%3d: warning: too many params in rv-send\n", + depth); + X = rX; /* restore receiver's context */ + if (!s_trail) + { if (!n_rem || !q_rem) + fatal("cannot happen, s_snd", (char *) 0); + m = n_rem->rgt; + for (j = 0; m && j < q->nflds; m = m->rgt, j++) + { if (m->lft->ntyp != NAME + || strcmp(m->lft->sym->name, "_") != 0) + i = eval(m->lft); + else i = 0; + + if (verbose&8) + sr_talk(n_rem,i,"Recv ","<-",j,q_rem); + } + if (verbose&8) + for (i = j; i < q->nflds; i++) + sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem); + if (columns == 2) + putarrow(depth, depth); + } + n_rem = (Lextok *) 0; + q_rem = (Queue *) 0; + } + return 1; +} + +void +channm(Lextok *n) +{ char lbuf[512]; + + if (n->sym->type == CHAN) + strcat(Buf, n->sym->name); + else if (n->sym->type == NAME) + strcat(Buf, lookup(n->sym->name)->name); + else if (n->sym->type == STRUCT) + { Symbol *r = n->sym; + if (r->context) + r = findloc(r); + ini_struct(r); + printf("%s", r->name); + strcpy(lbuf, ""); + struct_name(n->lft, r, 1, lbuf); + strcat(Buf, lbuf); + } else + strcat(Buf, "-"); + if (n->lft->lft) + { sprintf(lbuf, "[%d]", eval(n->lft->lft)); + strcat(Buf, lbuf); + } +} + +static void +difcolumns(Lextok *n, char *tr, int v, int j, Queue *q) +{ extern int pno; + + if (j == 0) + { Buf[0] = '\0'; + channm(n); + strcat(Buf, (strncmp(tr, "Sen", 3))?"?":"!"); + } else + strcat(Buf, ","); + if (tr[0] == '[') strcat(Buf, "["); + sr_buf(v, q->fld_width[j] == MTYPE); + if (j == q->nflds - 1) + { int cnr; + if (s_trail) cnr = pno; else cnr = X?X->pid - Have_claim:0; + if (tr[0] == '[') strcat(Buf, "]"); + pstext(cnr, Buf); + } +} + +static void +docolumns(Lextok *n, char *tr, int v, int j, Queue *q) +{ int i; + + if (firstrow) + { printf("q\\p"); + for (i = 0; i < nproc-nstop - Have_claim; i++) + printf(" %3d", i); + printf("\n"); + firstrow = 0; + } + if (j == 0) + { printf("%3d", q->qid); + if (X) + for (i = 0; i < X->pid - Have_claim; i++) + printf(" ."); + printf(" "); + Buf[0] = '\0'; + channm(n); + printf("%s%c", Buf, (strncmp(tr, "Sen", 3))?'?':'!'); + } else + printf(","); + if (tr[0] == '[') printf("["); + sr_mesg(stdout, v, q->fld_width[j] == MTYPE); + if (j == q->nflds - 1) + { if (tr[0] == '[') printf("]"); + printf("\n"); + } +} + +typedef struct QH { + int n; + struct QH *nxt; +} QH; +QH *qh; + +void +qhide(int q) +{ QH *p = (QH *) emalloc(sizeof(QH)); + p->n = q; + p->nxt = qh; + qh = p; +} + +int +qishidden(int q) +{ QH *p; + for (p = qh; p; p = p->nxt) + if (p->n == q) + return 1; + return 0; +} + +static void +sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q) +{ char s[64]; + + if (qishidden(eval(n->lft))) + return; + + if (columns) + { if (columns == 2) + difcolumns(n, tr, v, j, q); + else + docolumns(n, tr, v, j, q); + return; + } + if (xspin) + { if ((verbose&4) && tr[0] != '[') + sprintf(s, "(state -)\t[values: %d", + eval(n->lft)); + else + sprintf(s, "(state -)\t[%d", eval(n->lft)); + if (strncmp(tr, "Sen", 3) == 0) + strcat(s, "!"); + else + strcat(s, "?"); + } else + { strcpy(s, tr); + } + + if (j == 0) + { whoruns(1); + printf("line %3d %s %s", + n->ln, n->fn->name, s); + } else + printf(","); + sr_mesg(stdout, v, q->fld_width[j] == MTYPE); + + if (j == q->nflds - 1) + { if (xspin) + { printf("]\n"); + if (!(verbose&4)) printf("\n"); + return; + } + printf("\t%s queue %d (", a, eval(n->lft)); + Buf[0] = '\0'; + channm(n); + printf("%s)\n", Buf); + } + fflush(stdout); +} + +void +sr_buf(int v, int j) +{ int cnt = 1; Lextok *n; + char lbuf[512]; + + for (n = Mtype; n && j; n = n->rgt, cnt++) + if (cnt == v) + { if(strlen(n->lft->sym->name) >= sizeof(lbuf)) + { non_fatal("mtype name %s too long", n->lft->sym->name); + break; + } + sprintf(lbuf, "%s", n->lft->sym->name); + strcat(Buf, lbuf); + return; + } + sprintf(lbuf, "%d", v); + strcat(Buf, lbuf); +} + +void +sr_mesg(FILE *fd, int v, int j) +{ Buf[0] ='\0'; + sr_buf(v, j); + fprintf(fd, Buf); +} + +void +doq(Symbol *s, int n, RunList *r) +{ Queue *q; + int j, k; + + if (!s->val) /* uninitialized queue */ + return; + for (q = qtab; q; q = q->nxt) + if (q->qid == s->val[n]) + { if (xspin > 0 + && (verbose&4) + && q->setat < depth) + continue; + if (q->nslots == 0) + continue; /* rv q always empty */ + printf("\t\tqueue %d (", q->qid); + if (r) + printf("%s(%d):", r->n->name, r->pid - Have_claim); + if (s->nel != 1) + printf("%s[%d]): ", s->name, n); + else + printf("%s): ", s->name); + for (k = 0; k < q->qlen; k++) + { printf("["); + for (j = 0; j < q->nflds; j++) + { if (j > 0) printf(","); + sr_mesg(stdout, q->contents[k*q->nflds+j], + q->fld_width[j] == MTYPE); + } + printf("]"); + } + printf("\n"); + break; + } +} + +void +nochan_manip(Lextok *p, Lextok *n, int d) +{ int e = 1; + + if (d == 0 && p->sym && p->sym->type == CHAN) + { setaccess(p->sym, ZS, 0, 'L'); + + if (n && n->ntyp == CONST) + fatal("invalid asgn to chan", (char *) 0); + + if (n && n->sym && n->sym->type == CHAN) + { setaccess(n->sym, ZS, 0, 'V'); + return; + } + } + + if (!n || n->ntyp == LEN || n->ntyp == RUN) + return; + + if (n->sym && n->sym->type == CHAN) + { if (d == 1) + fatal("invalid use of chan name", (char *) 0); + else + setaccess(n->sym, ZS, 0, 'V'); + } + + if (n->ntyp == NAME + || n->ntyp == '.') + e = 0; /* array index or struct element */ + + nochan_manip(p, n->lft, e); + nochan_manip(p, n->rgt, 1); +} + +void +no_internals(Lextok *n) +{ char *sp; + + if (!n->sym + || !n->sym->name) + return; + + sp = n->sym->name; + + if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0) + || (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0)) + { fatal("attempt to assign value to system variable %s", sp); + } +} |