# HG changeset patch # User David du Colombier <0intro@gmail.com> # Date 1331073250 -3600 # Node ID 5f9e0e495d4312f62a849ea58c4743a48e85eb0c # Parent dbb1bddf6759228f163a7c18aaea0cfd27aa4aeb cmd: sync with plan 9 R=nixiedev CC=nix-dev http://codereview.appspot.com/5763043 Committer: Francisco J Ballesteros diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/9660srv/9660srv.c --- a/sys/src/cmd/9660srv/9660srv.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/9660srv/9660srv.c Tue Mar 06 23:34:10 2012 +0100 @@ -31,6 +31,7 @@ static long gtime(uchar*); static long l16(void*); static long l32(void*); +static vlong l64(void *); static void newdrec(Xfile*, Drec*); static int rzdir(Xfs*, Dir*, int, Drec*); @@ -211,7 +212,7 @@ static void iwalkup(Xfile *f) { - long paddr; + vlong paddr; uchar dbuf[256]; Drec *d = (Drec *)dbuf; Xfile pf, ppf; @@ -493,7 +494,7 @@ return -1; size = fakemax(l32(ip->d.size)); while(ip->offset < size){ - addr = (l32(ip->d.addr)+ip->d.attrlen)*ip->blksize + ip->offset; + addr = ((vlong)l32(ip->d.addr)+ip->d.attrlen)*ip->blksize + ip->offset; boff = addr % Sectorsize; if(boff > Sectorsize-34){ ip->offset += Sectorsize-boff; @@ -748,13 +749,13 @@ static int getcontin(Xdata *dev, uchar *p, uchar **s) { - long bn, off, len; + vlong bn, off, len; Iobuf *b; bn = l32(p+4); off = l32(p+12); len = l32(p+20); - chat("getcontin %d...", bn); + chat("getcontin %lld...", bn); b = getbuf(dev, bn); if(b == 0){ *s = 0; @@ -871,7 +872,16 @@ static long l32(void *arg) { - return ((((((long)p[3]<<8)|p[2])<<8)|p[1])<<8)|p[0]; + return (((long)p[3]<<8 | p[2])<<8 | p[1])<<8 | p[0]; } #undef p + +static vlong +l64(void *arg) +{ + uchar *p; + + p = arg; + return (vlong)l32(p+4) << 32 | (ulong)l32(p); +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/9660srv/fns.h --- a/sys/src/cmd/9660srv/fns.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/9660srv/fns.h Tue Mar 06 23:34:10 2012 +0100 @@ -1,7 +1,7 @@ void chat(char*, ...); void* ealloc(long); void error(char*); -Iobuf* getbuf(Xdata*, ulong); +Iobuf* getbuf(Xdata*, uvlong); Xdata* getxdata(char*); void iobuf_init(void); void nexterror(void); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/9660srv/iobuf.c --- a/sys/src/cmd/9660srv/iobuf.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/9660srv/iobuf.c Tue Mar 06 23:34:10 2012 +0100 @@ -32,7 +32,7 @@ static Ioclust* iohead; static Ioclust* iotail; -static Ioclust* getclust(Xdata*, long); +static Ioclust* getclust(Xdata*, vlong); static void putclust(Ioclust*); static void xread(Ioclust*); @@ -88,7 +88,7 @@ } static Ioclust* -getclust(Xdata *dev, long addr) +getclust(Xdata *dev, vlong addr) { Ioclust *c, *f; @@ -142,7 +142,7 @@ } Iobuf* -getbuf(Xdata *dev, ulong addr) +getbuf(Xdata *dev, uvlong addr) { int off; Ioclust *c; @@ -151,7 +151,7 @@ c = getclust(dev, addr - off); if(c->nbuf < off){ c->busy--; - error("I/O read error"); + error("short read or I/O error"); } return &c->buf[off]; } @@ -172,6 +172,6 @@ seek(dev->dev, (vlong)c->addr * Sectorsize, 0); n = readn(dev->dev, c->iobuf, BUFPERCLUST*Sectorsize); if(n < Sectorsize) - error("I/O read error"); + error("short read or I/O error"); c->nbuf = n/Sectorsize; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/as.c --- a/sys/src/cmd/auth/as.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/as.c Tue Mar 06 23:34:10 2012 +0100 @@ -123,7 +123,7 @@ uchar rand[20]; char *cap; char *key; - int nfrom, nto; + int nfrom, nto, ncap; uchar hash[SHA1dlen]; if(caphashfd < 0) @@ -132,8 +132,9 @@ /* create the capability */ nto = strlen(to); nfrom = strlen(from); - cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); - sprint(cap, "%s@%s", from, to); + ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1; + cap = emalloc(ncap); + snprint(cap, ncap, "%s@%s", from, to); memrandom(rand, sizeof(rand)); key = cap+nfrom+1+nto+1; enc64(key, sizeof(rand)*3, rand, sizeof(rand)); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/authsrv.c --- a/sys/src/cmd/auth/authsrv.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/authsrv.c Tue Mar 06 23:34:10 2012 +0100 @@ -189,7 +189,7 @@ memset(buf, 0, sizeof(buf)); buf[0] = AuthOK; chal = lnrand(MAXNETCHAL); - sprint(buf+1, "%lud", chal); + snprint(buf+1, sizeof buf - 1, "%lud", chal); if(write(1, buf, NETCHLEN+1) < 0) exits(0); if(readn(0, buf, NETCHLEN) < 0) @@ -508,7 +508,7 @@ */ randombytes(chal+6, VNCchallen); chal[0] = AuthOKvar; - sprint((char*)chal+1, "%-5d", VNCchallen); + snprint((char*)chal+1, sizeof chal - 1, "%-5d", VNCchallen); if(write(1, chal, sizeof(chal)) != sizeof(chal)) return; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/changeuser.c --- a/sys/src/cmd/auth/changeuser.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/changeuser.c Tue Mar 06 23:34:10 2012 +0100 @@ -108,7 +108,7 @@ int fd; if(!exists(db, u)){ - sprint(buf, "%s/%s", db, u); + snprint(buf, sizeof buf, "%s/%s", db, u); fd = create(buf, OREAD, 0777|DMDIR); if(fd < 0) error("can't create user %s: %r", u); @@ -116,7 +116,7 @@ } if(newkey){ - sprint(buf, "%s/%s/key", db, u); + snprint(buf, sizeof buf, "%s/%s/key", db, u); fd = open(buf, OWRITE); if(fd < 0 || write(fd, key, DESKEYLEN) != DESKEYLEN) error("can't set key: %r"); @@ -125,7 +125,7 @@ if(t == -1) return; - sprint(buf, "%s/%s/expire", db, u); + snprint(buf, sizeof buf, "%s/%s/expire", db, u); fd = open(buf, OWRITE); if(fd < 0 || fprint(fd, "%ld", t) < 0) error("can't write expiration time"); @@ -137,7 +137,7 @@ { char buf[KEYDBBUF+ANAMELEN+6]; - sprint(buf, "%s/%s/expire", db, u); + snprint(buf, sizeof buf, "%s/%s/expire", db, u); if(access(buf, 0) < 0) return 0; return 1; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/cron.c --- a/sys/src/cmd/auth/cron.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/cron.c Tue Mar 06 23:34:10 2012 +0100 @@ -248,7 +248,7 @@ int fd; user = getuser(); - sprint(file, "/cron/%s", user); + snprint(file, sizeof file, "/cron/%s", user); fd = create(file, OREAD, 0755|DMDIR); if(fd < 0) sysfatal("couldn't create %s: %r", file); @@ -256,7 +256,7 @@ d.gid = user; dirfwstat(fd, &d); close(fd); - sprint(file, "/cron/%s/cron", user); + snprint(file, sizeof file, "/cron/%s/cron", user); fd = create(file, OREAD, 0644); if(fd < 0) sysfatal("couldn't create %s: %r", file); @@ -288,7 +288,7 @@ continue; } u = newuser(d[i].name); - sprint(file, "/cron/%s/cron", d[i].name); + snprint(file, sizeof file, "/cron/%s/cron", d[i].name); du = dirstat(file); if(du == nil || qidcmp(u->lastqid, du->qid) != 0){ freejobs(u->jobs); @@ -686,7 +686,7 @@ uchar rand[20]; char *cap; char *key; - int nfrom, nto; + int nfrom, nto, ncap; uchar hash[SHA1dlen]; if(caphashfd < 0) @@ -695,8 +695,9 @@ /* create the capability */ nto = strlen(to); nfrom = strlen(from); - cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); - sprint(cap, "%s@%s", from, to); + ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1; + cap = emalloc(ncap); + snprint(cap, ncap, "%s@%s", from, to); memrandom(rand, sizeof(rand)); key = cap+nfrom+1+nto+1; enc64(key, sizeof(rand)*3, rand, sizeof(rand)); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/factotum/apop.c --- a/sys/src/cmd/auth/factotum/apop.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/factotum/apop.c Tue Mar 06 23:34:10 2012 +0100 @@ -119,7 +119,7 @@ case AuthCram: hmac_md5((uchar*)a, n, (uchar*)v, strlen(v), digest, nil); - sprint(s->resp, "%.*H", MD5dlen, digest); + snprint(s->resp, sizeof s->resp, "%.*H", MD5dlen, digest); break; case AuthApop: ds = md5((uchar*)a, n, nil, nil); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/factotum/p9cr.c --- a/sys/src/cmd/auth/factotum/p9cr.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/factotum/p9cr.c Tue Mar 06 23:34:10 2012 +0100 @@ -175,7 +175,7 @@ return failure(fss, "vncresponse cannot happen"); passtokey(key, pw); memset(buf, 0, 8); - sprint((char*)buf, "%d", atoi(s->chal)); + snprint((char*)buf, sizeof buf, "%d", atoi(s->chal)); if(encrypt(key, buf, 8) < 0) return failure(fss, "can't encrypt response"); chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/factotum/util.c --- a/sys/src/cmd/auth/factotum/util.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/factotum/util.c Tue Mar 06 23:34:10 2012 +0100 @@ -494,7 +494,7 @@ s = emalloc(512); fmtinstall('H', encodefmt); - sprint(s, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______", + snprint(s, 512, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______", safe.authid, safe.authdom, DESKEYLEN, safe.machkey); writehostowner(safe.authid); @@ -594,7 +594,7 @@ uchar rand[20]; char *cap; char *key; - int nfrom, nto; + int nfrom, nto, ncap; uchar hash[SHA1dlen]; if(caphashfd < 0) @@ -603,8 +603,9 @@ /* create the capability */ nto = strlen(to); nfrom = strlen(from); - cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); - sprint(cap, "%s@%s", from, to); + ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1; + cap = emalloc(ncap); + snprint(cap, ncap, "%s@%s", from, to); memrandom(rand, sizeof(rand)); key = cap+nfrom+1+nto+1; enc64(key, sizeof(rand)*3, rand, sizeof(rand)); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/guard.srv.c --- a/sys/src/cmd/auth/guard.srv.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/guard.srv.c Tue Mar 06 23:34:10 2012 +0100 @@ -70,7 +70,7 @@ * challenge-response */ chal = lnrand(MAXNETCHAL); - sprint(buf, "challenge: %lud\nresponse: ", chal); + snprint(buf, sizeof buf, "challenge: %lud\nresponse: ", chal); n = strlen(buf) + 1; if(write(1, buf, n) != n){ if(debug) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/keyfs.c --- a/sys/src/cmd/auth/keyfs.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/keyfs.c Tue Mar 06 23:34:10 2012 +0100 @@ -797,22 +797,23 @@ int weirdfmt(Fmt *f) { - char *s, buf[ANAMELEN*4 + 1]; - int i, j, n; + char *s, *p, *ep, buf[ANAMELEN*4 + 1]; + int i, n; Rune r; s = va_arg(f->args, char*); - j = 0; + p = buf; + ep = buf + sizeof buf; for(i = 0; i < ANAMELEN; i += n){ n = chartorune(&r, s + i); if(r == Runeerror) - j += sprint(buf+j, "[%.2x]", buf[i]); + p = seprint(p, ep, "[%.2x]", buf[i]); else if(isascii(r) && iscntrl(r)) - j += sprint(buf+j, "[%.2x]", r); + p = seprint(p, ep, "[%.2x]", r); else if(r == ' ' || r == '/') - j += sprint(buf+j, "[%c]", r); + p = seprint(p, ep, "[%c]", r); else - j += sprint(buf+j, "%C", r); + p = seprint(p, ep, "%C", r); } return fmtstrcpy(f, buf); } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/lib/error.c --- a/sys/src/cmd/auth/lib/error.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/lib/error.c Tue Mar 06 23:34:10 2012 +0100 @@ -10,7 +10,7 @@ va_list arg; s = buf; - s += sprint(s, "%s: ", argv0); + s += snprint(s, sizeof buf, "%s: ", argv0); va_start(arg, fmt); s = vseprint(s, buf + sizeof(buf), fmt, arg); va_end(arg); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/lib/getexpiration.c --- a/sys/src/cmd/auth/lib/getexpiration.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/lib/getexpiration.c Tue Mar 06 23:34:10 2012 +0100 @@ -53,12 +53,14 @@ if(strncmp(buf, "never", 5)){ secs = atoi(buf); memmove(&date, localtime(secs), sizeof(date)); - sprint(buf, "%4.4d%2.2d%2.2d", date.year+1900, date.mon+1, date.mday); + snprint(buf, sizeof buf, "%4.4d%2.2d%2.2d", + date.year+1900, date.mon+1, date.mday); } else buf[5] = 0; } else strcpy(buf, "never"); - sprint(prompt, "Expiration date (YYYYMMDD or never)[return = %s]: ", buf); + snprint(prompt, sizeof prompt, + "Expiration date (YYYYMMDD or never)[return = %s]: ", buf); now = time(0); for(;;){ diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/lib/keyfmt.c --- a/sys/src/cmd/auth/lib/keyfmt.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/lib/keyfmt.c Tue Mar 06 23:34:10 2012 +0100 @@ -22,7 +22,8 @@ key[i+1] = k[i] << (7 - i); } key[7] &= ~1; - sprint(buf, "%.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo", + snprint(buf, sizeof buf, + "%.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo", key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]); fmtstrcpy(f, buf); return 0; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/lib/netcheck.c --- a/sys/src/cmd/auth/lib/netcheck.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/lib/netcheck.c Tue Mar 06 23:34:10 2012 +0100 @@ -27,7 +27,7 @@ uchar buf[8]; memset(buf, 0, 8); - sprint((char *)buf, "%lud", chal); + snprint((char *)buf, sizeof buf, "%lud", chal); if(encrypt(key, buf, 8) < 0) error("can't encrypt response"); chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; @@ -87,7 +87,7 @@ uchar buf[2*8]; int i, c, cslo, cshi; - sprint((char*)buf, "%lud ", chal); + snprint((char*)buf, sizeof buf, "%lud ", chal); cslo = 0x52; cshi = cslo; for(i = 0; i < 8; i++){ diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/netkey.c --- a/sys/src/cmd/auth/netkey.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/netkey.c Tue Mar 06 23:34:10 2012 +0100 @@ -42,7 +42,7 @@ exits(0); buf[n] = '\0'; n = strtol(buf, 0, 10); - sprint(buf, "%d", n); + snprint(buf, sizeof buf, "%d", n); netcrypt(key, buf); print("response: %s\n", buf); } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/auth/warning.c --- a/sys/src/cmd/auth/warning.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/auth/warning.c Tue Mar 06 23:34:10 2012 +0100 @@ -87,7 +87,7 @@ long rcvrs, et, now; char *l; - sprint(buf, "%s/expire", user); + snprint(buf, sizeof buf, "%s/expire", user); et = readnumfile(buf); now = time(0); @@ -95,7 +95,7 @@ if(et <= now || et > now+14*24*60*60) return; - sprint(buf, "%s/warnings", user); + snprint(buf, sizeof buf, "%s/warnings", user); nwarn = readnumfile(buf); if(et <= now+14*24*60*60 && et > now+7*24*60*60){ /* one warning 2 weeks before expiration */ @@ -222,7 +222,7 @@ p++; else p = f->keys; - sprint(buf, "/adm/warn.%s", p); + snprint(buf, sizeof buf, "/adm/warn.%s", p); fd = open(buf, OREAD); if(fd >= 0){ while((i = read(fd, buf, sizeof(buf))) > 0) @@ -278,7 +278,7 @@ va_list arg; s = buf; - s += sprint(s, "%s: ", argv0); + s += snprint(s, sizeof buf, "%s: ", argv0); va_start(arg, fmt); s = vseprint(s, buf + sizeof(buf) / sizeof(*buf), fmt, arg); va_end(arg); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/aux/stub.c --- a/sys/src/cmd/aux/stub.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/aux/stub.c Tue Mar 06 23:34:10 2012 +0100 @@ -189,6 +189,10 @@ *p++ = '\0'; kidname = p; } + /* don't leave standard descriptors open to confuse mk */ + close(0); + close(1); + close(2); postmountsrv(&fs, nil, mtpt, MBEFORE); exits(nil); } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/bsplit.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/bsplit.c Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,207 @@ +/* + * bsplit - split big binaries (copy-less plan 9 version) + */ + +#include +#include +#include /* for ANAMELEN */ + +enum { + Stdin, + Sectsiz = 512, + Bufsiz = 256*Sectsiz, +}; + +/* disk address (in bytes or sectors), also type of 2nd arg. to seek */ +typedef uvlong Daddr; + +#define BLEN(s) ((s)->wp - (s)->rp) +#define BALLOC(s) ((s)->lim - (s)->base) + +typedef struct { + uchar* rp; /* first unconsumed byte */ + uchar* wp; /* first empty byte */ + uchar* lim; /* 1 past the end of the buffer */ + uchar* base; /* start of the buffer */ +} Buffer; + +typedef struct { + /* parameters */ + Daddr maxoutsz; /* maximum size of output file(s) */ + + Daddr fileout; /* bytes written to the current output file */ + char *filenm; + int filesz; /* size of filenm */ + char *prefix; + long filenum; + int outf; /* open output file */ + + Buffer buff; +} Copy; + +/* global data */ +char *argv0; + +/* private data */ +static Copy cp = { 512*1024*1024 }; /* default maximum size */ +static int debug; + +static void +bufreset(Buffer *bp) +{ + bp->rp = bp->wp = bp->base; +} + +static void +bufinit(Buffer *bp, uchar *block, unsigned size) +{ + bp->base = block; + bp->lim = bp->base + size; + bufreset(bp); +} + +static int +eopen(char *file, int mode) +{ + int fd = open(file, mode); + + if (fd < 0) + sysfatal("can't open %s: %r", file); + return fd; +} + +static int +ecreate(char *file, int mode) +{ + int fd = create(file, mode, 0666); + + if (fd < 0) + sysfatal("can't create %s: %r", file); + return fd; +} + +static char * +filename(Copy *cp) +{ + return cp->filenm; +} + +static int +opennext(Copy *cp) +{ + if (cp->outf >= 0) + sysfatal("opennext called with file open"); + snprint(cp->filenm, cp->filesz, "%s%5.5ld", cp->prefix, cp->filenum++); + cp->outf = ecreate(cp->filenm, OWRITE); + cp->fileout = 0; + return cp->outf; +} + +static int +closeout(Copy *cp) +{ + if (cp->outf >= 0) { + if (close(cp->outf) < 0) + sysfatal("error writing %s: %r", filename(cp)); + cp->outf = -1; + cp->fileout = 0; + } + return cp->outf; +} + +/* + * process - process input file + */ +static void +process(int in, char *inname) +{ + int n = 1; + unsigned avail, tolim, wsz; + Buffer *bp = &cp.buff; + + USED(inname); + do { + if (BLEN(bp) == 0) { + if (bp->lim == bp->wp) + bufreset(bp); + n = read(in, bp->wp, bp->lim - bp->wp); + if (n <= 0) + break; + bp->wp += n; + } + if (cp.outf < 0) + opennext(&cp); + + /* + * write from buffer's current point to end or enough bytes to + * reach file-size limit. + */ + avail = BLEN(bp); + tolim = cp.maxoutsz - cp.fileout; + wsz = (tolim < avail? tolim: avail); + + /* try to write full sectors */ + if (tolim >= avail && n > 0 && wsz >= Sectsiz) + wsz = (wsz / Sectsiz) * Sectsiz; + if (write(cp.outf, bp->rp, wsz) != wsz) + sysfatal("error writing %s: %r", filename(&cp)); + bp->rp += wsz; + + cp.fileout += wsz; + if (cp.fileout >= cp.maxoutsz) + closeout(&cp); + } while (n > 0 || BLEN(bp) != 0); +} + +static void +usage(void) +{ + fprint(2, "usage: %s [-d][-p pfx][-s size] [file...]\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int i, errflg = 0; + uchar block[Bufsiz]; + + cp.prefix = "bs."; + ARGBEGIN { + case 'd': + debug++; + break; + case 'p': + cp.prefix = EARGF(usage()); + break; + case 's': + cp.maxoutsz = atoll(EARGF(usage())); + if (cp.maxoutsz < 1) + errflg++; + break; + default: + errflg++; + break; + } ARGEND + if (errflg || argc < 0) + usage(); + + bufinit(&cp.buff, block, sizeof block); + cp.outf = -1; + cp.filesz = strlen(cp.prefix) + 2*ANAMELEN; /* 2* is slop */ + cp.filenm = malloc(cp.filesz + 1); + if (cp.filenm == nil) + sysfatal("no memory: %r"); + + if (argc == 0) + process(Stdin, "/fd/0"); + else + for (i = 0; i < argc; i++) { + int in = eopen(argv[i], OREAD); + + process(in, argv[i]); + close(in); + } + closeout(&cp); + exits(0); +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/calls.c --- a/sys/src/cmd/calls.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/calls.c Tue Mar 06 23:34:10 2012 +0100 @@ -26,7 +26,7 @@ enum { Printstats = 0, /* flag */ - Maxseen = 400, /* # of instances w/in a function */ + Maxseen = 4000, /* # of instances w/in a function */ Maxdepth = 300, /* max func call tree depth */ Hashsize = 2048, @@ -94,8 +94,7 @@ }; char *aseen[Maxseen]; /* names being gathered within a function */ -Rname *namelist; /* names being tracked */ -Rnamehash nameshash[Hashsize]; +Rnamehash nameshash[Hashsize]; /* names being tracked */ Rname *activelist[Maxdepth]; /* names being output */ String *cppopt; Root *roots; @@ -268,7 +267,7 @@ } /* - * install (np,rp) puts a new instance of a function into the linked list. + * install(np, rp) puts a new instance of a function into the linked list. * It puts a pointer (np) to its own name (returned by place) into its * namepointer, a pointer to the calling routine (rp) into its called-by * pointer, and zero into the calls pointer. It then puts a pointer to @@ -325,8 +324,9 @@ rp = place(name); if (rp == nil) return RINSTERR; + /* declaration in a header file is enough to cause this. */ if (0 && rp->rnamedefined) - warning("function `%s' redefined", name); + warning("function `%s' redeclared", name); rp->rnamedefined = 1; return install(rp, nil); } @@ -818,6 +818,7 @@ * * must fork/exec cpp for each input file. * otherwise we get macro redefinitions and other problems. + * also plan 9's cpp can only process one input file per invocation. */ void scanfiles(int argc, char **argv) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/cb/cb.c --- a/sys/src/cmd/cb/cb.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/cb/cb.c Tue Mar 06 23:34:10 2012 +0100 @@ -33,7 +33,7 @@ plan9 = 1; continue; default: - fprint(2, "cb: illegal option %c\n", *argv[1]); + fprint(2, "cb: illegal option %c\n", (*argv)[1]); exits("boom"); } } @@ -43,6 +43,7 @@ Binit(&stdin, 0, OREAD); input = &stdin; work(); + Bterm(input); } else { while (argc-- > 0){ if ((input = Bopen( *argv, OREAD)) == 0){ @@ -50,6 +51,7 @@ exits("boom"); } work(); + Bterm(input); argv++; } } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/cdfs/dat.h --- a/sys/src/cmd/cdfs/dat.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/cdfs/dat.h Tue Mar 06 23:34:10 2012 +0100 @@ -214,12 +214,12 @@ int mmctype; /* cd, dvd, or bd */ char *dvdtype; /* name of dvd flavour */ int firsttrack; + int invistrack; int ntrack; int nchange; /* compare with the members in Scsi */ ulong changetime; /* " */ int nameok; int writeok; /* writable disc? */ - Tristate blank; /* (not used for anything yet) */ /* * we could combine these attributes into a single variable except * that we discover them separately sometimes. diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/cdfs/mmc.c --- a/sys/src/cmd/cdfs/mmc.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/cdfs/mmc.c Tue Mar 06 23:34:10 2012 +0100 @@ -35,7 +35,7 @@ int pagecmdsz; /* disc characteristics */ - ulong mmcnwa; + long mmcnwa; /* next writable address (block #) */ int nropen; int nwopen; vlong ntotby; @@ -62,6 +62,8 @@ "type-15-unknown", }; +static int getinvistrack(Drive *drive); + static ulong bige(void *p) { @@ -366,11 +368,16 @@ if (vflag) print("mmcprobe: inquiry: %s\n", scsi->inquire); + drive = emalloc(sizeof(Drive)); drive->Scsi = *scsi; drive->Dev = mmcdev; + drive->invistrack = -1; + getinvistrack(drive); + aux = emalloc(sizeof(Mmcaux)); drive->aux = aux; + scsiready(drive); drive->type = getdevtype(drive); if (drive->type != TypeCD) { @@ -458,6 +465,7 @@ mmctrackinfo(Drive *drive, int t, int i) { int n, type, bs; + long newnwa; ulong beg, size; uchar tmode; uchar cmd[10], resp[255]; @@ -525,17 +533,29 @@ drive->writeok = Yes; } + /* + * figure out the first writable block, if we can + */ if(vflag) print(" start %lud end %lud", beg, beg + size - 1); + if(resp[7] & 1) { /* nwa valid? */ + newnwa = bige(&resp[12]); + if (newnwa >= 0) + if (aux->mmcnwa < 0) + aux->mmcnwa = newnwa; + else if (aux->mmcnwa != newnwa) + fprint(2, "nwa is %ld but invis track starts blk %ld\n", + newnwa, aux->mmcnwa); + } /* resp[6] & (1<<7) of zero: invisible track */ - /* t == getinvistrack(): invisible track */ - if(t == Invistrack || resp[7] & 1) { /* invis or nwa valid? */ - aux->mmcnwa = bige(&resp[12]); - if ((long)aux->mmcnwa < 0) /* implausible? */ - aux->mmcnwa = 0; - if (vflag) - print(" nwa %lud", aux->mmcnwa); - } + if(t == Invistrack || t == drive->invistrack) + if (aux->mmcnwa < 0) + aux->mmcnwa = beg; + else if (aux->mmcnwa != beg) + fprint(2, "invis track starts blk %ld but nwa is %ld\n", + beg, aux->mmcnwa); + if (vflag && aux->mmcnwa >= 0) + print(" nwa %lud", aux->mmcnwa); if (vflag) print("\n"); return 0; @@ -712,8 +732,7 @@ drive->erasable = Yes; else if (resp[6] & (1<<1)) /* recordable once? */ drive->recordable = Yes; - else /* factory-pressed disk */ - drive->blank = No; + /* else it's a factory-pressed disk */ drive->mmctype = (cat >= 8? Mmcdvdplus: Mmcdvdminus); return 0; } @@ -801,7 +820,6 @@ drive->erasable = drive->recordable = No; switch (body[2]) { case 'O': /* read-Only */ - drive->blank = No; break; case 'R': /* Recordable */ drive->recordable = Yes; @@ -904,9 +922,10 @@ drive->nchange = drive->Scsi.nchange; drive->changetime = drive->Scsi.changetime; drive->writeok = No; - drive->erasable = drive->recordable = drive->blank = Unset; + drive->erasable = drive->recordable = Unset; + getinvistrack(drive); aux = drive->aux; - aux->mmcnwa = 0; + aux->mmcnwa = -1; aux->nropen = aux->nwopen = 0; aux->ntotby = aux->ntotbk = 0; @@ -924,8 +943,8 @@ */ if((n = mmcreadtoc(drive, Msfbit, 0, resp, sizeof(resp))) < 4) { /* - * on a blank disc in a cd-rw, use readdiscinfo - * to find the track info. + * it could be a blank disc. in case it's a blank disc in a + * cd-rw drive, use readdiscinfo to try to find the track info. */ if(getdiscinfo(drive, resp, sizeof(resp)) < 7) return -1; @@ -935,9 +954,8 @@ first = resp[3]; last = resp[6]; if(vflag) - print("blank disc %d %d\n", first, last); - /* the assumption of blankness may be unwarranted */ - drive->writeok = drive->blank = Yes; + print("tracks %d-%d\n", first, last); + drive->writeok = Yes; } else { first = resp[2]; last = resp[3]; @@ -967,7 +985,6 @@ if (vflag) { fprint(2, "writeok %d", drive->writeok); - /* drive->blank is never used and hard to figure out */ if (drive->recordable != Unset) fprint(2, " recordable %d", drive->recordable); if (drive->erasable != Unset) @@ -1250,12 +1267,13 @@ static long mmcxwrite(Otrack *o, void *v, long nblk) { + int r; uchar cmd[10]; Mmcaux *aux; assert(o->omode == OWRITE); aux = o->drive->aux; - if (aux->mmcnwa == 0 && scsiready(o->drive) < 0) { + if (aux->mmcnwa == -1 && scsiready(o->drive) < 0) { werrstr("device not ready to write"); return -1; } @@ -1272,8 +1290,14 @@ if(vflag) print("%lld ns: write %ld at 0x%lux\n", nsec(), nblk, aux->mmcnwa); + r = scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite); + if (r < 0) + fprint(2, "%s: write error at blk offset %,ld = " + "offset %,lld / bs %ld: %r\n", + argv0, aux->mmcnwa, (vlong)aux->mmcnwa * o->track->bs, + o->track->bs); aux->mmcnwa += nblk; - return scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite); + return r; } static long @@ -1336,13 +1360,14 @@ if(vflag) print("getinvistrack: track #%d session #%d\n", resp[2], resp[3]); + drive->invistrack = resp[2]; return resp[2]; } static Otrack* mmccreate(Drive *drive, int type) { - int bs, invis; + int bs; Mmcaux *aux; Track *t; Otrack *o; @@ -1366,15 +1391,11 @@ return nil; } - invis = getinvistrack(drive); - if (invis < 0) - invis = Invistrack; - /* comment out the returns for now; it should be no big deal - geoff */ - if(mmctrackinfo(drive, invis, Maxtrack)) { + if(mmctrackinfo(drive, drive->invistrack, Maxtrack)) { if (vflag) fprint(2, "mmccreate: mmctrackinfo for invis track %d" - " failed: %r\n", invis); + " failed: %r\n", drive->invistrack); werrstr("disc not writable"); // return nil; } @@ -1382,20 +1403,20 @@ werrstr("cannot set bs mode"); // return nil; } - if(mmctrackinfo(drive, invis, Maxtrack)) { + if(mmctrackinfo(drive, drive->invistrack, Maxtrack)) { if (vflag) fprint(2, "mmccreate: mmctrackinfo for invis track %d" - " (2) failed: %r\n", invis); + " (2) failed: %r\n", drive->invistrack); werrstr("disc not writable 2"); // return nil; } /* special hack for dvd-r: reserve the invisible track */ if (drive->mmctype == Mmcdvdminus && drive->writeok && - drive->recordable == Yes && reserve(drive, invis) < 0) { + drive->recordable == Yes && reserve(drive, drive->invistrack) < 0) { if (vflag) fprint(2, "mmcreate: reserving track %d for dvd-r " - "failed: %r\n", invis); + "failed: %r\n", drive->invistrack); return nil; } @@ -1446,7 +1467,6 @@ void mmcsynccache(Drive *drive) { - int invis; uchar cmd[10]; Mmcaux *aux; @@ -1470,9 +1490,6 @@ aux->ntotby, aux->ntotbk, aux->mmcnwa); } - invis = getinvistrack(drive); - if (invis < 0) - invis = Invistrack; /* * rsc: seems not to work on some drives. * so ignore return code & don't issue on dvd+rw. @@ -1480,11 +1497,12 @@ if(drive->mmctype != Mmcdvdplus || drive->erasable == No) { if (vflag) fprint(2, "closing invisible track %d (not dvd+rw)...\n", - invis); - mmcxclose(drive, Closetrack, invis); + drive->invistrack); + mmcxclose(drive, Closetrack, drive->invistrack); if (vflag) fprint(2, "... done.\n"); } + getinvistrack(drive); /* track # has probably changed */ } /* diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/cpp/nlist.c --- a/sys/src/cmd/cpp/nlist.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/cpp/nlist.c Tue Mar 06 23:34:10 2012 +0100 @@ -161,6 +161,8 @@ dp = "."; fp = ""; fd = 0; + if (argc > 2) + error(FATAL, "Too many file arguments; see cpp(1)"); if (argc > 0) { if ((fp = strrchr(argv[0], '/')) != NULL) { int len = fp - argv[0]; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/disk/9660/cdrdwr.c --- a/sys/src/cmd/disk/9660/cdrdwr.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/disk/9660/cdrdwr.c Tue Mar 06 23:34:10 2012 +0100 @@ -269,11 +269,11 @@ } void -setvolsize(Cdimg *cd, ulong block, ulong size) +setvolsize(Cdimg *cd, uvlong block, ulong size) { assert(block != 0); - Cwseek(cd, (vlong)block * Blocksize + offsetof(Cvoldesc, volsize[0])); + Cwseek(cd, block * Blocksize + offsetof(Cvoldesc, volsize[0])); Cputn(cd, size, 4); } @@ -388,35 +388,67 @@ } void -Cputnl(Cdimg *cd, ulong val, int size) +Cputnl(Cdimg *cd, uvlong val, int size) { switch(size) { default: - sysfatal("bad size %d in bputnl", size); + sysfatal("bad size %d in Cputnl", size); case 2: + if(val >= (1<<16)) + sysfatal("value %llud too big for size %d in Cputnl", + val, size); Cputc(cd, val); Cputc(cd, val>>8); break; case 4: + if(val >= (1ULL<<32)) + sysfatal("value %llud too big for size %d in Cputnl", + val, size); Cputc(cd, val); Cputc(cd, val>>8); Cputc(cd, val>>16); Cputc(cd, val>>24); break; + case 8: + Cputc(cd, val); + Cputc(cd, val>>8); + Cputc(cd, val>>16); + Cputc(cd, val>>24); + Cputc(cd, val>>32); + Cputc(cd, val>>40); + Cputc(cd, val>>48); + Cputc(cd, val>>56); + break; } } void -Cputnm(Cdimg *cd, ulong val, int size) +Cputnm(Cdimg *cd, uvlong val, int size) { switch(size) { default: - sysfatal("bad size %d in bputnl", size); + sysfatal("bad size %d in Cputnm", size); case 2: + if(val >= (1<<16)) + sysfatal("value %llud too big for size %d in Cputnl", + val, size); Cputc(cd, val>>8); Cputc(cd, val); break; case 4: + if(val >= (1ULL<<32)) + sysfatal("value %llud too big for size %d in Cputnl", + val, size); + Cputc(cd, val>>24); + Cputc(cd, val>>16); + Cputc(cd, val>>8); + Cputc(cd, val); + break; + case 8: + Cputc(cd, val>>56); + Cputc(cd, val>>48); + Cputc(cd, val>>40); + Cputc(cd, val>>32); Cputc(cd, val>>24); Cputc(cd, val>>16); Cputc(cd, val>>8); @@ -426,7 +458,7 @@ } void -Cputn(Cdimg *cd, long val, int size) +Cputn(Cdimg *cd, uvlong val, int size) { Cputnl(cd, val, size); Cputnm(cd, val, size); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/disk/9660/iso9660.h --- a/sys/src/cmd/disk/9660/iso9660.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/disk/9660/iso9660.h Tue Mar 06 23:34:10 2012 +0100 @@ -304,12 +304,12 @@ ulong little(void*, int); int parsedir(Cdimg*, Direc*, uchar*, int, char *(*)(uchar*, int)); void setroot(Cdimg*, ulong, ulong, ulong); -void setvolsize(Cdimg*, ulong, ulong); +void setvolsize(Cdimg*, uvlong, ulong); void setpathtable(Cdimg*, ulong, ulong, ulong, ulong); void Cputc(Cdimg*, int); -void Cputnl(Cdimg*, ulong, int); -void Cputnm(Cdimg*, ulong, int); -void Cputn(Cdimg*, long, int); +void Cputnl(Cdimg*, uvlong, int); +void Cputnm(Cdimg*, uvlong, int); +void Cputn(Cdimg*, uvlong, int); void Crepeat(Cdimg*, int, int); void Cputs(Cdimg*, char*, int); void Cwrite(Cdimg*, void*, int); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/disk/mbr.c --- a/sys/src/cmd/disk/mbr.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/disk/mbr.c Tue Mar 06 23:34:10 2012 +0100 @@ -145,10 +145,16 @@ if(disk->type == Tfloppy) fatal("will not install mbr on floppy"); - if(disk->secsize != 512) - fatal("secsize %d invalid", disk->secsize); + /* + * we need to cope with 4k-byte sectors on some newer disks. + * we're only interested in 512 bytes of mbr, so + * on 4k disks, rely on /dev/sd to read-modify-write. + */ + secsize = 512; + if(disk->secsize != secsize) + fprint(2, "%s: sector size %lld not %ld, should be okay\n", + argv0, disk->secsize, secsize); - secsize = disk->secsize; buf = malloc(secsize*(disk->s+1)); mbr = malloc(secsize*disk->s); if(buf == nil || mbr == nil) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/fossil/cache.c --- a/sys/src/cmd/fossil/cache.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/fossil/cache.c Tue Mar 06 23:34:10 2012 +0100 @@ -9,6 +9,9 @@ typedef struct BAddr BAddr; enum { + Nowaitlock, + Waitlock, + BadHeap = ~0, }; @@ -112,14 +115,12 @@ static void cacheCheck(Cache*); static void unlinkThread(void *a); static void flushThread(void *a); -static void flushBody(Cache *c); static void unlinkBody(Cache *c); static int cacheFlushBlock(Cache *c); static void cacheSync(void*); static BList *blistAlloc(Block*); static void blistFree(Cache*, BList*); static void doRemoveLink(Cache*, BList*); -static void doRemoveLinkList(Cache*, BList*); /* * Mapping from local block type to Venti type @@ -473,7 +474,7 @@ static Block* cacheLocalLookup(Cache *c, int part, u32int addr, u32int vers) { - return _cacheLocalLookup(c, part, addr, vers, 1, 0); + return _cacheLocalLookup(c, part, addr, vers, Waitlock, 0); } @@ -1194,7 +1195,8 @@ } lockfail = 0; - bb = _cacheLocalLookup(c, p->part, p->addr, p->vers, 0, &lockfail); + bb = _cacheLocalLookup(c, p->part, p->addr, p->vers, Nowaitlock, + &lockfail); if(bb == nil){ if(lockfail) return 0; @@ -2003,7 +2005,8 @@ return 0; p = c->baddr + c->br; c->br++; - b = _cacheLocalLookup(c, p->part, p->addr, p->vers, 0, &lockfail); + b = _cacheLocalLookup(c, p->part, p->addr, p->vers, Nowaitlock, + &lockfail); if(b && blockWrite(b)){ c->nflush++; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/fossil/flfmt.c --- a/sys/src/cmd/fossil/flfmt.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/fossil/flfmt.c Tue Mar 06 23:34:10 2012 +0100 @@ -8,7 +8,6 @@ static void usage(void); static u64int fdsize(int fd); static void partition(int fd, int bsize, Header *h); -static void writeBlock(int fd, uchar *buf, int bsize, ulong bn); static u64int unittoull(char *s); static u32int blockAlloc(int type, u32int tag); static void blockRead(int part, u32int addr); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/fossil/source.c --- a/sys/src/cmd/fossil/source.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/fossil/source.c Tue Mar 06 23:34:10 2012 +0100 @@ -7,7 +7,6 @@ static int sizeToDepth(uvlong s, int psize, int dsize); static u32int tagGen(void); static Block *sourceLoad(Source *r, Entry *e); -static Block *sourceLoadUnlocked(Source *r, Entry *e); static int sourceShrinkDepth(Source*, Block*, Entry*, int); static int sourceShrinkSize(Source*, Entry*, uvlong); static int sourceGrowDepth(Source*, Block*, Entry*, int); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ip/ftpd.c --- a/sys/src/cmd/ip/ftpd.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/ip/ftpd.c Tue Mar 06 23:34:10 2012 +0100 @@ -1152,6 +1152,8 @@ int nf, r; Dir *d; + if(arg == 0) + return reply("501 bad site command"); nf = tokenize(arg, f, nelem(f)); if(nf != 3 || cistrcmp(f[0], "chmod") != 0) return reply("501 bad site command"); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ip/tftpd.c --- a/sys/src/cmd/ip/tftpd.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/ip/tftpd.c Tue Mar 06 23:34:10 2012 +0100 @@ -219,8 +219,10 @@ name, val); } *op->valp = n; - syslog(dbg, flog, "tftpd %d setting %s to %d", - pid, name, n); + /* incoming 0 for tsize is uninteresting */ + if(cistrcmp("tsize", op->name) != 0) + syslog(dbg, flog, "tftpd %d setting %s to client's %d", + pid, name, n); return op; } return nil; @@ -234,25 +236,59 @@ dp = dirstat(file); if (dp == nil) - return 0; + return -1; size = dp->length; free(dp); return size; } +/* copy word into bp iff it fits before ep, returns bytes to advance bp. */ static int -options(int fd, char *buf, char *file, ushort oper, char *p, int dlen) +emits(char *word, char *bp, char *ep) { - int nmlen, vallen, nopts; + int len; + + len = strlen(word) + 1; + if (bp + len >= ep) + return -1; + strcpy(bp, word); + return len; +} + +/* format number into bp iff it fits before ep. */ +static int +emitn(vlong n, char *bp, char *ep) +{ + char numb[32]; + + snprint(numb, sizeof numb, "%lld", n); + return emits(numb, bp, ep); +} + +/* + * send an OACK packet to respond to options. bail early with -1 on error. + * p is the packet containing the options. + * + * hack: bandt (viaducts) uses smaller mtu than ether's + * (1400 bytes for tcp mss of 1300 bytes), + * so offer at most bandt's mtu minus headers, + * to avoid failure of pxe booting via viaduct. + * there's an exception for the cavium's u-boot. + */ +static int +options(int fd, char *buf, int bufsz, char *file, ushort oper, char *p, int dlen) +{ + int nmlen, vallen, olen, nopts; vlong size; - char *val, *bp; + char *val, *bp, *ep; Opt *op; buf[0] = 0; buf[1] = Tftp_OACK; bp = buf + Opsize; + ep = buf + bufsz; nopts = 0; - while (dlen > 0 && *p != '\0') { + for (; dlen > 0 && *p != '\0'; p = val + vallen, bp += olen) { nmlen = strlen(p) + 1; /* include NUL */ if (nmlen > dlen) break; @@ -267,43 +303,49 @@ dlen -= vallen; nopts++; + olen = 0; op = handleopt(fd, p, val); - if (op) { - /* append OACK response to buf */ - sprint(bp, "%s", p); - bp += nmlen; - if (oper == Tftp_READ && cistrcmp(p, "tsize") == 0) { - size = filesize(file); - sprint(bp, "%lld", size); - syslog(dbg, flog, "tftpd %d %s tsize is %,lld", - pid, file, size); + if (op == nil) + continue; + + /* append OACK response to buf */ + nmlen = emits(p, bp, ep); /* option name */ + if (nmlen < 0) + return -1; + bp += nmlen; + + if (oper == Tftp_READ && cistrcmp(p, "tsize") == 0) { + size = filesize(file); + if (size == -1) { + nak(fd, Errnotfound, "no such file"); + syslog(dbg, flog, "tftpd tsize for " + "non-existent file %s", file); + // *op->valp = 0; + // olen = emits("0", bp, ep); + return -1; } - /* - * hack: bandt (viaducts) uses smaller mtu than ether's - * (1400 bytes for tcp mss of 1300 bytes), - * so offer at most bandt's mtu minus headers, - * to avoid failure of pxe booting via viaduct. - * there's an exception for the cavium's u-boot. - */ - else if (oper == Tftp_READ && - cistrcmp(p, "blksize") == 0 && - blksize > Bandtblksz && blksize != Bcavium) { - blksize = Bandtblksz; - sprint(bp, "%d", blksize); - syslog(dbg, flog, - "tftpd %d overriding blksize to %d", - pid, blksize); - } else - strcpy(bp, val); /* use requested value */ - bp += strlen(bp) + 1; - } - p = val + vallen; + *op->valp = size; + olen = emitn(size, bp, ep); + syslog(dbg, flog, "tftpd %d %s tsize is %,lld", + pid, file, size); + } else if (oper == Tftp_READ && cistrcmp(p, "blksize") == 0 && + blksize > Bandtblksz && blksize != Bcavium) { + *op->valp = blksize = Bandtblksz; + olen = emitn(blksize, bp, ep); + syslog(dbg, flog, "tftpd %d overriding blksize to %d", + pid, blksize); + } else + olen = emits(val, bp, ep); /* use requested value */ } if (nopts == 0) return 0; /* no options actually seen */ + + if (bp + 3 >= ep) + return -1; *bp++ = '\0'; *bp++ = '\0'; /* overkill */ *bp++ = '\0'; + if (write(fd, buf, bp - buf) < bp - buf) { syslog(dbg, flog, "tftpd network write error on oack to %s: %r", raddr); @@ -314,25 +356,6 @@ return nopts; } -/* this doesn't stop the cavium from barging ahead */ -//static void -//sendnoopts(int fd, char *name) -//{ -// char buf[64]; -// -// memset(buf, 0, sizeof buf); -// buf[0] = 0; -// buf[1] = Tftp_OACK; -// -// if(write(fd, buf, sizeof buf) < sizeof buf) { -// syslog(dbg, flog, "tftpd network write error on %s oack to %s: %r", -// name, raddr); -// sysfatal("tftpd: network write error: %r"); -// } -// if(Debug) -// syslog(dbg, flog, "tftpd oack: no options to %s", raddr); -//} - static void optlog(char *bytes, char *p, int dlen) { @@ -347,6 +370,65 @@ syslog(dbg, flog, "%s", bytes); } +/* + * replace one occurrence of %[ICE] with ip, cfgpxe name, or ether mac, resp. + * we can't easily use $ because u-boot has stranger quoting rules than sh. + */ +char * +mapname(char *file) +{ + int nf; + char *p, *newnm, *cur, *arpf, *ln, *remip, *bang; + char *fields[4]; + Biobuf *arp; + + p = strchr(file, '%'); + if (p == nil || p[1] == '\0') + return strdup(file); + + remip = strdup(raddr); + newnm = mallocz(strlen(file) + Maxpath, 1); + if (remip == nil || newnm == nil) + sysfatal("out of memory"); + + bang = strchr(remip, '!'); + if (bang) + *bang = '\0'; /* remove !port */ + + memmove(newnm, file, p - file); /* copy up to % */ + cur = newnm + strlen(newnm); + switch(p[1]) { + case 'I': + strcpy(cur, remip); /* remote's IP */ + break; + case 'C': + strcpy(cur, "/cfg/pxe/"); + cur += strlen(cur); + /* fall through */ + case 'E': + /* look up remote's IP in /net/arp to get mac. */ + arpf = smprint("%s/arp", net); + arp = Bopen(arpf, OREAD); + free(arpf); + if (arp == nil) + break; + /* read lines looking for remip in 3rd field of 4 */ + while ((ln = Brdline(arp, '\n')) != nil) { + ln[Blinelen(arp)-1] = 0; + nf = tokenize(ln, fields, nelem(fields)); + if (nf >= 4 && strcmp(fields[2], remip) == 0) { + strcpy(cur, fields[3]); + break; + } + } + Bterm(arp); + break; + } + strcat(newnm, p + 2); /* tail following %x */ + free(remip); + return newnm; +} + void doserve(int fd) { @@ -368,6 +450,9 @@ p = mode; while(*p && dlen--) p++; + + file = mapname(file); /* we don't free the result; minor leak */ + if(dlen == 0) { nak(fd, 0, "bad tftpmode"); close(fd); @@ -379,7 +464,8 @@ if(op != Tftp_READ && op != Tftp_WRITE) { nak(fd, Errbadop, "Illegal TFTP operation"); close(fd); - syslog(dbg, flog, "tftpd %d bad request %d %s", pid, op, raddr); + syslog(dbg, flog, "tftpd %d bad request %d (%s) %s", pid, op, + (op < nelem(opnames)? opnames[op]: "gok"), raddr); return; } @@ -408,7 +494,9 @@ if(Debug) optlog(bytes, p, dlen); - opts = options(fd, bytes, file, op, p, dlen); + opts = options(fd, bytes, sizeof bytes, file, op, p, dlen); + if (opts < 0) + return; } if(op == Tftp_READ) sendfile(fd, file, mode, opts); @@ -481,12 +569,13 @@ uchar buf[Maxsegsize+Hdrsize]; char errbuf[Maxerr]; + file = -1; syslog(dbg, flog, "tftpd %d send file '%s' %s to %s", pid, name, mode, raddr); name = sunkernel(name); if(name == 0){ nak(fd, 0, "not in our database"); - return; + goto error; } notify(catcher); @@ -495,7 +584,7 @@ if(file < 0) { errstr(errbuf, sizeof errbuf); nak(fd, 0, errbuf); - return; + goto error; } block = 0; rexmit = Ackok; @@ -521,7 +610,7 @@ if(n < 0) { errstr(errbuf, sizeof errbuf); nak(fd, 0, errbuf); - return; + goto error; } txtry = 0; } @@ -547,6 +636,8 @@ if(ret != blksize+Hdrsize && rexmit == Ackok) break; } + syslog(dbg, flog, "tftpd %d done sending file '%s' %s to %s", + pid, name, mode, raddr); error: close(fd); close(file); @@ -583,7 +674,11 @@ name); goto error; } - if(n <= Hdrsize) { + /* + * NB: not `<='; just a header is legal and happens when + * file being read is a multiple of segment-size bytes long. + */ + if(n < Hdrsize) { syslog(dbg, flog, "tftpd: short read from network, reading %s", name); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/jpg/gif.c --- a/sys/src/cmd/jpg/gif.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/jpg/gif.c Tue Mar 06 23:34:10 2012 +0100 @@ -14,6 +14,7 @@ ulong outchan = CMAP8; Image **allims; Image **allmasks; +Rawimage **allimages; int which; int defaultcolor = 1; @@ -52,7 +53,12 @@ border(screen, r, -Border, nil, ZP); r.min.x += allims[which]->r.min.x - allims[0]->r.min.x; r.min.y += allims[which]->r.min.y - allims[0]->r.min.y; - drawop(screen, r, allims[which], allmasks[which], allims[which]->r.min, S); + if(which > 0 && allimages[which]->gifflags & TRANSP) + drawop(screen, r, allims[which], allmasks[which], + allims[which]->r.min, SoverD); + else + drawop(screen, r, allims[which], allmasks[which], + allims[which]->r.min, S); flushimage(display, 1); } @@ -229,7 +235,7 @@ * r is used only for reference; the image is already in c. */ void -whiteout(Rawimage *r, Rawimage *c) +blackout(Rawimage *r, Rawimage *c) { int i, trindex; uchar *rp, *cp; @@ -241,9 +247,9 @@ for(i=0; ichanlen; i++){ if(*rp == trindex){ *cp++ = 0x00; - *cp++ = 0xFF; - *cp++ = 0xFF; - *cp++ = 0xFF; + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; }else{ *cp++ = 0xFF; cp += 3; @@ -254,7 +260,7 @@ for(i=0; ichanlen; i++){ if(*rp == trindex){ *cp++ = 0x00; - *cp++ = 0xFF; + *cp++ = 0x00; }else{ *cp++ = 0xFF; cp++; @@ -349,6 +355,7 @@ } } + allimages = images; allims = ims; allmasks = masks; loopcount = images[0]->gifloopcount; @@ -380,7 +387,7 @@ if(nineflag){ if(images[0]->gifflags&TRANSP){ addalpha(rgbv[0]); - whiteout(images[0], rgbv[0]); + blackout(images[0], rgbv[0]); } chantostr(buf, outchan); print("%11s %11d %11d %11d %11d ", buf, @@ -392,7 +399,7 @@ }else if(cflag){ if(images[0]->gifflags&TRANSP){ addalpha(rgbv[0]); - whiteout(images[0], rgbv[0]); + blackout(images[0], rgbv[0]); } if(writerawimage(1, rgbv[0]) < 0){ fprint(2, "gif: %s: write error: %r\n", name); @@ -403,6 +410,7 @@ Return: allims = nil; allmasks = nil; + allimages = nil; for(k=0; images[k]; k++){ for(j=0; jnchans; j++) free(images[k]->chans[j]); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/lex/ldefs.h --- a/sys/src/cmd/lex/ldefs.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/lex/ldefs.h Tue Mar 06 23:34:10 2012 +0100 @@ -155,7 +155,7 @@ extern int mn0(int); extern int mn1(int, int); extern int mnp(int, void*); -extern int mn2(int, int, int); +extern int mn2(int, int, uintptr); extern void munputc(int); extern void munputs(uchar *); extern void *myalloc(int, int); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/lex/parser.y --- a/sys/src/cmd/lex/parser.y Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/lex/parser.y Tue Mar 06 23:34:10 2012 +0100 @@ -196,7 +196,7 @@ } } | SCON r - ={ $$.i = mn2(RSCON,$2.i,$1.i); } + ={ $$.i = mn2(RSCON,$2.i,(uintptr)$1.cp); } | '^' r ={ $$.i = mn1(CARAT,$2.i); } | r '$' diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/lex/sub1.c --- a/sys/src/cmd/lex/sub1.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/lex/sub1.c Tue Mar 06 23:34:10 2012 +0100 @@ -302,7 +302,7 @@ } int -mn2(int a, int d, int c) +mn2(int a, int d, uintptr c) { name[tptr] = a; left[tptr] = d; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ndb/convM2DNS.c --- a/sys/src/cmd/ndb/convM2DNS.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/ndb/convM2DNS.c Tue Mar 06 23:34:10 2012 +0100 @@ -6,9 +6,9 @@ typedef struct Scan Scan; struct Scan { - uchar *base; - uchar *p; - uchar *ep; + uchar *base; /* input buffer */ + uchar *p; /* current position */ + uchar *ep; /* byte after the end */ char *err; char errbuf[256]; /* hold a formatted error sometimes */ @@ -17,16 +17,6 @@ int trunc; /* flag: input truncated */ }; -#define NAME(x) gname(x, rp, sp) -#define SYMBOL(x) (x = gsym(rp, sp)) -#define STRING(x) (x = gstr(rp, sp)) -#define USHORT(x) (x = gshort(rp, sp)) -#define ULONG(x) (x = glong(rp, sp)) -#define UCHAR(x) (x = gchar(rp, sp)) -#define V4ADDR(x) (x = gv4addr(rp, sp)) -#define V6ADDR(x) (x = gv6addr(rp, sp)) -#define BYTES(x, y) (y = gbytes(rp, sp, &x, len - (sp->p - data))) - static int errneg(RR *rp, Scan *sp, int actual) { @@ -56,7 +46,7 @@ /* hack to cope with servers that don't set Ftrunc when they should */ if (remain < Maxudp && need > Maxudp) sp->trunc = 1; - if (debug) + if (debug && rp) dnslog("malformed rr: %R", rp); return 0; } @@ -236,6 +226,10 @@ goto err; pointer = 0; p = sp->p; + if (p == nil) { + dnslog("gname: %R: nil sp->p", rp); + goto err; + } toend = to + Domlen; for(len = 0; *p && p < sp->ep; len += (pointer? 0: n+1)) { n = 0; @@ -312,24 +306,35 @@ // where); if (sp->rcode == Rok) sp->rcode = Rformat; - return (uchar)type << 8 | type >> 8; + type >>= 8; } return type; } +#define NAME(x) gname(x, rp, sp) +#define SYMBOL(x) ((x) = gsym(rp, sp)) +#define STRING(x) ((x) = gstr(rp, sp)) +#define USHORT(x) ((x) = gshort(rp, sp)) +#define ULONG(x) ((x) = glong(rp, sp)) +#define UCHAR(x) ((x) = gchar(rp, sp)) +#define V4ADDR(x) ((x) = gv4addr(rp, sp)) +#define V6ADDR(x) ((x) = gv6addr(rp, sp)) +#define BYTES(x, y) ((y) = gbytes(rp, sp, &(x), len - (sp->p - data))) + /* * convert the next RR from a message */ static RR* convM2RR(Scan *sp, char *what) { - int type, class, len; + int type, class, len, left; char dname[Domlen+1]; uchar *data; - RR *rp = nil; + RR *rp; Txt *t, **l; retry: + rp = nil; NAME(dname); USHORT(type); USHORT(class); @@ -341,8 +346,10 @@ ULONG(rp->ttl); rp->ttl += now; - USHORT(len); + USHORT(len); /* length of data following */ data = sp->p; + assert(data != nil); + left = sp->ep - sp->p; /* * ms windows generates a lot of badly-formatted hints. @@ -350,21 +357,23 @@ * it also generates answers in which p overshoots ep by exactly * one byte; this seems to be harmless, so don't log them either. */ - if (sp->ep - sp->p < len && + if (len > left && !(strcmp(what, "hints") == 0 || sp->p == sp->ep + 1 && strcmp(what, "answers") == 0)) - errtoolong(rp, sp, sp->ep - sp->p, len, "convM2RR"); + errtoolong(rp, sp, left, len, "convM2RR"); if(sp->err || sp->rcode || sp->stop){ rrfree(rp); return nil; } + /* even if we don't log an error message, truncate length to fit data */ + if (len > left) + len = left; switch(type){ default: /* unknown type, just ignore it */ sp->p = data + len; rrfree(rp); - rp = nil; goto retry; case Thinfo: SYMBOL(rp->cpu); @@ -493,8 +502,9 @@ { char dname[Domlen+1]; int type, class; - RR *rp = nil; + RR *rp; + rp = nil; NAME(dname); USHORT(type); USHORT(class); @@ -535,7 +545,8 @@ *l = rp; l = &rp->next; } -// setmalloctag(first, getcallerpc(&sp)); +// if(first) +// setmalloctag(first, getcallerpc(&sp)); return first; } @@ -553,15 +564,15 @@ Scan scan; Scan *sp; - if (codep) - *codep = Rok; assert(len >= 0); + assert(buf != nil); sp = &scan; memset(sp, 0, sizeof *sp); sp->base = sp->p = buf; sp->ep = buf + len; sp->err = nil; sp->errbuf[0] = '\0'; + sp->rcode = Rok; memset(m, 0, sizeof *m); USHORT(m->id); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ndb/dnresolve.c --- a/sys/src/cmd/ndb/dnresolve.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/ndb/dnresolve.c Tue Mar 06 23:34:10 2012 +0100 @@ -646,7 +646,7 @@ mp->qdcount = mp->ancount = mp->nscount = mp->arcount = 0; } -/* timed read of reply. sets srcip */ +/* timed read of reply. sets srcip. ibuf must be 64K to handle tcp answers. */ static int readnet(Query *qp, int medium, uchar *ibuf, uvlong endms, uchar **replyp, uchar *srcip) @@ -1527,7 +1527,6 @@ static ulong lastmount; /* use alloced buffers rather than ones from the stack */ - // ibuf = emalloc(Maxudpin+Udphdrsize); ibuf = emalloc(64*1024); /* max. tcp reply size */ obuf = emalloc(Maxudp+Udphdrsize); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ndb/dnudpserver.c --- a/sys/src/cmd/ndb/dnudpserver.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/ndb/dnudpserver.c Tue Mar 06 23:34:10 2012 +0100 @@ -283,19 +283,21 @@ ctl = announce(datafile, dir); if(ctl < 0){ if(!whined++) - warning("can't announce on dns udp port"); + warning("can't announce on %s", datafile); return -1; } - snprint(datafile, sizeof(datafile), "%s/data", dir); /* turn on header style interface */ if(write(ctl, hmsg, strlen(hmsg)) != strlen(hmsg)) abort(); /* hmsg */ + + snprint(datafile, sizeof(datafile), "%s/data", dir); data = open(datafile, ORDWR); if(data < 0){ close(ctl); if(!whined++) - warning("can't announce on dns udp port"); + warning("can't open %s to announce on dns udp port", + datafile); return -1; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ndb/inform.c --- a/sys/src/cmd/ndb/inform.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/ndb/inform.c Tue Mar 06 23:34:10 2012 +0100 @@ -24,11 +24,6 @@ [10] "domain name not in zone", }; -char *dnsrch[] = { - "dnsdomain", - "dom", -}; - void usage(void) { @@ -98,12 +93,12 @@ { int debug, len, fd; uint err; - char *sysname, *dnsdomain, *dom, *ns, net[32]; + char *sysname, *dnsdomain, *dom, *inform, *ns, net[32]; uchar *p, buf[4096], addr[IPv4addrlen], v6addr[IPaddrlen]; ushort txid; Ndb *db; Ndbtuple *t, *tt; - static char *query[] = { "dom", "dnsdomain", "ns", }; + static char *query[] = { "dom", "dnsdomain", "ns", "inform" }; fmtinstall('I', eipfmt); fmtinstall('V', eipfmt); @@ -112,6 +107,7 @@ debug = 0; ns = nil; dom = nil; + inform = nil; dnsdomain = nil; ARGBEGIN{ case 'd': @@ -133,16 +129,22 @@ if((db = ndbopen(nil)) == nil) sysfatal("can't open ndb: %r"); tt = ndbipinfo(db, "sys", sysname, query, nelem(query)); - for(t = tt; t; t = t->entry) + for(t = tt; t; t = t->entry){ if(strcmp(t->attr, "ns") == 0) ns = t->val; else if(strcmp(t->attr, "dom") == 0) dom = t->val; else if(strcmp(t->attr, "dnsdomain") == 0) dnsdomain = t->val; + else if(strcmp(t->attr, "inform") == 0) + inform = t->val; + } + ndbfree(tt); ndbclose(db); + if(inform) + dom = inform; if(!ns) sysfatal("no relevant ns="); if(!dom) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/nntpfs.c --- a/sys/src/cmd/nntpfs.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/nntpfs.c Tue Mar 06 23:34:10 2012 +0100 @@ -213,7 +213,7 @@ n->currentgroup = nil; close(n->fd); if((n->fd = dial(n->addr, nil, nil, nil)) < 0){ - snprint(n->response, sizeof n->response, "dial: %r"); + snprint(n->response, sizeof n->response, "dial %s: %r", n->addr); return -1; } Binit(&n->br, n->fd, OREAD); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/page/gfx.c --- a/sys/src/cmd/page/gfx.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/page/gfx.c Tue Mar 06 23:34:10 2012 +0100 @@ -87,6 +87,7 @@ static Image* gfxdrawpage(Document *doc, int page) { + setlabel(gfxpagename(doc, page)); GfxInfo *gfx = doc->extra; return convert(gfx->g+page); } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/page/page.h --- a/sys/src/cmd/page/page.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/page/page.h Tue Mar 06 23:34:10 2012 +0100 @@ -25,6 +25,7 @@ Document *inittroff(Biobuf*, int, char**, uchar*, int); Document *initdvi(Biobuf*, int, char**, uchar*, int); Document *initmsdoc(Biobuf*, int, char**, uchar*, int); +void setlabel(char *); void viewer(Document*); extern Cursor reading; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/page/util.c --- a/sys/src/cmd/page/util.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/page/util.c Tue Mar 06 23:34:10 2012 +0100 @@ -129,3 +129,22 @@ _exits(0); return -1; /* not reached */ } + +/* try to update the label, but don't fail on any errors */ +void +setlabel(char *label) +{ + char *s; + int fd; + + s = smprint("%s/label", display->windir); + if (s == nil) + return; + fd = open(s, OWRITE); + free(s); + if(fd >= 0){ + write(fd, label, strlen(label)); + close(fd); + } + werrstr(""); +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/page/view.c --- a/sys/src/cmd/page/view.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/page/view.c Tue Mar 06 23:34:10 2012 +0100 @@ -317,6 +317,8 @@ midmenu.gen = 0; midmenu.lasthit = Next; + if(doc->docname != nil) + setlabel(doc->docname); showpage(page, &menu); esetcursor(nil); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/pump.c --- a/sys/src/cmd/pump.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/pump.c Tue Mar 06 23:34:10 2012 +0100 @@ -153,7 +153,8 @@ lock(&arithlock); if(c != n) { - fprint(2, "%s: write error: %r\n", argv0); + fprint(2, "%s: write error at offset %,lld: %r\n", + argv0, seek(f, 0, 1)); break; } nout += c; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/rc/pfnc.c --- a/sys/src/cmd/rc/pfnc.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/rc/pfnc.c Tue Mar 06 23:34:10 2012 +0100 @@ -48,7 +48,7 @@ Xglob, "Xglob", Xrdfn, "Xrdfn", Xsimple, "Xsimple", - Xrdfn, "Xrdfn", + Xsub, "Xsub", Xqdol, "Xqdol", 0}; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/scuzz/cdaudio.c --- a/sys/src/cmd/scuzz/cdaudio.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/scuzz/cdaudio.c Tue Mar 06 23:34:10 2012 +0100 @@ -1,7 +1,7 @@ #include #include #include - +#include #include "scsireq.h" extern Biobuf bout; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/scuzz/cdr.c --- a/sys/src/cmd/scuzz/cdr.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/scuzz/cdr.c Tue Mar 06 23:34:10 2012 +0100 @@ -1,6 +1,6 @@ #include #include - +#include #include "scsireq.h" long diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/scuzz/changer.c --- a/sys/src/cmd/scuzz/changer.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/scuzz/changer.c Tue Mar 06 23:34:10 2012 +0100 @@ -1,6 +1,6 @@ #include #include - +#include #include "scsireq.h" long diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/scuzz/scsireq.c --- a/sys/src/cmd/scuzz/scsireq.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/scuzz/scsireq.c Tue Mar 06 23:34:10 2012 +0100 @@ -5,6 +5,7 @@ * no luns * and incomplete in many other ways */ +#include #include "scsireq.h" enum { diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/scuzz/scsireq.h --- a/sys/src/cmd/scuzz/scsireq.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/scuzz/scsireq.h Tue Mar 06 23:34:10 2012 +0100 @@ -68,67 +68,6 @@ Status_RO = 0x85, /* device is read-only */ }; -enum { /* SCSI command codes */ - ScmdTur = 0x00, /* test unit ready */ - ScmdRewind = 0x01, /* rezero/rewind */ - ScmdRsense = 0x03, /* request sense */ - ScmdFormat = 0x04, /* format unit */ - ScmdRblimits = 0x05, /* read block limits */ - ScmdRead = 0x08, /* read */ - ScmdWrite = 0x0A, /* write */ - ScmdSeek = 0x0B, /* seek */ - ScmdFmark = 0x10, /* write filemarks */ - ScmdSpace = 0x11, /* space forward/backward */ - ScmdInq = 0x12, /* inquiry */ - ScmdMselect6 = 0x15, /* mode select */ - ScmdMselect10 = 0x55, /* mode select */ - ScmdMsense6 = 0x1A, /* mode sense */ - ScmdMsense10 = 0x5A, /* mode sense */ - ScmdStart = 0x1B, /* start/stop unit */ - ScmdRcapacity = 0x25, /* read capacity */ - ScmdExtread = 0x28, /* extended read */ - ScmdExtwrite = 0x2A, /* extended write */ - ScmdExtseek = 0x2B, /* extended seek */ - - ScmdSynccache = 0x35, /* flush cache */ - ScmdRTOC = 0x43, /* read TOC data */ - ScmdRdiscinfo = 0x51, /* read disc information */ - ScmdRtrackinfo = 0x52, /* read track information */ - ScmdReserve = 0x53, /* reserve track */ - ScmdBlank = 0xA1, /* blank *-RW media */ - - ScmdCDpause = 0x4B, /* pause/resume */ - ScmdCDstop = 0x4E, /* stop play/scan */ - ScmdCDplay = 0xA5, /* play audio */ - ScmdCDload = 0xA6, /* load/unload */ - ScmdCDscan = 0xBA, /* fast forward/reverse */ - ScmdCDstatus = 0xBD, /* mechanism status */ - Scmdgetconf = 0x46, /* get configuration */ - - ScmdEInitialise = 0x07, /* initialise element status */ - ScmdMMove = 0xA5, /* move medium */ - ScmdEStatus = 0xB8, /* read element status */ - ScmdMExchange = 0xA6, /* exchange medium */ - ScmdEposition = 0x2B, /* position to element */ - - ScmdReadDVD = 0xAD, /* read dvd structure */ - ScmdReportKey = 0xA4, /* read dvd key */ - ScmdSendKey = 0xA3, /* write dvd key */ - - ScmdClosetracksess= 0x5B, - ScmdRead12 = 0xA8, - ScmdSetcdspeed = 0xBB, - ScmdReadcd = 0xBE, - - /* vendor-specific */ - ScmdFwaddr = 0xE2, /* first writeable address */ - ScmdTreserve = 0xE4, /* reserve track */ - ScmdTinfo = 0xE5, /* read track info */ - ScmdTwrite = 0xE6, /* write track */ - ScmdMload = 0xE7, /* medium load/unload */ - ScmdFixation = 0xE9, /* fixation */ -}; - enum { /* sense data byte 0 */ Sd0valid = 0x80, /* valid sense data present */ diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/scuzz/scuzz.c --- a/sys/src/cmd/scuzz/scuzz.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/scuzz/scuzz.c Tue Mar 06 23:34:10 2012 +0100 @@ -1,7 +1,7 @@ #include #include #include - +#include #include "scsireq.h" enum { /* fundamental constants/defaults */ @@ -30,7 +30,7 @@ char *help; } ScsiCmd; -static ScsiCmd scsicmd[]; +static ScsiCmd scsicmds[]; static vlong vlmin(vlong a, vlong b) @@ -1518,7 +1518,7 @@ p = argv[0]; else p = 0; - for(cp = scsicmd; cp->name; cp++){ + for(cp = scsicmds; cp->name; cp++){ if(p == 0 || strcmp(p, cp->name) == 0) Bprint(&bout, "%s\n", cp->help); } @@ -1601,7 +1601,7 @@ return status; } -static ScsiCmd scsicmd[] = { +static ScsiCmd scsicmds[] = { { "ready", cmdready, 1, /*[0x00]*/ "ready", }, @@ -1908,7 +1908,7 @@ switch(ac = parse(ap, av, nelem(av))){ default: - for(cp = scsicmd; cp->name; cp++){ + for(cp = scsicmds; cp->name; cp++){ if(strcmp(cp->name, av[0]) == 0) break; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/dstep.c --- a/sys/src/cmd/spin/dstep.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/dstep.c Tue Mar 06 23:34:10 2012 +0100 @@ -12,7 +12,7 @@ #include "spin.h" #include "y.tab.h" -#define MAXDSTEP 1024 /* was 512 */ +#define MAXDSTEP 2048 /* was 512 */ char *NextLab[64]; int Level=0, GenCode=0, IsGuard=0, TestOnly=0; @@ -21,7 +21,7 @@ static int Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP]; static void putCode(FILE *, Element *, Element *, Element *, int); -extern int Pid, claimnr, separate, OkBreak; +extern int Pid, separate, OkBreak; static void Sourced(int n, int special) @@ -59,7 +59,7 @@ if (Tojump[j] == Jumpto[i]) break; if (j == Tj) - { char buf[12]; + { char buf[16]; if (Jumpto[i] == OkBreak) { if (!LastGoto) fprintf(fd, "S_%.3d_0: /* break-dest */\n", @@ -164,7 +164,7 @@ break; case ELSE: if (inh++ > 0) fprintf(fd, " || "); -/* 4.2.5 */ if (Pid != claimnr) +/* 4.2.5 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1 /* else */)"); else fprintf(fd, "(1 /* else */)"); @@ -184,17 +184,17 @@ case 's': if (inh++ > 0) fprintf(fd, " || "); fprintf(fd, "("); TestOnly=1; -/* 4.2.1 */ if (Pid != claimnr) fprintf(fd, "(boq == -1) && "); +/* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1) && "); putstmnt(fd, ee->n, ee->seqno); fprintf(fd, ")"); TestOnly=0; break; case 'c': if (inh++ > 0) fprintf(fd, " || "); fprintf(fd, "("); TestOnly=1; - if (Pid != claimnr) + if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1 && "); putstmnt(fd, ee->n->lft, e->seqno); - if (Pid != claimnr) + if (!pid_is_claim(Pid)) fprintf(fd, ")"); fprintf(fd, ")"); TestOnly=0; break; @@ -245,7 +245,7 @@ case 's': fprintf(fd, "if ("); #if 1 -/* 4.2.1 */ if (Pid != claimnr) fprintf(fd, "(boq != -1) || "); +/* 4.2.1 */ if (!pid_is_claim(Pid)) fprintf(fd, "(boq != -1) || "); #endif fprintf(fd, "!("); TestOnly=1; putstmnt(fd, s->frst->n, s->frst->seqno); @@ -253,7 +253,7 @@ break; case 'c': fprintf(fd, "if (!("); - if (Pid != claimnr) fprintf(fd, "boq == -1 && "); + if (!pid_is_claim(Pid)) fprintf(fd, "boq == -1 && "); TestOnly=1; putstmnt(fd, s->frst->n->lft, s->frst->seqno); fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/flow.c --- a/sys/src/cmd/spin/flow.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/flow.c Tue Mar 06 23:34:10 2012 +0100 @@ -13,12 +13,14 @@ #include "y.tab.h" extern Symbol *Fname; -extern int nr_errs, lineno, verbose; -extern short has_unless, has_badelse; +extern int nr_errs, lineno, verbose, in_for; +extern short has_unless, has_badelse, has_xu; +extern char CurScope[MAXSCOPESZ]; Element *Al_El = ZE; Label *labtab = (Label *) 0; -int Unique=0, Elcnt=0, DstepStart = -1; +int Unique = 0, Elcnt = 0, DstepStart = -1; +int initialization_ok = 1; static Lbreak *breakstack = (Lbreak *) 0; static Lextok *innermost; @@ -40,7 +42,10 @@ t = seqlist(s, cur_s); cur_s = t; - if (top) Elcnt = 1; + if (top) + { Elcnt = 1; + initialization_ok = 1; + } } void @@ -113,8 +118,8 @@ && n->ntyp != PRINT && n->ntyp != PRINTM) { if (verbose&32) - printf("spin: line %d %s, redundant skip\n", - n->ln, n->fn->name); + printf("spin: %s:%d, redundant skip\n", + n->fn->name, n->ln); if (e != s->frst && e != s->last && e != s->extent) @@ -147,6 +152,10 @@ { Sequence *s = cur_s->this; Symbol *z; + if (nottop == 0) /* end of proctype body */ + { initialization_ok = 1; + } + if (nottop > 0 && (z = has_lab(s->frst, 0))) { printf("error: (%s:%d) label %s placed incorrectly\n", (s->frst->n)?s->frst->n->fn->name:"-", @@ -388,8 +397,13 @@ && prev_z->this->frst->n->ntyp == ELSE) { prev_z->this->frst->n->val = 1; has_badelse++; - non_fatal("dubious use of 'else' combined with i/o,", - (char *)0); + if (has_xu) + { fatal("invalid use of 'else' combined with i/o and xr/xs assertions,", + (char *)0); + } else + { non_fatal("dubious use of 'else' combined with i/o,", + (char *)0); + } nr_errs--; } @@ -561,35 +575,71 @@ } void +show_lab(void) +{ Label *l; + for (l = labtab; l; l = l->nxt) + printf("label %s\n", l->s->name); +} + +void set_lab(Symbol *s, Element *e) { Label *l; extern Symbol *context; + int cur_uiid = is_inline(); if (!s) return; + for (l = labtab; l; l = l->nxt) - if (l->s == s && l->c == context) + { if (strcmp(l->s->name, s->name) == 0 + && l->c == context + && l->uiid == cur_uiid) { non_fatal("label %s redeclared", s->name); break; - } + } } + l = (Label *) emalloc(sizeof(Label)); l->s = s; l->c = context; l->e = e; + l->uiid = cur_uiid; l->nxt = labtab; labtab = l; } +static Label * +get_labspec(Lextok *n) +{ Symbol *s = n->sym; + Label *l, *anymatch = (Label *) 0; + int cur_uiid = n->uiid; + /* + * try to find a label with the same uiid + * but if it doesn't exist, return any other + * that is defined within the same scope + */ + for (l = labtab; l; l = l->nxt) + { if (strcmp(s->name, l->s->name) == 0 + && s->context == l->s->context) + { anymatch = l; + if (cur_uiid == l->uiid) /* best match */ + { return l; + } } } + + return anymatch; /* likely to be 0 */ +} + Element * get_lab(Lextok *n, int md) -{ Label *l; - Symbol *s = n->sym; +{ Label *l = get_labspec(n); - for (l = labtab; l; l = l->nxt) - if (s == l->s) - return (l->e); + if (l != (Label *) 0) + { return (l->e); + } - lineno = n->ln; - Fname = n->fn; - if (md) fatal("undefined label %s", s->name); + if (md) + { lineno = n->ln; + Fname = n->fn; + fatal("undefined label %s", n->sym->name); + } + return ZE; } @@ -735,6 +785,226 @@ } } +#if 0 +static int depth = 0; +void dump_sym(Symbol *, char *); + +void +dump_lex(Lextok *t, char *s) +{ int i; + + depth++; + printf(s); + for (i = 0; i < depth; i++) + printf("\t"); + explain(t->ntyp); + if (t->ntyp == NAME) printf(" %s ", t->sym->name); + if (t->ntyp == CONST) printf(" %d ", t->val); + if (t->ntyp == STRUCT) + { dump_sym(t->sym, "\n:Z:"); + } + if (t->lft) + { dump_lex(t->lft, "\nL"); + } + if (t->rgt) + { dump_lex(t->rgt, "\nR"); + } + depth--; +} +void +dump_sym(Symbol *z, char *s) +{ int i; + char txt[64]; + depth++; + printf(s); + for (i = 0; i < depth; i++) + printf("\t"); + + if (z->type == CHAN) + { if (z->ini && z->ini->rgt && z->ini->rgt->sym) + { // dump_sym(z->ini->rgt->sym, "\n:I:"); /* could also be longer list */ + if (z->ini->rgt->rgt + || !z->ini->rgt->sym) + fatal("chan %s in for should have only one field (a typedef)", z->name); + printf(" -- %s %p -- ", z->ini->rgt->sym->name, z->ini->rgt->sym); + } + } else if (z->type == STRUCT) + { if (z->Snm) + printf(" == %s %p == ", z->Snm->name, z->Snm); + else + { if (z->Slst) + dump_lex(z->Slst, "\n:X:"); + if (z->ini) + dump_lex(z->ini, "\n:I:"); + } + } + depth--; + +} +#endif + +int +match_struct(Symbol *s, Symbol *t) +{ + if (!t + || !t->ini + || !t->ini->rgt + || !t->ini->rgt->sym + || t->ini->rgt->rgt) + { fatal("chan %s in for should have only one field (a typedef)", t->name); + } + /* we already know that s is a STRUCT */ + if (0) + { printf("index type %s %p ==\n", s->Snm->name, s->Snm); + printf("chan type %s %p --\n\n", t->ini->rgt->sym->name, t->ini->rgt->sym); + } + + return (s->Snm == t->ini->rgt->sym); +} + +void +valid_name(Lextok *a3, Lextok *a5, Lextok *a8, char *tp) +{ + if (a3->ntyp != NAME) + { fatal("%s ( .name : from .. to ) { ... }", tp); + } + if (a3->sym->type == CHAN + || a3->sym->type == STRUCT + || a3->sym->isarray != 0) + { fatal("bad index in for-construct %s", a3->sym->name); + } + if (a5->ntyp == CONST && a8->ntyp == CONST && a5->val > a8->val) + { non_fatal("start value for %s exceeds end-value", a3->sym->name); + } +} + +void +for_setup(Lextok *a3, Lextok *a5, Lextok *a8) +{ /* for ( a3 : a5 .. a8 ) */ + + valid_name(a3, a5, a8, "for"); + /* a5->ntyp = a8->ntyp = CONST; */ + add_seq(nn(a3, ASGN, a3, a5)); /* start value */ + open_seq(0); + add_seq(nn(ZN, 'c', nn(a3, LE, a3, a8), ZN)); /* condition */ +} + +Lextok * +for_index(Lextok *a3, Lextok *a5) +{ Lextok *z0, *z1, *z2, *z3; + Symbol *tmp_cnt; + char tmp_nm[MAXSCOPESZ]; + /* for ( a3 in a5 ) { ... } */ + + if (a3->ntyp != NAME) + { fatal("for ( .name in name ) { ... }", (char *) 0); + } + + if (a5->ntyp != NAME) + { fatal("for ( %s in .name ) { ... }", a3->sym->name); + } + + if (a3->sym->type == STRUCT) + { if (a5->sym->type != CHAN) + { fatal("for ( %s in .channel_name ) { ... }", + a3->sym->name); + } + z0 = a5->sym->ini; + if (!z0 + || z0->val <= 0 + || z0->rgt->ntyp != STRUCT + || z0->rgt->rgt != NULL) + { fatal("bad channel type %s in for", a5->sym->name); + } + + if (!match_struct(a3->sym, a5->sym)) + { fatal("type of %s does not match chan", a3->sym->name); + } + + z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0; + z2 = nn(a5, LEN, a5, ZN); + + sprintf(tmp_nm, "_f0r_t3mp%s", CurScope); /* make sure it's unique */ + tmp_cnt = lookup(tmp_nm); + if (z0->val > 255) /* check nr of slots, i.e. max length */ + { tmp_cnt->type = SHORT; /* should be rare */ + } else + { tmp_cnt->type = BYTE; + } + z3 = nn(ZN, NAME, ZN, ZN); + z3->sym = tmp_cnt; + + add_seq(nn(z3, ASGN, z3, z1)); /* start value 0 */ + + open_seq(0); + + add_seq(nn(ZN, 'c', nn(z3, LT, z3, z2), ZN)); /* condition */ + + /* retrieve message from the right slot -- for now: rotate contents */ + in_for = 0; + add_seq(nn(a5, 'r', a5, expand(a3, 1))); /* receive */ + add_seq(nn(a5, 's', a5, expand(a3, 1))); /* put back in to rotate */ + in_for = 1; + return z3; + } else + { if (a5->sym->isarray == 0 + || a5->sym->nel <= 0) + { fatal("bad arrayname %s", a5->sym->name); + } + z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0; + z2 = nn(ZN, CONST, ZN, ZN); z2->val = a5->sym->nel - 1; + for_setup(a3, z1, z2); + return a3; + } +} + +Lextok * +for_body(Lextok *a3, int with_else) +{ Lextok *t1, *t2, *t0, *rv; + + rv = nn(ZN, CONST, ZN, ZN); rv->val = 1; + rv = nn(ZN, '+', a3, rv); + rv = nn(a3, ASGN, a3, rv); + add_seq(rv); /* initial increment */ + + pushbreak(); + + /* completed loop body, main sequence */ + t1 = nn(ZN, 0, ZN, ZN); + t1->sq = close_seq(8); + + open_seq(0); /* add else -> break sequence */ + if (with_else) + { add_seq(nn(ZN, ELSE, ZN, ZN)); + } + t2 = nn(ZN, GOTO, ZN, ZN); + t2->sym = break_dest(); + add_seq(t2); + t2 = nn(ZN, 0, ZN, ZN); + t2->sq = close_seq(9); + + t0 = nn(ZN, 0, ZN, ZN); + t0->sl = seqlist(t2->sq, seqlist(t1->sq, 0)); + + rv = nn(ZN, DO, ZN, ZN); + rv->sl = t0->sl; + return rv; +} + +Lextok * +sel_index(Lextok *a3, Lextok *a5, Lextok *a7) +{ /* select ( a3 : a5 .. a7 ) */ + + valid_name(a3, a5, a7, "select"); + /* a5->ntyp = a7->ntyp = CONST; */ + + add_seq(nn(a3, ASGN, a3, a5)); /* start value */ + open_seq(0); + add_seq(nn(ZN, 'c', nn(a3, LT, a3, a7), ZN)); /* condition */ + + return for_body(a3, 0); /* no else, just a non-deterministic break */ +} + static void walk_atomic(Element *a, Element *b, int added) { Element *f; Symbol *ofn; int oln; @@ -747,16 +1017,16 @@ switch (f->n->ntyp) { case ATOMIC: if (verbose&32) - printf("spin: warning, line %3d %s, atomic inside %s (ignored)\n", - f->n->ln, f->n->fn->name, (added)?"d_step":"atomic"); + printf("spin: warning, %s:%d, atomic inside %s (ignored)\n", + f->n->fn->name, f->n->ln, (added)?"d_step":"atomic"); goto mknonat; case D_STEP: if (!(verbose&32)) { if (added) goto mknonat; break; } - printf("spin: warning, line %3d %s, d_step inside ", - f->n->ln, f->n->fn->name); + printf("spin: warning, %s:%d, d_step inside ", + f->n->fn->name, f->n->ln); if (added) { printf("d_step (ignored)\n"); goto mknonat; @@ -770,8 +1040,8 @@ break; case UNLESS: if (added) - { printf("spin: error, line %3d %s, unless in d_step (ignored)\n", - f->n->ln, f->n->fn->name); + { printf("spin: error, %s:%d, unless in d_step (ignored)\n", + f->n->fn->name, f->n->ln); } } for (h = f->sub; h; h = h->nxt) @@ -789,6 +1059,11 @@ for (l = labtab; l; l = l->nxt) if (l->c != 0 && l->s->name[0] != ':') - printf("label %s %d <%s>\n", - l->s->name, l->e->seqno, l->c->name); + { printf("label %s %d ", + l->s->name, l->e->seqno); + if (l->uiid == 0) + printf("<%s>\n", l->c->name); + else + printf("<%s i%d>\n", l->c->name, l->uiid); + } } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/guided.c --- a/sys/src/cmd/spin/guided.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/guided.c Tue Mar 06 23:34:10 2012 +0100 @@ -21,6 +21,7 @@ extern int nproc, nstop, Tval, ntrail, columns; extern short Have_claim, Skip_claim; extern void ana_src(int, int); +extern char **trailfilename; int TstOnly = 0, pno; @@ -88,10 +89,18 @@ * leader.tra */ - if (ntrail) - sprintf(snap, "%s%d.trail", oFname->name, ntrail); - else - sprintf(snap, "%s.trail", oFname->name); + if (trailfilename) + { if (strlen(*trailfilename) < sizeof(snap)) + { strcpy(snap, (const char *) *trailfilename); + } else + { fatal("filename %s too long", *trailfilename); + } + } else + { if (ntrail) + sprintf(snap, "%s%d.trail", oFname->name, ntrail); + else + sprintf(snap, "%s.trail", oFname->name); + } if ((fd = fopen(snap, "r")) == NULL) { snap[strlen(snap)-2] = '\0'; /* .tra */ @@ -188,16 +197,36 @@ pno - Have_claim, i, nst, dothis->n->ntyp); lost_trail(); } + + if (!xspin && (verbose&32)) + { printf("i=%d pno %d\n", i, pno); + } + for (X = run; X; X = X->nxt) { if (--i == pno) break; } + if (!X) - { printf("%3d: no process %d ", depth, pno - Have_claim); - printf("(state %d)\n", nst); - lost_trail(); + { if (verbose&32) + { printf("%3d: no process %d (step %d)\n", depth, pno - Have_claim, nst); + printf(" max %d (%d - %d + %d) claim %d", + nproc - nstop + Skip_claim, + nproc, nstop, Skip_claim, Have_claim); + printf("active processes:\n"); + for (X = run; X; X = X->nxt) + { printf("\tpid %d\tproctype %s\n", X->pid, X->n->name); + } + printf("\n"); + continue; + } else + { printf("%3d:\tproc %d (?) ", depth, pno); + lost_trail(); + } + } else + { X->pc = dothis; } - X->pc = dothis; + lineno = dothis->n->ln; Fname = dothis->n->fn; @@ -271,7 +300,7 @@ } } if (Have_claim && X && X->pid == 0 - && dothis && dothis->n + && dothis->n && lastclaim != dothis->n->ln) { lastclaim = dothis->n->ln; if (columns == 2) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/main.c --- a/sys/src/cmd/spin/main.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/main.c Tue Mar 06 23:34:10 2012 +0100 @@ -12,6 +12,8 @@ #include #include "spin.h" #include "version.h" +#include +#include #include /* #include */ #include @@ -29,6 +31,7 @@ extern char *claimproc; extern void repro_src(void); extern void qhide(int); +extern char CurScope[MAXSCOPESZ]; Symbol *Fname, *oFname; @@ -40,12 +43,16 @@ int no_print, no_wrapup, Caccess, limited_vis, like_java; int separate; /* separate compilation */ int export_ast; /* pangen5.c */ -int inlineonly; /* show inlined code */ -int seedy; /* be verbose about chosen seed */ +int old_scope_rules; /* use pre 5.3.0 rules */ +int split_decl = 1, product, Strict; -int dataflow = 1, merger = 1, deadvar = 1, ccache = 1; +int merger = 1, deadvar = 1; +int ccache = 0; /* oyvind teig: 5.2.0 case caching off by default */ static int preprocessonly, SeedUsed; +static int seedy; /* be verbose about chosen seed */ +static int inlineonly; /* show inlined code */ +static int dataflow = 1; #if 0 meaning of flags on verbose: @@ -61,33 +68,44 @@ static char Operator[] = "operator: "; static char Keyword[] = "keyword: "; static char Function[] = "function-name: "; -static char **add_ltl = (char **)0; -static char **ltl_file = (char **)0; -static char **nvr_file = (char **)0; +static char **add_ltl = (char **) 0; +static char **ltl_file = (char **) 0; +static char **nvr_file = (char **) 0; +static char *ltl_claims = (char *) 0; +static FILE *fd_ltl = (FILE *) 0; static char *PreArg[64]; static int PreCnt = 0; static char out1[64]; -static void explain(int); +char **trailfilename; /* new option 'k' */ + +void explain(int); + + /* to use visual C++: + #define CPP "CL -E/E" + or call spin as: "spin -PCL -E/E" + + on OS2: + #define CPP "icc -E/Pd+ -E/Q+" + or call spin as: "spin -Picc -E/Pd+ -E/Q+" + */ #ifndef CPP - /* OS2: "spin -Picc -E/Pd+ -E/Q+" */ - /* Visual C++: "spin -PCL -E/E */ -#ifdef PC -#define CPP "gcc -E -x c" /* most systems have gcc anyway */ - /* else use "cpp" */ -#else -#ifdef SOLARIS -#define CPP "/usr/ccs/lib/cpp" -#else -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) -#define CPP "cpp" -#else -#define CPP "/bin/cpp" /* classic Unix systems */ -#endif -#endif + #if defined(PC) || defined(MAC) + #define CPP "gcc -E -x c" /* most systems have gcc or cpp */ + /* if gcc-4 is available, this setting is modified below */ + #else + #ifdef SOLARIS + #define CPP "/usr/ccs/lib/cpp" + #else + #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + #define CPP "cpp" + #else + #define CPP "/bin/cpp" /* classic Unix systems */ + #endif + #endif + #endif #endif -#endif static char *PreProc = CPP; extern int depth; /* at least some steps were made */ @@ -114,16 +132,36 @@ void preprocess(char *a, char *b, int a_tmp) -{ char precmd[512], cmd[1024]; int i; +{ char precmd[1024], cmd[2048]; int i; +#if defined(WIN32) || defined(WIN64) + struct _stat x; +/* struct stat x; */ +#endif #ifdef PC extern int try_zpp(char *, char *); - if (PreCnt == 0 && try_zpp(a, b)) goto out; + if (PreCnt == 0 && try_zpp(a, b)) + { goto out; + } +#endif +#if defined(WIN32) || defined(WIN64) + if (strncmp(PreProc, "gcc -E -x c", strlen("gcc -E -x c")) == 0) + { if (stat("/bin/gcc-4.exe", (struct stat *)&x) == 0 /* for PCs with cygwin */ + || stat("c:/cygwin/bin/gcc-4.exe", (struct stat *)&x) == 0) + { PreProc = "gcc-4 -E -x c"; + } else if (stat("/bin/gcc-3.exe", (struct stat *)&x) == 0 + || stat("c:/cygwin/bin/gcc-3.exe", (struct stat *)&x) == 0) + { PreProc = "gcc-3 -E -x c"; + } } #endif strcpy(precmd, PreProc); for (i = 1; i <= PreCnt; i++) { strcat(precmd, " "); strcat(precmd, PreArg[i]); } + if (strlen(precmd) > sizeof(precmd)) + { fprintf(stdout, "spin: too many -D args, aborting\n"); + alldone(1); + } sprintf(cmd, "%s %s > %s", precmd, a, b); if (system((const char *)cmd)) { (void) unlink((const char *) b); @@ -137,23 +175,6 @@ if (a_tmp) (void) unlink((const char *) a); } -FILE * -cpyfile(char *src, char *tgt) -{ FILE *inp, *out; - char buf[1024]; - - inp = fopen(src, "r"); - out = fopen(tgt, "w"); - if (!inp || !out) - { printf("spin: cannot cp %s to %s\n", src, tgt); - alldone(1); - } - while (fgets(buf, 1024, inp)) - fprintf(out, "%s", buf); - fclose(inp); - return out; -} - void usage(void) { @@ -168,25 +189,30 @@ printf("\t-d produce symbol-table information\n"); printf("\t-Dyyy pass -Dyyy to the preprocessor\n"); printf("\t-Eyyy pass yyy to the preprocessor\n"); + printf("\t-e compute synchronous product of multiple never claims (modified by -L)\n"); printf("\t-f \"..formula..\" translate LTL "); printf("into never claim\n"); - printf("\t-F file like -f, but with the LTL "); - printf("formula stored in a 1-line file\n"); + printf("\t-F file like -f, but with the LTL formula stored in a 1-line file\n"); printf("\t-g print all global variables\n"); - printf("\t-h at end of run, print value of seed for random nr generator used\n"); + printf("\t-h at end of run, print value of seed for random nr generator used\n"); printf("\t-i interactive (random simulation)\n"); printf("\t-I show result of inlining and preprocessing\n"); printf("\t-J reverse eval order of nested unlesses\n"); printf("\t-jN skip the first N steps "); printf("in simulation trail\n"); + printf("\t-k fname use the trailfile stored in file fname, see also -t\n"); + printf("\t-L when using -e, use strict language intersection\n"); printf("\t-l print all local variables\n"); printf("\t-M print msc-flow in Postscript\n"); printf("\t-m lose msgs sent to full queues\n"); - printf("\t-N file use never claim stored in file\n"); + printf("\t-N fname use never claim stored in file fname\n"); printf("\t-nN seed for random nr generator\n"); + printf("\t-O use old scope rules (pre 5.3.0)\n"); printf("\t-o1 turn off dataflow-optimizations in verifier\n"); printf("\t-o2 don't hide write-only variables in verifier\n"); printf("\t-o3 turn off statement merging in verifier\n"); + printf("\t-o4 turn on rendezvous optiomizations in verifier\n"); + printf("\t-o5 turn on case caching (reduces size of pan.m, but affects reachability reports)\n"); printf("\t-Pxxx use xxx for preprocessing\n"); printf("\t-p print all statements\n"); printf("\t-qN suppress io for queue N in printouts\n"); @@ -194,7 +220,7 @@ printf("\t-S1 and -S2 separate pan source for claim and model\n"); printf("\t-s print send events\n"); printf("\t-T do not indent printf output\n"); - printf("\t-t[N] follow [Nth] simulation trail\n"); + printf("\t-t[N] follow [Nth] simulation trail, see also -k\n"); printf("\t-Uyyy pass -Uyyy to the preprocessor\n"); printf("\t-uN stop a simulation run after N steps\n"); printf("\t-v verbose, more warnings\n"); @@ -205,7 +231,7 @@ } void -optimizations(char nr) +optimizations(int nr) { switch (nr) { case '1': @@ -250,31 +276,6 @@ } } -#if 0 -static int -Rename(const char *old, char *new) -{ FILE *fo, *fn; - char buf[1024]; - - if ((fo = fopen(old, "r")) == NULL) - { printf("spin: cannot open %s\n", old); - return 1; - } - if ((fn = fopen(new, "w")) == NULL) - { printf("spin: cannot create %s\n", new); - fclose(fo); - return 2; - } - while (fgets(buf, 1024, fo)) - fputs(buf, fn); - - fclose(fo); - fclose(fn); - - return 0; /* success */ -} -#endif - int main(int argc, char *argv[]) { Symbol *s; @@ -285,16 +286,15 @@ yyin = stdin; yyout = stdout; tl_out = stdout; + strcpy(CurScope, "_"); - /* unused flags: e, w, x, y, z, A, G, I, L, O, Q, R, S, T, W */ + /* unused flags: y, z, G, L, Q, R, W */ while (argc > 1 && argv[1][0] == '-') { switch (argv[1][1]) { - /* generate code for separate compilation: S1 or S2 */ case 'S': separate = atoi(&argv[1][2]); /* fall through */ case 'a': analyze = 1; break; - case 'A': export_ast = 1; break; case 'B': no_wrapup = 1; break; case 'b': no_print = 1; break; @@ -305,6 +305,7 @@ case 'd': dumptab = 1; break; case 'E': PreArg[++PreCnt] = (char *) &argv[1][2]; break; + case 'e': product++; break; /* see also 'L' */ case 'F': ltl_file = (char **) (argv+2); argc--; argv++; break; case 'f': add_ltl = (char **) argv; @@ -315,34 +316,42 @@ case 'I': inlineonly = 1; break; case 'J': like_java = 1; break; case 'j': jumpsteps = atoi(&argv[1][2]); break; + case 'k': s_trail = 1; + trailfilename = (char **) (argv+2); + argc--; argv++; break; + case 'L': Strict++; break; /* modified -e */ case 'l': verbose += 2; break; case 'M': columns = 2; break; case 'm': m_loss = 1; break; case 'N': nvr_file = (char **) (argv+2); argc--; argv++; break; case 'n': T = atoi(&argv[1][2]); tl_terse = 1; break; + case 'O': old_scope_rules = 1; break; case 'o': optimizations(argv[1][2]); usedopts = 1; break; case 'P': PreProc = (char *) &argv[1][2]; break; case 'p': verbose += 4; break; - case 'q': if (isdigit(argv[1][2])) + case 'q': if (isdigit((int) argv[1][2])) qhide(atoi(&argv[1][2])); break; case 'r': verbose += 8; break; case 's': verbose += 16; break; case 'T': notabs = 1; break; case 't': s_trail = 1; - if (isdigit(argv[1][2])) + if (isdigit((int)argv[1][2])) ntrail = atoi(&argv[1][2]); break; case 'U': PreArg[++PreCnt] = (char *) &argv[1][0]; break; /* undefine */ case 'u': cutoff = atoi(&argv[1][2]); break; /* new 3.4.14 */ case 'v': verbose += 32; break; - case 'V': printf("%s\n", Version); + case 'V': printf("%s\n", SpinVersion); alldone(0); break; case 'w': verbose += 64; break; +#if 0 + case 'x': split_decl = 0; break; /* experimental */ +#endif case 'X': xspin = notabs = 1; #ifndef PC signal(SIGPIPE, alldone); /* not posix... */ @@ -355,9 +364,10 @@ } argc--; argv++; } + if (usedopts && !analyze) printf("spin: warning -o[123] option ignored in simulations\n"); - + if (ltl_file) { char formula[4096]; add_ltl = ltl_file-2; add_ltl[1][1] = 'f'; @@ -365,41 +375,42 @@ { printf("spin: cannot open %s\n", *ltl_file); alldone(1); } - fgets(formula, 4096, tl_out); + if (!fgets(formula, 4096, tl_out)) + { printf("spin: cannot read %s\n", *ltl_file); + } fclose(tl_out); tl_out = stdout; *ltl_file = (char *) formula; } if (argc > 1) - { char cmd[128], out2[64]; + { FILE *fd = stdout; + char cmd[512], out2[512]; /* must remain in current dir */ strcpy(out1, "pan.pre"); if (add_ltl || nvr_file) - strcpy(out2, "pan.___"); + { sprintf(out2, "%s.nvr", argv[1]); + if ((fd = fopen(out2, MFLAGS)) == NULL) + { printf("spin: cannot create tmp file %s\n", + out2); + alldone(1); + } + fprintf(fd, "#include \"%s\"\n", argv[1]); + } if (add_ltl) - { tl_out = cpyfile(argv[1], out2); - nr_errs = tl_main(2, add_ltl); /* in tl_main.c */ - fclose(tl_out); + { tl_out = fd; + nr_errs = tl_main(2, add_ltl); + fclose(fd); preprocess(out2, out1, 1); } else if (nvr_file) - { FILE *fd; char buf[1024]; - - if ((fd = fopen(*nvr_file, "r")) == NULL) - { printf("spin: cannot open %s\n", - *nvr_file); - alldone(1); - } - tl_out = cpyfile(argv[1], out2); - while (fgets(buf, 1024, fd)) - fprintf(tl_out, "%s", buf); - fclose(tl_out); + { fprintf(fd, "#include \"%s\"\n", *nvr_file); fclose(fd); preprocess(out2, out1, 1); } else - preprocess(argv[1], out1, 0); + { preprocess(argv[1], out1, 0); + } if (preprocessonly) alldone(0); @@ -409,8 +420,8 @@ alldone(1); } - if (strncmp(argv[1], "progress", 8) == 0 - || strncmp(argv[1], "accept", 6) == 0) + if (strncmp(argv[1], "progress", (size_t) 8) == 0 + || strncmp(argv[1], "accept", (size_t) 6) == 0) sprintf(cmd, "_%s", argv[1]); else strcpy(cmd, argv[1]); @@ -428,9 +439,10 @@ printf("spin: missing argument to -f\n"); alldone(1); } - printf("%s\n", Version); - printf("reading input from stdin:\n"); + printf("%s\n", SpinVersion); + fprintf(stderr, "spin: error, no filename specified"); fflush(stdout); + alldone(1); } if (columns == 2) { extern void putprelude(void); @@ -444,7 +456,7 @@ verbose += (8+16); if (columns == 2 && limited_vis) verbose += (1+4); - Srand(T); /* defined in run.c */ + Srand((unsigned int) T); /* defined in run.c */ SeedUsed = T; s = lookup("_"); s->type = PREDEF; /* write-only global var */ s = lookup("_p"); s->type = PREDEF; @@ -454,6 +466,23 @@ yyparse(); fclose(yyin); + + if (ltl_claims) + { Symbol *r; + fclose(fd_ltl); + if (!(yyin = fopen(ltl_claims, "r"))) + { fatal("cannot open %s", ltl_claims); + } + r = oFname; + oFname = Fname = lookup(ltl_claims); + lineno = 0; + yyparse(); + fclose(yyin); + oFname = Fname = r; + if (0) + { (void) unlink(ltl_claims); + } } + loose_ends(); if (inlineonly) @@ -471,6 +500,35 @@ return 0; } +void +ltl_list(char *nm, char *fm) +{ + if (analyze || dumptab) /* when generating pan.c only */ + { if (!ltl_claims) + { ltl_claims = "_spin_nvr.tmp"; + if ((fd_ltl = fopen(ltl_claims, MFLAGS)) == NULL) + { fatal("cannot open tmp file %s", ltl_claims); + } + tl_out = fd_ltl; + } + + add_ltl = (char **) emalloc(5 * sizeof(char *)); + add_ltl[1] = "-c"; + add_ltl[2] = nm; + add_ltl[3] = "-f"; + add_ltl[4] = (char *) emalloc(strlen(fm)+4); + strcpy(add_ltl[4], "!("); + strcat(add_ltl[4], fm); + strcat(add_ltl[4], ")"); + /* add_ltl[4] = fm; */ + + nr_errs += tl_main(4, add_ltl); + + fflush(tl_out); + /* should read this file after the main file is read */ + } +} + int yywrap(void) /* dummy routine */ { @@ -481,13 +539,13 @@ non_fatal(char *s1, char *s2) { extern char yytext[]; - printf("spin: line %3d %s, Error: ", - lineno, Fname?Fname->name:"nofilename"); + printf("spin: %s:%d, Error: ", + oFname?oFname->name:"nofilename", lineno); if (s2) printf(s1, s2); else printf(s1); - if (yytext && strlen(yytext)>1) + if (strlen(yytext)>1) printf(" near '%s'", yytext); printf("\n"); nr_errs++; @@ -497,24 +555,35 @@ fatal(char *s1, char *s2) { non_fatal(s1, s2); + (void) unlink("pan.b"); + (void) unlink("pan.c"); + (void) unlink("pan.h"); + (void) unlink("pan.m"); + (void) unlink("pan.t"); + (void) unlink("pan.pre"); alldone(1); } char * -emalloc(int n) +emalloc(size_t n) { char *tmp; + static unsigned long cnt = 0; if (n == 0) return NULL; /* robert shelton 10/20/06 */ if (!(tmp = (char *) malloc(n))) + { printf("spin: allocated %ld Gb, wanted %d bytes more\n", + cnt/(1024*1024*1024), (int) n); fatal("not enough memory", (char *)0); + } + cnt += (unsigned long) n; memset(tmp, 0, n); return tmp; } void -trapwonly(Lextok *n, char *unused) +trapwonly(Lextok *n /* , char *unused */) { extern int realread; short i = (n->sym)?n->sym->type:0; @@ -555,6 +624,7 @@ { Lextok *n = (Lextok *) emalloc(sizeof(Lextok)); static int warn_nn = 0; + n->uiid = is_inline(); /* record origin of the statement */ n->ntyp = (short) t; if (s && s->fn) { n->ln = s->ln; @@ -679,13 +749,13 @@ #endif } -static void +void explain(int n) { FILE *fd = stdout; switch (n) { default: if (n > 0 && n < 256) - fprintf(fd, "'%c' = '", n); - fprintf(fd, "%d'", n); + fprintf(fd, "'%c' = ", n); + fprintf(fd, "%d", n); break; case '\b': fprintf(fd, "\\b"); break; case '\t': fprintf(fd, "\\t"); break; @@ -698,6 +768,16 @@ case 'R': fprintf(fd, "recv poll %s", Operator); break; case '@': fprintf(fd, "@"); break; case '?': fprintf(fd, "(x->y:z)"); break; +#if 1 + case NEXT: fprintf(fd, "X"); break; + case ALWAYS: fprintf(fd, "[]"); break; + case EVENTUALLY: fprintf(fd, "<>"); break; + case IMPLIES: fprintf(fd, "->"); break; + case EQUIV: fprintf(fd, "<->"); break; + case UNTIL: fprintf(fd, "U"); break; + case WEAK_UNTIL: fprintf(fd, "W"); break; + case IN: fprintf(fd, "%sin", Keyword); break; +#endif case ACTIVE: fprintf(fd, "%sactive", Keyword); break; case AND: fprintf(fd, "%s&&", Operator); break; case ASGN: fprintf(fd, "%s=", Operator); break; @@ -776,3 +856,5 @@ case UNLESS: fprintf(fd, "%sunless", Keyword); break; } } + + diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/mesg.c --- a/sys/src/cmd/spin/mesg.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/mesg.c Tue Mar 06 23:34:10 2012 +0100 @@ -185,9 +185,11 @@ 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; + if (New == Old) + continue; + if (New > Old) + break; /* inner loop */ + goto found; /* New < Old */ } found: for (j = q->qlen-1; j >= i; j--) @@ -383,7 +385,7 @@ return 1; } -void +static void channm(Lextok *n) { char lbuf[512]; @@ -394,7 +396,11 @@ else if (n->sym->type == STRUCT) { Symbol *r = n->sym; if (r->context) - r = findloc(r); + { r = findloc(r); + if (!r) + { strcat(Buf, "*?*"); + return; + } } ini_struct(r); printf("%s", r->name); strcpy(lbuf, ""); @@ -462,7 +468,7 @@ int n; struct QH *nxt; } QH; -QH *qh; +static QH *qh; void qhide(int q) @@ -483,7 +489,7 @@ static void sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q) -{ char s[64]; +{ char s[128]; if (qishidden(eval(n->lft))) return; @@ -510,9 +516,20 @@ } if (j == 0) - { whoruns(1); - printf("line %3d %s %s", - n->ln, n->fn->name, s); + { char snm[128]; + whoruns(1); + { char *ptr = n->fn->name; + char *qtr = snm; + while (*ptr != '\0') + { if (*ptr != '\"') + { *qtr++ = *ptr; + } + ptr++; + } + *qtr = '\0'; + printf("%s:%d %s", + snm, n->ln, s); + } } else printf(","); sr_mesg(stdout, v, q->fld_width[j] == MTYPE); @@ -572,10 +589,15 @@ continue; if (q->nslots == 0) continue; /* rv q always empty */ +#if 0 + if (q->qlen == 0) /* new 7/10 -- dont show if queue is empty */ + { continue; + } +#endif printf("\t\tqueue %d (", q->qid); if (r) printf("%s(%d):", r->n->name, r->pid - Have_claim); - if (s->nel != 1) + if (s->nel > 1 || s->isarray) printf("%s[%d]): ", s->name, n); else printf("%s): ", s->name); @@ -609,7 +631,10 @@ } } - if (!n || n->ntyp == LEN || n->ntyp == RUN) + /* ok on the rhs of an assignment: */ + if (!n || n->ntyp == LEN || n->ntyp == RUN + || n->ntyp == FULL || n->ntyp == NFULL + || n->ntyp == EMPTY || n->ntyp == NEMPTY) return; if (n->sym && n->sym->type == CHAN) @@ -627,6 +652,120 @@ nochan_manip(p, n->rgt, 1); } +typedef struct BaseName { + char *str; + int cnt; + struct BaseName *nxt; +} BaseName; +BaseName *bsn; + +void +newbasename(char *s) +{ BaseName *b; + +/* printf("+++++++++%s\n", s); */ + for (b = bsn; b; b = b->nxt) + if (strcmp(b->str, s) == 0) + { b->cnt++; + return; + } + b = (BaseName *) emalloc(sizeof(BaseName)); + b->str = emalloc(strlen(s)+1); + b->cnt = 1; + strcpy(b->str, s); + b->nxt = bsn; + bsn = b; +} + +void +delbasename(char *s) +{ BaseName *b, *prv = (BaseName *) 0; + + for (b = bsn; b; prv = b, b = b->nxt) + { if (strcmp(b->str, s) == 0) + { b->cnt--; + if (b->cnt == 0) + { if (prv) + { prv->nxt = b->nxt; + } else + { bsn = b->nxt; + } } +/* printf("---------%s\n", s); */ + break; + } } +} + +void +checkindex(char *s, char *t) +{ BaseName *b; + +/* printf("xxx Check %s (%s)\n", s, t); */ + for (b = bsn; b; b = b->nxt) + { +/* printf(" %s\n", b->str); */ + if (strcmp(b->str, s) == 0) + { non_fatal("do not index an array with itself (%s)", t); + break; + } } +} + +void +scan_tree(Lextok *t, char *mn, char *mx) +{ char sv[512]; + char tmp[32]; + int oln = lineno; + + if (!t) return; + + lineno = t->ln; + + if (t->ntyp == NAME) + { strcat(mn, t->sym->name); + strcat(mx, t->sym->name); + if (t->lft) /* array index */ + { strcat(mn, "[]"); + newbasename(mn); + strcpy(sv, mn); /* save */ + strcpy(mn, ""); /* clear */ + strcat(mx, "["); + scan_tree(t->lft, mn, mx); /* index */ + strcat(mx, "]"); + checkindex(mn, mx); /* match against basenames */ + strcpy(mn, sv); /* restore */ + delbasename(mn); + } + if (t->rgt) /* structure element */ + { scan_tree(t->rgt, mn, mx); + } + } else if (t->ntyp == CONST) + { strcat(mn, "1"); /* really: t->val */ + sprintf(tmp, "%d", t->val); + strcat(mx, tmp); + } else if (t->ntyp == '.') + { strcat(mn, "."); + strcat(mx, "."); + scan_tree(t->lft, mn, mx); + } else + { strcat(mn, "??"); + strcat(mx, "??"); + } + lineno = oln; +} + +void +no_nested_array_refs(Lextok *n) /* a [ a[1] ] with a[1] = 1, causes trouble in pan.b */ +{ char mn[512]; + char mx[512]; + +/* printf("==================================ZAP\n"); */ + bsn = (BaseName *) 0; /* start new list */ + strcpy(mn, ""); + strcpy(mx, ""); + + scan_tree(n, mn, mx); +/* printf("==> %s\n", mn); */ +} + void no_internals(Lextok *n) { char *sp; @@ -641,4 +780,6 @@ || (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0)) { fatal("attempt to assign value to system variable %s", sp); } + + no_nested_array_refs(n); } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/mkfile --- a/sys/src/cmd/spin/mkfile Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/mkfile Tue Mar 06 23:34:10 2012 +0100 @@ -14,6 +14,7 @@ pangen4.$O\ pangen5.$O\ pangen6.$O\ + pangen7.$O\ pc_zpp.$O\ ps_msc.$O\ reprosrc.$O\ @@ -53,4 +54,4 @@ main.$O pangen2.$O ps_msc.$O: version.h pangen1.$O: pangen1.h pangen3.h -pangen2.$O: pangen2.h pangen4.h pangen5.h +pangen2.$O: pangen2.h pangen4.h pangen5.h pangen6.h diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen1.c --- a/sys/src/cmd/spin/pangen1.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen1.c Tue Mar 06 23:34:10 2012 +0100 @@ -8,11 +8,14 @@ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ +/* (c) 2007: small additions for V5.0 to support multi-core verifications */ #include "spin.h" #include "y.tab.h" #include "pangen1.h" #include "pangen3.h" +#include "pangen6.h" +#include extern FILE *tc, *th, *tt; extern Label *labtab; @@ -20,9 +23,10 @@ extern ProcList *rdy; extern Queue *qtab; extern Symbol *Fname; -extern int lineno, verbose, Pid, separate; +extern int lineno, verbose, Pid, separate, old_scope_rules, nclaims; extern int nrRdy, nqs, mst, Mpars, claimnr, eventmapnr; extern short has_sorted, has_random, has_provided; +extern Queue *ltab[]; int Npars=0, u_sync=0, u_async=0, hastrack = 1; short has_io = 0; @@ -36,9 +40,10 @@ static void dohidden(void); static void do_init(FILE *, Symbol *); static void end_labs(Symbol *, int); -static void put_ptype(char *, int, int, int); +static void put_ptype(char *, int, int, int, enum btypes); static void tc_predef_np(void); static void put_pinit(ProcList *); +static void multi_init(void); void walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *); static void @@ -48,6 +53,21 @@ reverse_names(p->nxt); fprintf(th, " \"%s\",\n", p->n->name); } +static void +reverse_types(ProcList *p) +{ + if (!p) return; + reverse_types(p->nxt); + fprintf(th, " %d, /* %s */\n", p->b, p->n->name); +} + +static int +blog(int n) /* for small log2 without rounding problems */ +{ int m=1, r=2; + + while (r < n) { m++; r *= 2; } + return 1+m; +} void genheader(void) @@ -57,9 +77,19 @@ { putunames(th); goto here; } - + /* 5.2.3: gcc 3 no longer seems to compute sizeof at compile time */ + fprintf(th, "#define WS %d /* word size in bytes */\n", (int) sizeof(void *)); fprintf(th, "#define SYNC %d\n", u_sync); fprintf(th, "#define ASYNC %d\n\n", u_async); + fprintf(th, "#ifndef NCORE\n"); + fprintf(th, " #ifdef DUAL_CORE\n"); + fprintf(th, " #define NCORE 2\n"); + fprintf(th, " #elif QUAD_CORE\n"); + fprintf(th, " #define NCORE 4\n"); + fprintf(th, " #else\n"); + fprintf(th, " #define NCORE 1\n"); + fprintf(th, " #endif\n"); + fprintf(th, "#endif\n"); putunames(th); @@ -67,6 +97,11 @@ for (p = rdy, i=0; p; p = p->nxt, i++) fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i); fprintf(tc, ", (short) Air%d", i); /* np_ */ + if (nclaims > 1) + { fprintf(tc, "\n#ifndef NOCLAIM\n"); + fprintf(tc, " , (short) Air%d", i+1); /* Multi */ + fprintf(tc, "\n#endif\n\t"); + } fprintf(tc, " };\n"); fprintf(th, "char *procname[] = {\n"); @@ -74,18 +109,86 @@ fprintf(th, " \":np_:\",\n"); fprintf(th, "};\n\n"); + fprintf(th, "enum btypes { NONE=%d, N_CLAIM=%d,", NONE, N_CLAIM); + fprintf(th, " I_PROC=%d, A_PROC=%d,", I_PROC, A_PROC); + fprintf(th, " P_PROC=%d, E_TRACE=%d, N_TRACE=%d };\n", + P_PROC, E_TRACE, N_TRACE); + fprintf(th, "int Btypes[] = {\n"); + reverse_types(rdy); + fprintf(th, " 0 /* :np_: */\n"); + fprintf(th, "};\n\n"); + here: for (p = rdy; p; p = p->nxt) - put_ptype(p->n->name, p->tn, mst, nrRdy+1); + put_ptype(p->n->name, p->tn, mst, nrRdy+1, p->b); /* +1 for np_ */ - put_ptype("np_", nrRdy, mst, nrRdy+1); + put_ptype("np_", nrRdy, mst, nrRdy+1, 0); + + if (nclaims > 1) + { /* this is the structure that goes into the state-vector + * instead of the actual never claims + * this assumes that the claims do not have any local variables + * this claim records the types and states of all subclaims in an array + * NB: not sure if we need the first 3 fields in this structure + * it's here for now to avoid breaking some possible dependence + * in the calculations above, we were already taking into account + * that there is one never-claim, which will now be this one + */ + + i = blog(mst); + fprintf(th, "\n"); + fprintf(th, "#ifndef NOCLAIM\n"); + fprintf(th, " #undef VERI\n"); + fprintf(th, " #define VERI %d\n", nrRdy+1); + fprintf(th, " #define Pclaim P%d\n\n", nrRdy+1); + fprintf(th, "typedef struct P%d {\n", nrRdy+1); + fprintf(th, " unsigned _pid : 8; /* always zero */\n"); + fprintf(th, " unsigned _t : %d; /* active-claim type */\n", + blog(nrRdy+1)); + fprintf(th, " unsigned _p : %d; /* active-claim state */\n", + i); + fprintf(th, " unsigned _n : %d; /* active-claim index */\n", + blog(nclaims)); + if (i <= 255) /* in stdint.h = UCHAR_MAX from limits.h */ + { fprintf(th, " uchar c_cur[NCLAIMS]; /* claim-states */\n"); + } else if (i <= 65535) /* really USHRT_MAX from limits.h */ + { fprintf(th, " ushort c_cur[NCLAIMS]; /* claim-states */\n"); + } else /* the most unlikely case */ + { fprintf(th, " uint c_cur[NCLAIMS]; /* claim-states */\n"); + } + fprintf(th, "} P%d;\n", nrRdy+1); + fprintf(th, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n"); + fprintf(th, " #define Air%d (0)\n\n", nrRdy+1); + fprintf(th, "#endif\n"); + /* + * find special states as: + * stopstate [ claimnr ][ curstate ] == 1 + * accpstate [ claimnr ][ curstate ] + * progstate [ claimnr ][ curstate ] + * reached [ claimnr ][ curstate ] + * visstate [ claimnr ][ curstate ] + * loopstate [ claimnr ][ curstate ] + * mapstate [ claimnr ][ curstate ] + */ + } else + { fprintf(th, "\n#define Pclaim P0\n"); + fprintf(th, "#ifndef NCLAIMS\n"); + fprintf(th, " #define NCLAIMS 1\n"); + fprintf(th, "#endif\n"); + fprintf(th, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n"); + } ntimes(th, 0, 1, Head0); if (separate != 2) { extern void c_add_stack(FILE *); + extern void c_stack_size(FILE *); ntimes(th, 0, 1, Header); + fprintf(th, "#define StackSize ("); + c_stack_size(th); + fprintf(th, ")\n"); + c_add_stack(th); ntimes(th, 0, 1, Header0); } @@ -96,7 +199,13 @@ hastrack = c_add_sv(th); + fprintf(th, "#ifdef TRIX\n"); + fprintf(th, " /* room for 512 proc+chan ptrs, + safety margin */\n"); + fprintf(th, " char *_ids_[MAXPROC+MAXQ+4];\n"); + fprintf(th, "#else\n"); fprintf(th, " uchar sv[VECTORSZ];\n"); + fprintf(th, "#endif\n"); + fprintf(th, "} State"); #ifdef SOLARIS fprintf(th,"\n#ifdef GCC\n"); @@ -105,6 +214,23 @@ #endif fprintf(th, ";\n\n"); + fprintf(th, "#ifdef TRIX\n"); + fprintf(th, "typedef struct TRIX_v6 {\n"); + fprintf(th, " uchar *body; /* aligned */\n"); + fprintf(th, "#ifndef BFS\n"); + fprintf(th, " short modified;\n"); + fprintf(th, "#endif\n"); + fprintf(th, " short psize;\n"); + fprintf(th, " short parent_pid;\n"); + fprintf(th, " struct TRIX_v6 *nxt;\n"); + fprintf(th, "} TRIX_v6;\n"); + fprintf(th, "TRIX_v6 *freebodies;\n"); + fprintf(th, "TRIX_v6 *processes[MAXPROC+1];\n"); + fprintf(th, "TRIX_v6 *channels[MAXQ+1]; \n"); + fprintf(th, "long _p_count[MAXPROC];\n"); + fprintf(th, "long _c_count[MAXPROC];\n"); + fprintf(th, "#endif\n\n"); + fprintf(th, "#define HAS_TRACK %d\n", hastrack); if (separate != 2) @@ -114,16 +240,52 @@ void genaddproc(void) { ProcList *p; - int i = 0; + int i = 0, j; - if (separate ==2) goto shortcut; + if (separate == 2) goto shortcut; - fprintf(tc, "int\naddproc(int n"); - for (i = 0; i < Npars; i++) + fprintf(tc, "\n#ifdef TRIX\n"); + fprintf(tc, "int what_p_size(int);\n"); + fprintf(tc, "int what_q_size(int);\n\n"); + /* the number of processes just changed by 1 (up or down) */ + /* this means that the channel indices move up or down by one slot */ + /* not all new channels may have a valid index yet, but we move */ + /* all of them anyway, as if they existed */ + fprintf(tc, "void\nre_mark_all(int whichway)\n"); + fprintf(tc, "{ int j;\n"); + fprintf(tc, " #ifdef V_TRIX\n"); + fprintf(tc, " printf(\"%%d: re_mark_all channels %%d\\n\", depth, whichway);\n"); + fprintf(tc, " #endif\n"); + fprintf(tc, " #ifndef BFS\n"); + fprintf(tc, " for (j = 0; j < now._nr_qs; j++)\n"); + fprintf(tc, " channels[j]->modified = 1; /* channel index moved */\n"); + fprintf(tc, " #endif\n"); + fprintf(tc, " #ifndef TRIX_ORIG\n"); + fprintf(tc, " if (whichway > 0)\n"); + fprintf(tc, " { for (j = now._nr_pr + now._nr_qs - 1; j >= now._nr_pr; j--)\n"); + fprintf(tc, " now._ids_[j] = now._ids_[j-1];\n"); + fprintf(tc, " } else\n"); + fprintf(tc, " { for (j = now._nr_pr; j < now._nr_pr + now._nr_qs; j++)\n"); + fprintf(tc, " now._ids_[j] = now._ids_[j+1];\n"); + fprintf(tc, " }\n"); + fprintf(tc, " #endif\n"); + fprintf(tc, "}\n"); + + fprintf(tc, "#endif\n\n"); + + fprintf(tc, "int\naddproc(int calling_pid, int n"); + for (/* i = 0 */; i < Npars; i++) fprintf(tc, ", int par%d", i); ntimes(tc, 0, 1, Addp0); ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */ + + if (nclaims > 1) + { fprintf(tc, "#ifndef NOCLAIM\n"); + ntimes(tc, nrRdy+1, nrRdy+2, R5); + fprintf(tc, "#endif\n"); + } + ntimes(tc, 0, 1, Addp1); if (has_provided) @@ -132,6 +294,9 @@ fprintf(tt, "{\n\tswitch(ot) {\n"); } shortcut: + if (nclaims > 1) + { multi_init(); + } tc_predef_np(); for (p = rdy; p; p = p->nxt) { Pid = p->tn; @@ -167,13 +332,18 @@ switch (separate) { case 2: - if (claimnr >= 0) - ntimes(tc, claimnr, claimnr+1, R0); /* claim only */ + if (nclaims > 0) + { for (p = rdy; p; p = p->nxt) + { if (p->b == N_CLAIM) + { ntimes(tc, p->tn, p->tn+1, R0); /* claims only */ + } } } break; case 1: ntimes(tc, 0, 1, Code0); - ntimes(tc, 0, claimnr, R0); /* all except claim */ - ntimes(tc, claimnr+1, nrRdy, R0); + for (p = rdy; p; p = p->nxt) + { if (p->b != N_CLAIM) + { ntimes(tc, p->tn, p->tn+1, R0); /* all except claims */ + } } break; case 0: ntimes(tc, 0, 1, Code0); @@ -186,44 +356,53 @@ switch (separate) { case 2: - if (claimnr >= 0) - ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */ + if (nclaims > 0) + { for (p = rdy; p; p = p->nxt) + { if (p->b == N_CLAIM) + { ntimes(tc, p->tn, p->tn+1, R0a); /* claims only */ + } } } return; case 1: - ntimes(tc, 0, claimnr, R0a); /* all except claim */ - ntimes(tc, claimnr+1, nrRdy, R0a); + for (p = rdy; p; p = p->nxt) + { if (p->b != N_CLAIM) + { ntimes(tc, p->tn, p->tn+1, R0a); /* all except claims */ + } } fprintf(tc, " if (state_tables)\n"); - fprintf(tc, " ini_claim(%d, 0);\n", claimnr); + fprintf(tc, " ini_claim(%d, 0);\n", claimnr); /* the default claim */ + if (acceptors == 0) + { acceptors = 1; /* assume at least 1 acceptstate */ + } break; case 0: ntimes(tc, 0, nrRdy, R0a); /* all */ break; } - ntimes(tc, 0, 1, R0b); - if (separate == 1 && acceptors == 0) - acceptors = 1; /* assume at least 1 acceptstate */ ntimes(th, acceptors, acceptors+1, Code1); ntimes(th, progressors, progressors+1, Code3); ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */ - fprintf(tc, " iniglobals();\n"); - ntimes(tc, 0, 1, Code2a); - ntimes(tc, 0, 1, Code2b); /* bfs option */ - ntimes(tc, 0, 1, Code2c); + ntimes(tc, 0, 1, Code2a); /* dfs, bfs */ + ntimes(tc, 0, 1, Code2c); /* multicore */ + ntimes(tc, 0, 1, Code2d); + + fprintf(tc, "void\ndo_reach(void)\n{\n"); ntimes(tc, 0, nrRdy, R4); fprintf(tc, "}\n\n"); - fprintf(tc, "void\n"); - fprintf(tc, "iniglobals(void)\n{\n"); + fprintf(tc, "void\niniglobals(int calling_pid)\n{\n"); + ntimes(tc, 1, u_sync+u_async+1, R3); /* because nqs is still 0 */ + fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);\n"); + fprintf(tc, "\tif ((Maxbody %% WS) != 0)\n"); + fprintf(tc, "\t Maxbody += WS - (Maxbody %% WS);\n\n"); + + /* after the value of Maxbody has settled */ if (doglobal("", INIV) > 0) { fprintf(tc, "#ifdef VAR_RANGES\n"); (void) doglobal("logval(\"", LOGV); fprintf(tc, "#endif\n"); } - ntimes(tc, 1, nqs+1, R3); - fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);"); - fprintf(tc, "\n}\n\n"); + fprintf(tc, "}\n\n"); } void @@ -248,13 +427,13 @@ Label *l; int j; char foo[128]; - if ((i == claimnr && separate == 1) - || (i != claimnr && separate == 2)) + if ((pid_is_claim(i) && separate == 1) + || (!pid_is_claim(i) && separate == 2)) return; for (l = labtab; l; l = l->nxt) for (j = 0; ln[j].n; j++) - if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0 + { if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0 && strcmp(l->c->name, s->name) == 0) { fprintf(tc, "\t%s[%d][%d] = 1;\n", ln[j].t, i, l->e->seqno); @@ -272,8 +451,7 @@ Fname = l->e->n->fn; printf("spin: %3d:%s, warning, %s - is invisible\n", lineno, Fname?Fname->name:"-", foo); - } - } + } } } /* visible states -- through remote refs: */ for (l = labtab; l; l = l->nxt) if (l->visible @@ -305,7 +483,7 @@ n = (s->context != ZS)?s->context->ini:s->ini; if (n) - printf("line %3d %s, ", n->ln, n->fn->name); + printf("line %s:%d, ", n->fn->name, n->ln); } void @@ -338,7 +516,7 @@ { if (!(verbose&32)) return; sputtype(buf, sp->type); i = (int) strlen(buf); - while (buf[--i] == ' ') buf[i] = '\0'; + while (i > 0 && buf[--i] == ' ') buf[i] = '\0'; prehint(sp); if (sp->context) printf("proctype %s:", s); @@ -361,12 +539,12 @@ } } -int -dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s) +static int +dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, enum btypes b) { int h, j, k=0; extern int nr_errs; Ordered *walk; Symbol *sp; - char buf[64], buf2[128], buf3[128]; + char buf[128], buf2[128], buf3[128]; if (dowhat == INIV) { /* initialize in order of declaration */ @@ -390,7 +568,8 @@ if (sp->context && !sp->owner && sp->type == Types[j] - && ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1)) + && ((h == 0 && (sp->nel == 1 && sp->isarray == 0)) + || (h == 1 && (sp->nel > 1 || sp->isarray == 1))) && strcmp(s, sp->context->name) == 0) { switch (dowhat) { case LOGV: @@ -409,7 +588,7 @@ k++; break; } - if (strcmp(s, ":never:") == 0) + if (b == N_CLAIM) { printf("error: %s defines local %s\n", s, sp->name); nr_errs++; @@ -426,7 +605,7 @@ if (!qtab) { fprintf(fd, "void\nc_chandump(int unused) "); - fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n"); + fprintf(fd, "{ unused++; /* avoid complaints */ }\n"); return; } @@ -465,9 +644,19 @@ void c_var(FILE *fd, char *pref, Symbol *sp) -{ char buf[256]; +{ char *ptr, buf[256]; int i; + if (!sp) + { fatal("cannot happen - c_var", 0); + } + + ptr = sp?sp->name:""; + if (!old_scope_rules) + { while (*ptr == '_' || isdigit((int)*ptr)) + { ptr++; + } } + switch (sp->type) { case STRUCT: /* c_struct(fd, pref, sp); */ @@ -480,30 +669,29 @@ case SHORT: case INT: case UNSIGNED: sputtype(buf, sp->type); - if (sp->nel == 1) + if (sp->nel == 1 && sp->isarray == 0) { fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n", - buf, sp->name, pref, sp->name); + buf, ptr, pref, sp->name); } else { fprintf(fd, "\t{\tint l_in;\n"); fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel); fprintf(fd, "\t\t{\n"); fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n", - buf, sp->name, pref, sp->name); + buf, ptr, pref, sp->name); fprintf(fd, "\t\t}\n"); fprintf(fd, "\t}\n"); } break; case CHAN: - if (sp->nel == 1) - { fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ", - sp->name); + if (sp->nel == 1 && sp->isarray == 0) + { fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ", ptr); fprintf(fd, "%s%s, q_len(%s%s));\n", pref, sp->name, pref, sp->name); fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name); } else for (i = 0; i < sp->nel; i++) { fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ", - sp->name, i); + ptr, i); fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n", pref, sp->name, i, pref, sp->name, i); fprintf(fd, "\tc_chandump(%s%s[%d]);\n", @@ -518,9 +706,7 @@ { Ordered *walk; Symbol *sp; - if (strcmp(p->n->name, ":never:") != 0 - && strcmp(p->n->name, ":trace:") != 0 - && strcmp(p->n->name, ":notrace:") != 0) + if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE) for (walk = all_names; walk; walk = walk->next) { sp = walk->entry; if (!sp->context @@ -541,9 +727,7 @@ Symbol *sp; char pref[64]; - if (strcmp(p->n->name, ":never:") != 0 - && strcmp(p->n->name, ":trace:") != 0 - && strcmp(p->n->name, ":notrace:") != 0) + if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE) for (walk = all_names; walk; walk = walk->next) { sp = walk->entry; if (!sp->context @@ -583,8 +767,6 @@ fprintf(fd, " switch(tp) {\n"); for (p = rdy; p; p = p->nxt) { fprintf(fd, " case %d:\n", p->tn); - fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n", - p->n->name); if (c_splurge_any(p)) { fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n", p->n->name); @@ -633,8 +815,9 @@ checktype(sp, (char *) 0); cnt++; /* fall through */ case PUTV: - do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp, - "", " = ", ";\n"); + do_var(tc, dowhat, + (sp->hidden&1)?"":"now.", sp, + "", " = ", ";\n"); break; } } } return cnt; @@ -665,15 +848,25 @@ do_var(FILE *ofd, int dowhat, char *s, Symbol *sp, char *pre, char *sep, char *ter) { int i; + char *ptr = sp?sp->name:""; + + if (!sp) + { fatal("cannot happen - do_var", 0); + } switch(dowhat) { case PUTV: - if (sp->hidden&1) break; typ2c(sp); break; + case LOGV: + if (!old_scope_rules) + { while (*ptr == '_' || isdigit((int)*ptr)) + { ptr++; + } } + /* fall thru */ case INIV: if (sp->type == STRUCT) { /* struct may contain a chan */ @@ -682,13 +875,16 @@ } if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */ break; - if (sp->nel == 1) - { fprintf(ofd, "\t\t%s%s%s%s", - pre, s, sp->name, sep); - if (dowhat == LOGV) + if (sp->nel == 1 && sp->isarray == 0) + { if (dowhat == LOGV) + { fprintf(ofd, "\t\t%s%s%s%s", + pre, s, ptr, sep); fprintf(ofd, "%s%s", s, sp->name); - else + } else + { fprintf(ofd, "\t\t%s%s%s%s", + pre, s, sp->name, sep); do_init(ofd, sp); + } fprintf(ofd, "%s", ter); } else { if (sp->ini && sp->ini->ntyp == CHAN) @@ -722,42 +918,31 @@ static void do_init(FILE *ofd, Symbol *sp) -{ int i; extern Queue *ltab[]; +{ int i; if (sp->ini && sp->type == CHAN && ((i = qmake(sp)) > 0)) { if (sp->ini->ntyp == CHAN) - fprintf(ofd, "addqueue(%d, %d)", - i, ltab[i-1]->nslots == 0); - else - fprintf(ofd, "%d", i); + { fprintf(ofd, "addqueue(calling_pid, %d, %d)", + i, ltab[i-1]->nslots == 0); + } else + { fprintf(ofd, "%d", i); + } } else - putstmnt(ofd, sp->ini, 0); -} - -static int -blog(int n) /* for small log2 without rounding problems */ -{ int m=1, r=2; - - while (r < n) { m++; r *= 2; } - return 1+m; + { putstmnt(ofd, sp->ini, 0); + } } static void -put_ptype(char *s, int i, int m0, int m1) +put_ptype(char *s, int i, int m0, int m1, enum btypes b) { int k; - if (strcmp(s, ":init:") == 0) - fprintf(th, "#define Pinit ((P%d *)this)\n", i); - - if (strcmp(s, ":never:") != 0 - && strcmp(s, ":trace:") != 0 - && strcmp(s, ":notrace:") != 0 - && strcmp(s, ":init:") != 0 - && strcmp(s, "_:never_template:_") != 0 - && strcmp(s, "np_") != 0) - fprintf(th, "#define P%s ((P%d *)this)\n", s, i); + if (b == I_PROC) + { fprintf(th, "#define Pinit ((P%d *)this)\n", i); + } else if (b == P_PROC || b == A_PROC) + { fprintf(th, "#define P%s ((P%d *)this)\n", s, i); + } fprintf(th, "typedef struct P%d { /* %s */\n", i, s); fprintf(th, " unsigned _pid : 8; /* 0..255 */\n"); @@ -765,14 +950,14 @@ fprintf(th, " unsigned _p : %d; /* state */\n", blog(m0)); LstSet = ZS; nBits = 8 + blog(m1) + blog(m0); - k = dolocal(tc, "", PUTV, i, s); /* includes pars */ + k = dolocal(tc, "", PUTV, i, s, b); /* includes pars */ c_add_loc(th, s); fprintf(th, "} P%d;\n", i); if ((!LstSet && k > 0) || has_state) fprintf(th, "#define Air%d 0\n", i); - else + else if (LstSet || k == 0) /* 5.0, added condition */ { fprintf(th, "#define Air%d (sizeof(P%d) - ", i, i); if (k == 0) { fprintf(th, "%d", (nBits+7)/8); @@ -813,6 +998,7 @@ fprintf(th, "#define _NP_ %d\n", i); /* if (separate == 2) fprintf(th, "extern "); */ fprintf(th, "uchar reached%d[3]; /* np_ */\n", i); + fprintf(th, "uchar *loopstate%d; /* np_ */\n", i); fprintf(th, "#define nstates%d 3 /* np_ */\n", i); fprintf(th, "#define endstate%d 2 /* np_ */\n\n", i); @@ -831,6 +1017,48 @@ } static void +multi_init(void) +{ ProcList *p; + Element *e; + int i = nrRdy+1; + int ini, j; + int nrc = nclaims; + + fprintf(tc, "#ifndef NOCLAIM\n"); + fprintf(tc, "\tcase %d: /* claim select */\n", i); + for (p = rdy, j = 0; p; p = p->nxt, j++) + { if (p->b == N_CLAIM) + { e = p->s->frst; + ini = huntele(e, e->status, -1)->seqno; + + fprintf(tc, "\t\tspin_c_typ[%d] = %d; /* %s */\n", + j, p->tn, p->n->name); + fprintf(tc, "\t\t((P%d *)pptr(h))->c_cur[%d] = %d;\n", + i, j, ini); + fprintf(tc, "\t\treached%d[%d]=1;\n", p->tn, ini); + + /* the default initial claim is first one in model */ + if (--nrc == 0) + { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, p->tn); + fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini); + fprintf(tc, "\t\t((P%d *)pptr(h))->_n = %d; /* %s */\n", + i, j, p->n->name); + fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", p->tn); + fprintf(tc, "#ifndef BFS\n"); + fprintf(tc, "\t\tif (whichclaim == -1 && claimname == NULL)\n"); + fprintf(tc, "\t\t\tprintf(\"0: Claim %s (%d), from state %d\\n\");\n", + p->n->name, p->tn, ini); + fprintf(tc, "#endif\n"); + } + } } + fprintf(tc, "\t\tif (whichclaim != -1)\n"); + fprintf(tc, "\t\t{ select_claim(whichclaim);\n"); + fprintf(tc, "\t\t}\n"); + fprintf(tc, "\t\tbreak;\n\n"); + fprintf(tc, "#endif\n"); +} + +static void put_pinit(ProcList *P) { Lextok *fp, *fpt, *t; Element *e = P->s->frst; @@ -839,29 +1067,30 @@ int i = P->tn; int ini, j, k; - if (i == claimnr + if (pid_is_claim(i) && separate == 1) { fprintf(tc, "\tcase %d: /* %s */\n", i, s->name); fprintf(tc, "\t\tini_claim(%d, h);\n", i); fprintf(tc, "\t\tbreak;\n"); return; } - if (i != claimnr + if (!pid_is_claim(i) && separate == 2) return; ini = huntele(e, e->status, -1)->seqno; fprintf(th, "#define start%d %d\n", i, ini); - if (i == claimnr) - fprintf(th, "#define start_claim %d\n", ini); if (i == eventmapnr) fprintf(th, "#define start_event %d\n", ini); fprintf(tc, "\tcase %d: /* %s */\n", i, s->name); fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i); - fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;", i, ini); - fprintf(tc, " reached%d[%d]=1;\n", i, ini); + fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini); + fprintf(tc, "\t\treached%d[%d]=1;\n", i, ini); + if (P->b == N_CLAIM) + { fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", i); + } if (has_provided) { fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name); @@ -879,7 +1108,7 @@ for (fp = p, j=0; fp; fp = fp->rgt) for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++) { t = (fpt->ntyp == ',') ? fpt->lft : fpt; - if (t->sym->nel != 1) + if (t->sym->nel > 1 || t->sym->isarray) { lineno = t->ln; Fname = t->fn; fatal("array in parameter list, %s", @@ -898,10 +1127,10 @@ fprintf(tc, " = par%d;\n", j); } fprintf(tc, "\t\t/* locals: */\n"); - k = dolocal(tc, "", INIV, i, s->name); + k = dolocal(tc, "", INIV, i, s->name, P->b); if (k > 0) { fprintf(tc, "#ifdef VAR_RANGES\n"); - (void) dolocal(tc, "logval(\"", LOGV, i, s->name); + (void) dolocal(tc, "logval(\"", LOGV, i, s->name, P->b); fprintf(tc, "#endif\n"); } @@ -939,7 +1168,7 @@ int cnt=0; /* a precaution against loops */ if (e) - for (cnt = 0; cnt < 200 && e->n; cnt++) + for ( ; cnt < 200 && e->n; cnt++) { if (e->seqno == stopat) break; @@ -992,7 +1221,7 @@ nBits += sp->nbits; break; case BIT: - if (sp->nel == 1 && !(sp->hidden&1)) + if (sp->nel == 1 && sp->isarray == 0 && !(sp->hidden&1)) { fprintf(th, "\tunsigned %s : 1", sp->name); LstSet = sp; nBits++; @@ -1031,7 +1260,7 @@ fatal("variable %s undeclared", sp->name); } - if (sp->nel != 1) + if (sp->nel > 1 || sp->isarray) fprintf(th, "[%d]", sp->nel); fprintf(th, ";\n"); } @@ -1124,6 +1353,22 @@ ntimes(tc, 0, 1, Addq1); + fprintf(tc, "#ifdef TRIX\n"); + fprintf(tc, "int\nwhat_p_size(int t)\n{\tint j;\n"); + fprintf(tc, " switch (t) {\n"); + ntimes(tc, 0, nrRdy+1, R5); /* +1 for np_ */ + fprintf(tc, " default: Uerror(\"bad proctype\");\n"); + fprintf(tc, " }\n return j;\n}\n\n"); + + fprintf(tc, "int\nwhat_q_size(int t)\n{\tint j;\n"); + fprintf(tc, " switch (t) {\n"); + for (j = 0; j < nqs+1; j++) + { fprintf(tc, " case %d: j = sizeof(Q%d); break;\n", j, j); + } + fprintf(tc, " default: Uerror(\"bad qtype\");\n"); + fprintf(tc, " }\n return j;\n}\n"); + fprintf(tc, "#endif\n\n"); + if (has_random) { fprintf(th, "int Q_has(int"); for (j = 0; j < Mpars; j++) @@ -1159,7 +1404,7 @@ fprintf(tc, "void\nqsend(int into, int sorted"); for (j = 0; j < Mpars; j++) fprintf(tc, ", int fld%d", j); - fprintf(tc, ")\n"); + fprintf(tc, ", int args_given)\n"); ntimes(tc, 0, 1, Addq11); for (q = qtab; q; q = q->nxt) @@ -1202,6 +1447,12 @@ sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid); for (j = 0; j < q->nflds; j++) fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j); + fprintf(tc, "\t\tif (args_given != %d)\n", q->nflds); + fprintf(tc, "\t\t{ if (args_given > %d)\n", q->nflds); + fprintf(tc, "\t\t uerror(\"too many parameters in send stmnt\");\n"); + fprintf(tc, "\t\t else\n"); + fprintf(tc, "\t\t uerror(\"too few parameters in send stmnt\");\n"); + fprintf(tc, "\t\t}\n"); fprintf(tc, "\t\tbreak;\n"); } ntimes(tc, 0, 1, Addq2); @@ -1266,9 +1517,10 @@ fprintf(th, "void qsend(int, int"); for (j = 0; j < Mpars; j++) fprintf(th, ", int"); - fprintf(th, ");\n"); + fprintf(th, ", int);\n"); - fprintf(th, "#define Addproc(x) addproc(x"); + fprintf(th, "#define Addproc(x) addproc(256, x"); + /* 256 is param outside the range of valid pids */ for (j = 0; j < Npars; j++) fprintf(th, ", 0"); fprintf(th, ")\n"); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen1.h --- a/sys/src/cmd/spin/pangen1.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen1.h Tue Mar 06 23:34:10 2012 +0100 @@ -1,6 +1,6 @@ /***** spin: pangen1.h *****/ -/* Copyright (c) 1989-2005 by Lucent Technologies, Bell Laboratories. */ +/* 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 */ @@ -8,13 +8,42 @@ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ +/* (c) 2007-2011: additions, enhancements, and bugfixes GJH */ static char *Code2a[] = { /* the tail of procedure run() */ + " if (state_tables)", + " { if (dodot) exit(0);", + " printf(\"\\nTransition Type: \");", + " printf(\"A=atomic; D=d_step; L=local; G=global\\n\");", + " printf(\"Source-State Labels: \");", + " printf(\"p=progress; e=end; a=accept;\\n\");", + "#ifdef MERGED", + " printf(\"Note: statement merging was used. Only the first\\n\");", + " printf(\" stmnt executed in each merge sequence is shown\\n\");", + " printf(\" (use spin -a -o3 to disable statement merging)\\n\");", + "#endif", + " pan_exit(0);", + " }", + "#if defined(BFS) && defined(TRIX)", /* before iniglobals */ + " { int i;", + " for (i = 0; i < MAXPROC+1; i++)", + " { processes[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));", + " processes[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));", + " }", + " for (i = 0; i < MAXQ+1; i++)", + " { channels[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));", + " channels[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));", + " } }", + "#endif", + " iniglobals(258); /* arg outside range of pids */", "#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)", " if (!state_tables", "#ifdef HAS_CODE", " && !readtrail", "#endif", + "#if NCORE>1", + " && core_id == 0", + "#endif", " )", " { printf(\"warning: for p.o. reduction to be valid \");", " printf(\"the never claim must be stutter-invariant\\n\");", @@ -24,33 +53,49 @@ "#endif", " UnBlock; /* disable rendez-vous */", "#ifdef BITSTATE", -#ifndef POWOW " if (udmem)", " { udmem *= 1024L*1024L;", + " #if NCORE>1", + " if (!readtrail)", + " { void init_SS(unsigned long);", + " init_SS((unsigned long) udmem);", + " } else", + " #endif", " SS = (uchar *) emalloc(udmem);", " bstore = bstore_mod;", " } else", -#endif - " SS = (uchar *) emalloc(1L<<(ssize-3));", - "#else", + " #if NCORE>1", + " { void init_SS(unsigned long);", + " init_SS(ONE_L<<(ssize-3));", + " }", + " #else", + " SS = (uchar *) emalloc(ONE_L<<(ssize-3));", + " #endif", + "#else", /* if not BITSTATE */ " hinit();", "#endif", "#if defined(FULLSTACK) && defined(BITSTATE)", " onstack_init();", "#endif", "#if defined(CNTRSTACK) && !defined(BFS)", - " LL = (uchar *) emalloc(1L<<(ssize-3));", - "#endif", - " stack = ( Stack *) emalloc(sizeof(Stack));", + " LL = (uchar *) emalloc(ONE_L<<(ssize-3));", + "#endif", + " stack = (_Stack *) emalloc(sizeof(_Stack));", " svtack = (Svtack *) emalloc(sizeof(Svtack));", " /* a place to point for Pptr of non-running procs: */", - " noptr = (uchar *) emalloc(Maxbody * sizeof(char));", - "#ifdef SVDUMP", + " noqptr = noptr = (uchar *) emalloc(Maxbody * sizeof(char));", + "#if defined(SVDUMP) && defined(VERBOSE)", " if (vprefix > 0)", - " write(svfd, (uchar *) &vprefix, sizeof(int));", + " (void) write(svfd, (uchar *) &vprefix, sizeof(int));", "#endif", "#ifdef VERI", - " Addproc(VERI); /* never - pid = 0 */", + " Addproc(VERI); /* pid = 0 */", + " #if NCLAIMS>1", + " if (claimname != NULL)", + " { whichclaim = find_claim(claimname);", + " select_claim(whichclaim);", + " }", + " #endif", "#endif", " active_procs(); /* started after never */", "#ifdef EVENT_TRACE", @@ -70,11 +115,17 @@ " { printf(\"Run %%d:\\n\", HASH_NR);", " wrap_stats();", " printf(\"\\n\");", - " memset(SS, 0, 1L<<(ssize-3));", - "#if defined(CNTRSTACK)", - " memset(LL, 0, 1L<<(ssize-3));", + + " if (udmem) /* Dillinger 3/2/09 */", + " { memset(SS, 0, udmem);", + " } else", + " { memset(SS, 0, ONE_L<<(ssize-3));", + " }", + + "#ifdef CNTRSTACK", + " memset(LL, 0, ONE_L<<(ssize-3));", "#endif", - "#if defined(FULLSTACK)", + "#ifdef FULLSTACK", " memset((uchar *) S_Tab, 0, ", " maxdepth*sizeof(struct H_el *));", "#endif", @@ -90,6 +141,68 @@ "int provided(int, uchar, int, Trans *);", "#endif", + "#if NCORE>1", + "#define GLOBAL_LOCK (0)", + "#ifndef CS_N", + "#define CS_N (256*NCORE)", /* must be a power of 2 */ + "#endif", + + "#ifdef NGQ", /* no global queue */ + "#define NR_QS (NCORE)", + "#define CS_NR (CS_N+1) /* 2^N + 1, nr critical sections */", + "#define GQ_RD GLOBAL_LOCK", /* not really used in this mode */ + "#define GQ_WR GLOBAL_LOCK", /* but just in case... */ + "#define CS_ID (1 + (int) (j1_spin & (CS_N-1))) /* mask: 2^N - 1, zero reserved */", + "#define QLOCK(n) (1+n)", /* overlaps first n zones of hashtable */ + "#else", + "#define NR_QS (NCORE+1)", /* add a global queue */ + "#define CS_NR (CS_N+3)", /* 2 extra locks for global q */ + "#define GQ_RD (1)", /* read access to global q */ + "#define GQ_WR (2)", /* write access to global q */ + "#define CS_ID (3 + (int) (j1_spin & (CS_N-1)))", + "#define QLOCK(n) (3+n)",/* overlaps first n zones of hashtable */ + "#endif", + "", + "void e_critical(int);", + "void x_critical(int);", + "", + "#ifndef SEP_STATE", + " #define enter_critical(w) e_critical(w)", + " #define leave_critical(w) x_critical(w)", + "#else", + " #ifdef NGQ", + " #define enter_critical(w) { if (w < 1+NCORE) e_critical(w); }", + " #define leave_critical(w) { if (w < 1+NCORE) x_critical(w); }", + " #else", + " #define enter_critical(w) { if (w < 3+NCORE) e_critical(w); }", + " #define leave_critical(w) { if (w < 3+NCORE) x_critical(w); }", + " #endif", + "#endif", + "", + "int", + "cpu_printf(const char *fmt, ...)", /* only used with VERBOSE/CHECK/DEBUG */ + "{ va_list args;", + " enter_critical(GLOBAL_LOCK); /* printing */", + " printf(\"cpu%%d: \", core_id);", + " fflush(stdout);", + " va_start(args, fmt);", + " vprintf(fmt, args);", + " va_end(args);", + " fflush(stdout);", + " leave_critical(GLOBAL_LOCK);", + " return 1;", + "}", + "#else", + "int", + "cpu_printf(const char *fmt, ...)", + "{ va_list args;", + " va_start(args, fmt);", + " vprintf(fmt, args);", + " va_end(args);", + " return 1;", + "}", + "#endif", + #ifndef PRINTF "int", "Printf(const char *fmt, ...)", @@ -172,44 +285,92 @@ "#endif", "#endif", + "#if NCORE>1", + "extern void cleanup_shm(int);", + "volatile unsigned int *search_terminated; /* to signal early termination */", + /* + * Meaning of bitflags in search_terminated: + * 1 set by pan_exit + * 2 set by wrapup + * 4 set by uerror + * 8 set by sudden_stop -- called after someone_crashed and [Uu]error + * 16 set by cleanup_shm + * 32 set by give_up -- called on signal + * 64 set by proxy_exit + * 128 set by proxy on write port failure + * 256 set by proxy on someone_crashed + * + * Flags 8|32|128|256 indicate abnormal termination + * + * The flags are checked in 4 functions in the code: + * sudden_stop() + * someone_crashed() (proxy and pan version) + * mem_hand_off() + */ + "#endif", "void", "pan_exit(int val)", - "{ if (signoff) printf(\"--end of output--\\n\");", + "{ void stop_timer(void);", + " if (signoff)", + " { printf(\"--end of output--\\n\");", + " }", + "#if NCORE>1", + " if (search_terminated != NULL)", + " { *search_terminated |= 1; /* pan_exit */", + " }", + "#ifdef USE_DISK", + " { void dsk_stats(void);", + " dsk_stats();", + " }", + "#endif", + " if (!state_tables && !readtrail)", + " { cleanup_shm(1);", + " }", + "#endif", + " if (val == 2)", + " { val = 0;", + " } else", + " { stop_timer();", + " }", + "", + "#ifdef C_EXIT", + " C_EXIT; /* trust that it defines a fct */", + "#endif", " exit(val);", "}", "#ifdef HAS_CODE", + "static char tbuf[2][2048];", + "", "char *", "transmognify(char *s)", "{ char *v, *w;", - " static char buf[2][2048];", " int i, toggle = 0;", - " if (!s || strlen(s) > 2047) return s;", - " memset(buf[0], 0, 2048);", - " memset(buf[1], 0, 2048);", - " strcpy(buf[toggle], s);", - " while ((v = strstr(buf[toggle], \"{c_code\")))", /* assign v */ + " memset(tbuf[0], 0, 2048);", + " memset(tbuf[1], 0, 2048);", + " strcpy(tbuf[toggle], s);", + " while ((v = strstr(tbuf[toggle], \"{c_code\")))", /* assign v */ " { *v = '\\0'; v++;", - " strcpy(buf[1-toggle], buf[toggle]);", + " strcpy(tbuf[1-toggle], tbuf[toggle]);", " for (w = v; *w != '}' && *w != '\\0'; w++) /* skip */;", " if (*w != '}') return s;", " *w = '\\0'; w++;", " for (i = 0; code_lookup[i].c; i++)", " if (strcmp(v, code_lookup[i].c) == 0", " && strlen(v) == strlen(code_lookup[i].c))", - " { if (strlen(buf[1-toggle])", + " { if (strlen(tbuf[1-toggle])", " + strlen(code_lookup[i].t)", " + strlen(w) > 2047)", " return s;", - " strcat(buf[1-toggle], code_lookup[i].t);", + " strcat(tbuf[1-toggle], code_lookup[i].t);", " break;", " }", - " strcat(buf[1-toggle], w);", + " strcat(tbuf[1-toggle], w);", " toggle = 1 - toggle;", " }", - " buf[toggle][2047] = '\\0';", - " return buf[toggle];", + " tbuf[toggle][2047] = '\\0';", + " return tbuf[toggle];", "}", "#else", "char * transmognify(char *s) { return s; }", @@ -223,7 +384,6 @@ "", " for (t = trans[ot][tt]; t; t = t->nxt)", " { printf(\"\\t\\t\");", - " q = transmognify(t->tp);", " for ( ; q && *q; q++)", " if (*q == '\\n')", @@ -233,6 +393,17 @@ " printf(\"\\n\");", " }", "}", + "", + "char *", + "find_source(int tp, int s)", + "{", + " if (s >= flref[tp]->from", + " && s <= flref[tp]->upto)", + " { return flref[tp]->fnm;", + " }", + " return PanSource; /* i.e., don't know */", + "}", + "", "void", "wrap_trail(void)", "{ static int wrap_in_progress = 0;", @@ -243,14 +414,15 @@ "", " printf(\"spin: trail ends after %%ld steps\\n\", depth);", " if (onlyproc >= 0)", - " { if (onlyproc >= now._nr_pr) pan_exit(0);", + " { if (onlyproc >= now._nr_pr) { pan_exit(0); }", " II = onlyproc;", " z = (P0 *)pptr(II);", " printf(\"%%3ld:\tproc %%d (%%s) \",", " depth, II, procname[z->_t]);", " for (i = 0; src_all[i].src; i++)", " if (src_all[i].tp == (int) z->_t)", - " { printf(\" line %%3d\",", + " { printf(\" %%s:%%d\",", + " find_source((int) z->_t, (int) z->_p),", " src_all[i].src[z->_p]);", " break;", " }", @@ -269,7 +441,8 @@ " depth, II, procname[z->_t]);", " for (i = 0; src_all[i].src; i++)", " if (src_all[i].tp == (int) z->_t)", - " { printf(\" line %%3d\",", + " { printf(\" %%s:%%d\",", + " find_source((int) z->_t, (int) z->_p),", " src_all[i].src[z->_p]);", " break;", " }", @@ -293,23 +466,100 @@ "findtrail(void)", "{ FILE *fd;", " char fnm[512], *q;", - " char MyFile[512];", - "", - " strcpy(MyFile, TrailFile);", /* avoid problem with non-writable strings */ - "", + " char MyFile[512];", /* avoid using a non-writable string */ + " char MySuffix[16];", + " int try_core;", + " int candidate_files;", + "", + " if (trailfilename != NULL)", + " { fd = fopen(trailfilename, \"r\");", + " if (fd == NULL)", + " { printf(\"pan: cannot find %%s\\n\", trailfilename);", + " pan_exit(1);", + " } /* else */", + " goto success;", + " }", + "talk:", + " try_core = 1;", + " candidate_files = 0;", + " tprefix = \"trail\";", + " strcpy(MyFile, TrailFile);", + " do { /* see if there's more than one possible trailfile */", + " if (whichtrail)", + " { sprintf(fnm, \"%%s%%d.%%s\",", + " MyFile, whichtrail, tprefix);", + " fd = fopen(fnm, \"r\");", + " if (fd != NULL)", + " { candidate_files++;", + " if (verbose==100)", + " printf(\"trail%%d: %%s\\n\",", + " candidate_files, fnm);", + " fclose(fd);", + " }", + " if ((q = strchr(MyFile, \'.\')) != NULL)", + " { *q = \'\\0\';", /* e.g., strip .pml */ + " sprintf(fnm, \"%%s%%d.%%s\",", + " MyFile, whichtrail, tprefix);", + " *q = \'.\';", + " fd = fopen(fnm, \"r\");", + " if (fd != NULL)", + " { candidate_files++;", + " if (verbose==100)", + " printf(\"trail%%d: %%s\\n\",", + " candidate_files, fnm);", + " fclose(fd);", + " } }", + " } else", + " { sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);", + " fd = fopen(fnm, \"r\");", + " if (fd != NULL)", + " { candidate_files++;", + " if (verbose==100)", + " printf(\"trail%%d: %%s\\n\",", + " candidate_files, fnm);", + " fclose(fd);", + " }", + " if ((q = strchr(MyFile, \'.\')) != NULL)", + " { *q = \'\\0\';", /* e.g., strip .pml */ + " sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);", + " *q = \'.\';", + " fd = fopen(fnm, \"r\");", + " if (fd != NULL)", + " { candidate_files++;", + " if (verbose==100)", + " printf(\"trail%%d: %%s\\n\",", + " candidate_files, fnm);", + " fclose(fd);", + " } } }", + " tprefix = MySuffix;", + " sprintf(tprefix, \"cpu%%d_trail\", try_core++);", + " } while (try_core <= NCORE);", + "", + " if (candidate_files != 1)", + " { if (verbose != 100)", + " { printf(\"error: there are %%d trail files:\\n\",", + " candidate_files);", + " verbose = 100;", + " goto talk;", + " } else", + " { printf(\"pan: rm or mv all except one\\n\");", + " exit(1);", + " } }", + + " try_core = 1;", + " strcpy(MyFile, TrailFile); /* restore */", + " tprefix = \"trail\";", + "try_again:", " if (whichtrail)", " { sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, tprefix);", " fd = fopen(fnm, \"r\");", " if (fd == NULL && (q = strchr(MyFile, \'.\')))", " { *q = \'\\0\';", /* e.g., strip .pml on original file */ - " sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, tprefix);", + " sprintf(fnm, \"%%s%%d.%%s\",", + " MyFile, whichtrail, tprefix);", " *q = \'.\';", " fd = fopen(fnm, \"r\");", - " if (fd == NULL)", - " { printf(\"pan: cannot find %%s%%d.%%s or %%s\\n\", ", - " MyFile, whichtrail, tprefix, fnm);", - " pan_exit(1);", - " } }", + " }", " } else", " { sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);", " fd = fopen(fnm, \"r\");", @@ -318,15 +568,22 @@ " sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);", " *q = \'.\';", " fd = fopen(fnm, \"r\");", - " if (fd == NULL)", - " { printf(\"pan: cannot find %%s.%%s or %%s\\n\", ", - " MyFile, tprefix, fnm);", - " pan_exit(1);", - " } } }", + " } }", " if (fd == NULL)", - " { printf(\"pan: cannot find trailfile %%s\\n\", fnm);", + " { if (try_core < NCORE)", + " { tprefix = MySuffix;", + " sprintf(tprefix, \"cpu%%d_trail\", try_core++);", + " goto try_again;", + " }", + " printf(\"pan: cannot find trailfile %%s\\n\", fnm);", " pan_exit(1);", " }", + "success:", + "#if NCORE>1 && defined(SEP_STATE)", + " { void set_root(void); /* for partial traces from local root */", + " set_root();", + " }", + "#endif", " return fd;", "}", "", @@ -352,22 +609,23 @@ " break;", " }", " II = i;", - "", " z = (P0 *)pptr(II);", " for (t = trans[z->_t][z->_p]; t; t = t->nxt)", - " if (t->t_id == t_id)", + " if (t->t_id == (T_ID) t_id)", " break;", " if (!t)", " { for (i = 0; i < NrStates[z->_t]; i++)", " { t = trans[z->_t][i];", - " if (t && t->t_id == t_id)", - " { printf(\" Recovered at state %%d\\n\", i);", + " if (t && t->t_id == (T_ID) t_id)", + " { printf(\"\\tRecovered at state %%d\\n\", i);", " z->_p = i;", " goto recovered;", " } }", " printf(\"pan: Error, proc %%d type %%d state %%d: \",", " II, z->_t, z->_p);", " printf(\"transition %%d not found\\n\", t_id);", + " printf(\"pan: list of possible transitions in this process:\\n\");", + " if (z->_t >= 0 && z->_t <= _NP_)", " for (t = trans[z->_t][z->_p]; t; t = t->nxt)", " printf(\" t_id %%d -- case %%d, [%%s]\\n\",", " t->t_id, t->forw, t->tp);", @@ -391,16 +649,24 @@ " goto moveon;", " if (verbose)", - " { printf(\"depth: %%3ld proc: %%3d trans: %%3d (%%d procs) \",", - " depth, II, t_id, now._nr_pr);", - " printf(\"forw=%%3d [%%s]\\n\", t->forw, q);", - "", + " { printf(\"%%3ld: proc %%2d (%%s) \", depth, II, procname[z->_t]);", + + " for (i = 0; src_all[i].src; i++)", + " if (src_all[i].tp == (int) z->_t)", + " { printf(\" %%s:%%d \",", + " find_source((int) z->_t, (int) z->_p),", + " src_all[i].src[z->_p]);", + " break;", + " }", + + " printf(\"(state %%d) trans {%%d,%%d} [%%s]\\n\",", + " z->_p, t_id, t->forw, q?q:\"\");", + " c_globals();", " for (i = 0; i < now._nr_pr; i++)", " { c_locals(i, ((P0 *)pptr(i))->_t);", " }", - " } else", - " if (strcmp(procname[z->_t], \":never:\") == 0)", + " } else if (Btypes[z->_t] == N_CLAIM)", " { if (lastnever != (int) z->_p)", " { for (i = 0; src_all[i].src; i++)", " if (src_all[i].tp == (int) z->_t)", @@ -413,8 +679,7 @@ " }", " lastnever = z->_p;", " goto sameas;", - " } else", - " if (strcmp(procname[z->_t], \":np_:\") != 0)", + " } else if (Btypes[z->_t] != 0) /* not :np_: */", " {", "sameas: if (no_rck) goto moveon;", " if (coltrace)", @@ -429,7 +694,8 @@ " depth, II, procname[z->_t]);", " for (i = 0; src_all[i].src; i++)", " if (src_all[i].tp == (int) z->_t)", - " { printf(\" line %%3d \\\"pan_in\\\" \",", + " { printf(\" %%s:%%d \",", + " find_source((int) z->_t, (int) z->_p),", " src_all[i].src[z->_p]);", " break;", " }", @@ -439,12 +705,13 @@ " depth, II, procname[z->_t]);", " for (i = 0; src_all[i].src; i++)", " if (src_all[i].tp == (int) z->_t)", - " { printf(\" line %%3d \\\"pan_in\\\" \",", + " { printf(\" %%s:%%d \",", + " find_source((int) z->_t, (int) z->_p),", " src_all[i].src[z->_p]);", " break;", " }", " printf(\"(state %%d)\t[%%s]\\n\", z->_p, q?q:\"\");", - " printf(\"\\n\");", + " /* printf(\"\\n\"); */", " } }", "moveon: z->_p = t->st;", " }", @@ -462,19 +729,36 @@ " }", " return -1;", "}", - "#ifdef VERI", - "void check_claim(int);", + "", + "#if !defined(HASH64) && !defined(HASH32)", + " #if WS>4", + " #define HASH64", + " #else", + " #define HASH32", + " #endif", + "#endif", + "#if defined(HASH32) && defined(SAFETY) && !defined(SFH) && !defined(SPACE)", + " #define SFH", + "#endif", + "#if defined(SFH) && (defined(BITSTATE) || defined(COLLAPSE) || defined(HC) || defined(HASH64) || defined(MA))", + " #undef SFH", /* need 2 hash fcts, for which Jenkins is best */ + "#endif", /* or a 64 bit hash, which we dont have for SFH */ + /* for MA, it would slow down the search to use a larger sv then possible */ + "#if defined(SFH) && !defined(NOCOMP)", + " #define NOCOMP /* go for speed */", + "#endif", + "#if NCORE>1 && !defined(GLOB_HEAP)", + " #define SEP_HEAP /* version 5.1.2 */", "#endif", "", "#ifdef BITSTATE", -#ifndef POWOW "int", "bstore_mod(char *v, int n) /* hasharray size not a power of two */", "{ unsigned long x, y;", " unsigned int i = 1;", "", " d_hash((uchar *) v, n); /* sets j3, j4, K1, K2 */", - " x = K2; y = j3;", + " x = K1; y = j3;", /* was K2 before 5.1.1 */ " for (;;)", " { if (!(SS[x%%udmem]&(1< 0)", - " sprintf(fnm, \"%%s%%d.%%s\",", + " { sprintf(fnm, \"%%s%%d.%%s\",", " MyFile, Nr_Trails-1, tprefix);", - " else", + " } else", + " {", + "#ifdef PUTPID", + " sprintf(fnm, \"%%s_%%s_%%d.%%s\", MyFile, progname, getpid(), tprefix);", + "#else", " sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);", - "", - " if ((fd = creat(fnm, TMODE)) < 0)", + "#endif", + " }", + " if ((fd = open(fnm, w_flags, TMODE)) < 0)", " { if ((q = strchr(MyFile, \'.\')))", " { *q = \'\\0\';", /* strip .pml */ " if (iterative == 0 && Nr_Trails-1 > 0)", @@ -574,25 +867,65 @@ " else", " sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);", " *q = \'.\';", - " fd = creat(fnm, TMODE);", + " fd = open(fnm, w_flags, TMODE);", " } }", " if (fd < 0)", " { printf(\"pan: cannot create %%s\\n\", fnm);", " perror(\"cause\");", " } else", - " { printf(\"pan: wrote %%s\\n\", fnm);", + " {", + "#if NCORE>1 && (defined(SEP_STATE) || !defined(FULL_TRAIL))", + " void write_root(void); ", + " write_root();", + "#else", + " printf(\"pan: wrote %%s\\n\", fnm);", + "#endif", " }", " return fd;", "}", - 0 -}; - -static char *Code2b[] = { /* breadth-first search option */ - "#ifdef BFS", + "", + "#ifndef FREQ", + "#define FREQ (1000000)", + "#endif", + "double freq = (double) FREQ;\n", + + "#ifdef TRIX", + "void sv_populate(void);", + "", + "void", + "re_populate(void) /* restore procs and chans from now._ids_ */", + "{ int i, cnt = 0;", + " char *b;", + "#ifdef V_TRIX", + " printf(\"%%4d: re_populate\\n\", depth);", + "#endif", + " for (i = 0; i < now._nr_pr; i++, cnt++)", + " { b = now._ids_[cnt];", + " processes[i]->psize = what_p_size( ((P0 *)b)->_t );", + " memcpy(processes[i]->body, b, processes[i]->psize);", + "#ifdef TRIX_RIX", + " ((P0 *)pptr(i))->_pid = i;", + "#endif", + "#ifndef BFS", + " processes[i]->modified = 1; /* re-populate */", + "#endif", + " }", + " for (i = 0; i < now._nr_qs; i++, cnt++)", + " { b = now._ids_[cnt];", + " channels[i]->psize = what_q_size( ((Q0 *)b)->_t );", + " memcpy(channels[i]->body, b, channels[i]->psize);", + "#ifndef BFS", + " channels[i]->modified = 1; /* re-populate */", + "#endif", + " }", + "}", + "#endif\n", + + "#ifdef BFS", /* breadth-first search */ "#define Q_PROVISO", - "#ifndef INLINE_REV", - "#define INLINE_REV", - "#endif", + " #ifndef INLINE_REV", + " #define INLINE_REV", + " #endif", "", "typedef struct SV_Hold {", " State *sv;", @@ -605,13 +938,10 @@ " int sz;", /* vsize */ " int nrpr;", " int nrqs;", - "#if VECTORSZ>32000", - " int *po;", - "#else", - " short *po;", - "#endif", - " int *qo;", - " uchar *ps, *qs;", + "#ifndef TRIX", + " char *po, *qo;", + " char *ps, *qs;", + "#endif", " struct EV_Hold *nxt;", "} EV_Hold;", "", @@ -623,6 +953,9 @@ " struct H_el *lstate;", "#endif", " short boq;", + "#ifdef VERBOSE", + " unsigned long nr;", + "#endif", " struct BFS_Trail *nxt;", "} BFS_Trail;", "", @@ -630,9 +963,38 @@ "", "SV_Hold *svhold, *svfree;", "", + "#ifdef BFS_DISK", + " #ifndef BFS_LIMIT", + " #define BFS_LIMIT 100000", + " #endif", + " #ifndef BFS_DSK_LIMIT", + " #define BFS_DSK_LIMIT 1000000", + " #endif", + " #if defined(WIN32) || defined(WIN64)", + " #define RFLAGS (O_RDONLY|O_BINARY)", + " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)", + " #else", + " #define RFLAGS (O_RDONLY)", + " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)", + " #endif", + + "long bfs_size_limit;", + "int bfs_dsk_write = -1;", + "int bfs_dsk_read = -1;", + "long bfs_dsk_writes, bfs_dsk_reads;", + "int bfs_dsk_seqno_w, bfs_dsk_seqno_r;", + "#endif", + "", "uchar do_reverse(Trans *, short, uchar);", "void snapshot(void);", "", + "void", + "select_claim(int x) /* ignored in BFS mode */", + "{ if (verbose)", + " { printf(\"select %%d (ignored)\\n\", x);", + " }", + "}", + "", "SV_Hold *", "getsv(int n)", "{ SV_Hold *h = (SV_Hold *) 0, *oh;", @@ -657,8 +1019,34 @@ " if (!h)", " { h = (SV_Hold *) emalloc(sizeof(SV_Hold));", " h->sz = n;", + "#ifdef BFS_DISK", + " if (bfs_size_limit >= BFS_LIMIT)", + " { h->sv = (State *) 0; /* means: read disk */", + " bfs_dsk_writes++; /* count */", + " if (bfs_dsk_write < 0 /* file descriptor */", + " || bfs_dsk_writes%%BFS_DSK_LIMIT == 0)", + " { char dsk_nm[32];", + " if (bfs_dsk_write >= 0)", + " { (void) close(bfs_dsk_write);", + " }", + " sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_w++);", + " bfs_dsk_write = open(dsk_nm, WFLAGS, 0644);", + " if (bfs_dsk_write < 0)", + " { Uerror(\"could not create tmp disk file\");", + " }", + " printf(\"pan: created disk file %%s\\n\", dsk_nm);", + " }", + " if (write(bfs_dsk_write, (char *) &now, n) != n)", + " { Uerror(\"aborting -- disk write failed (disk full?)\");", + " }", + " return h; /* no memcpy */", + " }", /* else */ + " bfs_size_limit++;", + "#endif", " h->sv = (State *) emalloc(sizeof(State) - VECTORSZ + n);", " }", + "", + " memcpy((char *)h->sv, (char *)&now, n);", " return h;", "}", "", @@ -672,15 +1060,19 @@ " && (memcmp((char *) Mask, (char *) h->sv, n) == 0)", " && (now._nr_pr == h->nrpr)", " && (now._nr_qs == h->nrqs)", - "#if VECTORSZ>32000", + "#ifdef TRIX", + " )", + "#else", + " #if VECTORSZ>32000", " && (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(int)) == 0)", " && (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(int)) == 0)", - "#else", + " #else", " && (memcmp((char *) proc_offset, (char *) h->po, now._nr_pr * sizeof(short)) == 0)", " && (memcmp((char *) q_offset, (char *) h->qo, now._nr_qs * sizeof(short)) == 0)", - "#endif", - " && (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)", - " && (memcmp((char *) q_skip, (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))", + " #endif", + " && (memcmp((char *) proc_skip, (char *) h->ps, now._nr_pr * sizeof(uchar)) == 0)", + " && (memcmp((char *) q_skip, (char *) h->qs, now._nr_qs * sizeof(uchar)) == 0))", + "#endif", " break;", " if (!h)", " { h = (EV_Hold *) emalloc(sizeof(EV_Hold));", @@ -690,28 +1082,30 @@ "", " h->sv = (char *) emalloc(n * sizeof(char));", " memcpy((char *) h->sv, (char *) Mask, n);", - "", + "#ifndef TRIX", " if (now._nr_pr > 0)", - " { h->po = (int *) emalloc(now._nr_pr * sizeof(int));", - " h->ps = (int *) emalloc(now._nr_pr * sizeof(int));", - "#if VECTORSZ>32000", + " { h->ps = (char *) emalloc(now._nr_pr * sizeof(int));", + " memcpy((char *) h->ps, (char *) proc_skip, now._nr_pr * sizeof(uchar));", + " #if VECTORSZ>32000", + " h->po = (char *) emalloc(now._nr_pr * sizeof(int));", " memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(int));", - "#else", + " #else", + " h->po = (char *) emalloc(now._nr_pr * sizeof(short));", " memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(short));", - "#endif", - " memcpy((char *) h->ps, (char *) proc_skip, now._nr_pr * sizeof(uchar));", + " #endif", " }", " if (now._nr_qs > 0)", - " { h->qo = (int *) emalloc(now._nr_qs * sizeof(int));", - " h->qs = (int *) emalloc(now._nr_qs * sizeof(int));", - "#if VECTORSZ>32000", + " { h->qs = (char *) emalloc(now._nr_qs * sizeof(int));", + " memcpy((char *) h->qs, (char *) q_skip, now._nr_qs * sizeof(uchar));", + " #if VECTORSZ>32000", + " h->qo = (char *) emalloc(now._nr_qs * sizeof(int));", " memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(int));", - "#else", + " #else", + " h->qo = (char *) emalloc(now._nr_qs * sizeof(short));", " memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(short));", - "#endif", - " memcpy((char *) h->qs, (char *) q_skip, now._nr_qs * sizeof(uchar));", + " #endif", " }", - "", + "#endif", " h->nxt = kept;", " kept = h;", " }", @@ -724,9 +1118,9 @@ "", " oh = (SV_Hold *) 0;", " for (h = svfree; h; oh = h, h = h->nxt)", - " if (h->sz >= p->sz)", + " { if (h->sz >= p->sz)", " break;", - "", + " }", " if (!oh)", " { p->nxt = svfree;", " svfree = p;", @@ -748,6 +1142,8 @@ " { t = (BFS_Trail *) emalloc(sizeof(BFS_Trail));", " }", " t->frame = (Trail *) emalloc(sizeof(Trail));", /* always new */ + " /* new because we keep a ptr to the frame of parent states */", + " /* used for reconstructing path and recovering failed rvs etc */", " return t;", "}", "", @@ -760,8 +1156,10 @@ " t->frame->o_tt = d; /* depth */", "", " t->boq = boq;", + "#ifdef TRIX", + " sv_populate();", + "#endif", " t->onow = getsv(vsize);", - " memcpy((char *)t->onow->sv, (char *)&now, vsize);", " t->omask = getsv_mask(vsize);", "#if defined(FULLSTACK) && defined(Q_PROVISO)", " t->lstate = Lstate;", @@ -772,8 +1170,11 @@ " { bfs_bot->nxt = t;", " bfs_bot = t;", " }", + "#ifdef VERBOSE", + " t->nr = nstates;", + "#endif", "#ifdef CHECK", - " printf(\"PUSH %%u (%%d)\\n\", t->frame, d);", + " printf(\"PUSH %%u (depth %%d, nr %%d)\\n\", t->frame, d, t->nr);", "#endif", "}", "", @@ -782,45 +1183,80 @@ "{ BFS_Trail *t;", "", " if (!bfs_trail)", - " return (Trail *) 0;", - "", + " { return (Trail *) 0;", + " }", " t = bfs_trail;", " bfs_trail = t->nxt;", " if (!bfs_trail)", - " bfs_bot = (BFS_Trail *) 0;", + " { bfs_bot = (BFS_Trail *) 0;", + " }", "#if defined(Q_PROVISO) && !defined(BITSTATE) && !defined(NOREDUCE)", - " if (t->lstate) t->lstate->tagged = 0;", - "#endif", - "", + " if (t->lstate)", + " { t->lstate->tagged = 0;", + " }", + "#endif", " t->nxt = bfs_free;", " bfs_free = t;", "", " vsize = t->onow->sz;", " boq = t->boq;", - "", - " memcpy((uchar *) &now, (uchar *) t->onow->sv, vsize);", + "#ifdef BFS_DISK", + " if (t->onow->sv == (State *) 0)", + " { char dsk_nm[32];", + " bfs_dsk_reads++; /* count */", + " if (bfs_dsk_read >= 0 /* file descriptor */", + " && bfs_dsk_reads%%BFS_DSK_LIMIT == 0)", + " { (void) close(bfs_dsk_read);", + " sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_r-1);", + " (void) unlink(dsk_nm);", + " bfs_dsk_read = -1;", + " }", + " if (bfs_dsk_read < 0)", + " { sprintf(dsk_nm, \"pan_bfs_%%d.tmp\", bfs_dsk_seqno_r++);", + " bfs_dsk_read = open(dsk_nm, RFLAGS);", + " if (bfs_dsk_read < 0)", + " { Uerror(\"could not open temp disk file\");", + " } }", + " if (read(bfs_dsk_read, (char *) &now, vsize) != vsize)", + " { Uerror(\"bad bfs disk file read\");", + " }", + " #ifndef NOVSZ", + " if (now._vsz != vsize)", + " { Uerror(\"disk read vsz mismatch\");", + " }", + " #endif", + " } else", + "#endif", + " { memcpy((uchar *) &now, (uchar *) t->onow->sv, vsize);", + " }", " memcpy((uchar *) Mask, (uchar *) t->omask->sv, vsize);", - + "#ifdef TRIX", + " re_populate();", + "#else", " if (now._nr_pr > 0)", - "#if VECTORSZ>32000", + " #if VECTORSZ>32000", " { memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(int));", - "#else", + " #else", " { memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(short));", - "#endif", + " #endif", " memcpy((char *)proc_skip, (char *)t->omask->ps, now._nr_pr * sizeof(uchar));", " }", " if (now._nr_qs > 0)", - "#if VECTORSZ>32000", + " #if VECTORSZ>32000", " { memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(int));", - "#else", + " #else", " { memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(short));", - "#endif", + " #endif", " memcpy((uchar *)q_skip, (uchar *)t->omask->qs, now._nr_qs * sizeof(uchar));", " }", - - " freesv(t->onow); /* omask not freed */", + "#endif", + "#ifdef BFS_DISK", + " if (t->onow->sv != (State *) 0)", + "#endif", + " { freesv(t->onow); /* omask not freed */", + " }", "#ifdef CHECK", - " printf(\"POP %%u (%%d)\\n\", t->frame, t->frame->o_tt);", + " printf(\"POP %%u (depth %%d, nr %%d)\\n\", t->frame, t->frame->o_tt, t->nr);", "#endif", " return t->frame;", "}", @@ -835,71 +1271,84 @@ "", " if (shortcut)", " {", - "#ifdef VERBOSE", + " #ifdef VERBOSE", " printf(\"claim: shortcut\\n\");", - "#endif", + " #endif", " goto store_it; /* no claim move */", " }", "", - " this = (((uchar *)&now)+proc_offset[0]); /* 0 = never claim */", + " this = pptr(0); /* 0 = never claim */", " trpt->o_pm = 0;", /* to interpret else in never claim */ "", " tt = (int) ((P0 *)this)->_p;", " ot = (uchar) ((P0 *)this)->_t;", "", - "#ifdef HAS_UNLESS", + " #ifdef HAS_UNLESS", " E_state = 0;", - "#endif", + " #endif", " for (t2 = trans[ot][tt]; t2; t2 = t2?t2->nxt:(Trans *)0)", " {", - "#ifdef HAS_UNLESS", - " if (E_state > 0", - " && E_state != t2->e_trans)", - " break;", - "#endif", + " #ifdef HAS_UNLESS", + " if (E_state > 0 && E_state != t2->e_trans)", + " { break;", + " }", + " #endif", " if (do_transit(t2, 0))", " {", - "#ifdef VERBOSE", + " #ifdef VERBOSE", " if (!reached[ot][t2->st])", " printf(\"depth: %%d -- claim move from %%d -> %%d\\n\",", " trpt->o_tt, ((P0 *)this)->_p, t2->st);", - "#endif", - "#ifdef HAS_UNLESS", + " #endif", + " #ifdef HAS_UNLESS", " E_state = t2->e_trans;", - "#endif", + " #endif", " if (t2->st > 0)", " { ((P0 *)this)->_p = t2->st;", " reached[ot][t2->st] = 1;", - "#ifndef NOCLAIM", - " check_claim(t2->st);", - "#endif", + " #ifndef NOCLAIM", + " if (stopstate[ot][t2->st])", + " { uerror(\"end state in claim reached\");", + " }", + " #endif", " }", " if (now._nr_pr == 0) /* claim terminated */", " uerror(\"end state in claim reached\");", "", - "#ifdef PEG", + " #ifdef PEG", " peg[t2->forw]++;", - "#endif", + " #endif", " trpt->o_pm |= 1;", - " if (t2->atom&2)", /* atomic in claim */ - " Uerror(\"atomic in claim not supported in BFS mode\");", + " if (t2->atom&2)", + " { Uerror(\"atomic in claim not supported in BFS\");", + " }", "store_it:", "", "#endif", /* VERI */ "", - "#ifdef BITSTATE", + "#if defined(BITSTATE)", " if (!bstore((char *)&now, vsize))", + "#elif defined(MA)", + " if (!gstore((char *)&now, vsize, 0))", "#else", - "#ifdef MA", - " if (!gstore((char *)&now, vsize, 0))", - "#else", " if (!hstore((char *)&now, vsize))", - "#endif", - "#endif", - " { nstates++;", + "#endif", + " { static long sdone = (long) 0; long ndone;", + " nstates++;", "#ifndef NOREDUCE", - " trpt->tau |= 64;", /* succ definitely outside stack */ - "#endif", + " trpt->tau |= 64;", /* bfs: succ definitely outside stack */ + "#endif", + " ndone = (unsigned long) (nstates/(freq));", + " if (ndone != sdone && mreached%%10 != 0)", + " { snapshot();", + " sdone = ndone;", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)", + " if (nstates > ((double)(1<<(ssize+1))))", + " { void resize_hashtable(void);", + " resize_hashtable();", + " }", + "#endif", + " }", "#if SYNC", " if (boq != -1)", " midrv++;", @@ -914,17 +1363,20 @@ " { truncs++;", "#if !defined(NOREDUCE) && defined(FULLSTACK) && defined(Q_PROVISO)", - "#if !defined(QLIST) && !defined(BITSTATE)", - " if (Lstate && Lstate->tagged) trpt->tau |= 64;", - "#else", + " #if !defined(BITSTATE)", + " if (Lstate && Lstate->tagged)", + " { trpt->tau |= 64;", + " }", + " #else", " if (trpt->tau&32)", " { BFS_Trail *tprov;", " for (tprov = bfs_trail; tprov; tprov = tprov->nxt)", - " if (!memcmp((uchar *)&now, (uchar *)tprov->onow->sv, vsize))", + " if (tprov->onow->sv != (State *) 0", + " && memcmp((uchar *)&now, (uchar *)tprov->onow->sv, vsize) == 0)", " { trpt->tau |= 64;", " break; /* state is in queue */", " } }", - "#endif", + " #endif", "#endif", " }", "#ifdef VERI", @@ -976,19 +1428,19 @@ " { revrv++;", " if (trpt->tau&8)", " {", - "#ifdef VERBOSE", + "#ifdef VERBOSE", " printf(\"Break atomic (pm:%%d,tau:%%d)\\n\",", " trpt->o_pm, trpt->tau);", - "#endif", + "#endif", " trpt->tau &= ~8;", " }", "#ifndef NOREDUCE", " else if (trpt->tau&32)", /* was a preselected move */ " {", - "#ifdef VERBOSE", + " #ifdef VERBOSE", " printf(\"Void preselection (pm:%%d,tau:%%d)\\n\",", " trpt->o_pm, trpt->tau);", - "#endif", + " #endif", " trpt->tau &= ~32;", " nps = 1; /* no preselection in repeat */", " }", @@ -998,13 +1450,7 @@ " if (trpt->o_tt > mreached)", " { mreached = trpt->o_tt;", " if (mreached%%10 == 0)", - " { printf(\"Depth= %%7d States= %%7g \", mreached, nstates);", - " printf(\"Transitions= %%7g \", nstates+truncs);", - "#ifdef MA", - " printf(\"Nodes= %%7d \", nr_states);", - "#endif", - " printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);", - " fflush(stdout);", + " { snapshot();", " } }", " depth = trpt->o_tt;", @@ -1023,16 +1469,15 @@ " printf(\"error: max search depth too small\\n\");", " }", " if (bounded)", - " uerror(\"depth limit reached\");", + " { uerror(\"depth limit reached\");", + " }", " continue;", " }", - -/* PO */ "#ifndef NOREDUCE", " if (boq == -1 && !(trpt->tau&8) && nps == 0)", " for (II = now._nr_pr-1; II >= BASE; II -= 1)", " {", - "Pickup: this = pptr(II);", + "Pickup: this = pptr(II);", " tt = (int) ((P0 *)this)->_p;", " ot = (uchar) ((P0 *)this)->_t;", " if (trans[ot][tt]->atom & 8)", /* safe */ @@ -1045,15 +1490,14 @@ " }", " From = To = II;", " trpt->tau |= 32; /* preselect marker */", - "#ifdef DEBUG", - " printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ", + " #ifdef DEBUG", + " printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ", " depth, II, trpt->tau);", - "#endif", + " #endif", " goto MainLoop;", " } }", " trpt->tau &= ~32;", /* not preselected */ - "#endif", -/* PO */ + "#endif", /* if !NOREDUCE */ "Repeat:", " if (trpt->tau&8) /* atomic */", " { From = To = (short ) trpt->pr;", @@ -1066,21 +1510,25 @@ " _n = _m = 0;", " for (II = From; II >= To; II -= 1)", " {", - " this = (((uchar *)&now)+proc_offset[II]);", + " this = pptr(II);", " tt = (int) ((P0 *)this)->_p;", " ot = (uchar) ((P0 *)this)->_t;", "#if SYNC", " /* no rendezvous with same proc */", - " if (boq != -1 && trpt->pr == II) continue;", + " if (boq != -1 && trpt->pr == II)", + " { continue;", + " }", "#endif", " ntrpt->pr = (uchar) II;", " ntrpt->st = tt; ", - " trpt->o_pm &= ~1; /* no move yet */", + " trpt->o_pm &= ~1; /* no move yet */", "#ifdef EVENT_TRACE", " trpt->o_event = now._event;", "#endif", "#ifdef HAS_PROVIDED", - " if (!provided(II, ot, tt, t)) continue;", + " if (!provided(II, ot, tt, t))", + " { continue;", + " }", "#endif", "#ifdef HAS_UNLESS", " E_state = 0;", @@ -1101,34 +1549,36 @@ "", " trpt->o_pm |= 1; /* we moved */", " (trpt+1)->o_m = _m; /* for unsend */", - "#ifdef PEG", + "#ifdef PEG", " peg[t->forw]++;", - "#endif", + "#endif", "#ifdef CHECK", - " printf(\"%%3d: proc %%d exec %%d, \",", + " printf(\"%%3ld: proc %%d exec %%d, \",", " depth, II, t->forw);", " printf(\"%%d to %%d, %%s %%s %%s\",", " tt, t->st, t->tp,", " (t->atom&2)?\"atomic\":\"\",", " (boq != -1)?\"rendez-vous\":\"\");", - "#ifdef HAS_UNLESS", + " #ifdef HAS_UNLESS", " if (t->e_trans)", " printf(\" (escapes to state %%d)\", t->st);", - "#endif", + " #endif", " printf(\" %%saccepting [tau=%%d]\\n\",", " (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);", "#endif", "#ifdef HAS_UNLESS", " E_state = t->e_trans;", - "#if SYNC>0", + " #if SYNC>0", " if (t->e_trans > 0 && (boq != -1 /* || oboq != -1 */))", - " { fprintf(efd, \"error:\tthe use of rendezvous stmnt in the escape clause\\n\");", + " { fprintf(efd, \"error:\ta rendezvous stmnt in the escape clause\\n\");", " fprintf(efd, \"\tof an unless stmnt is not compatible with -DBFS\\n\");", " pan_exit(1);", " }", - "#endif", - "#endif", - " if (t->st > 0) ((P0 *)this)->_p = t->st;", + " #endif", + "#endif", + " if (t->st > 0)", + " { ((P0 *)this)->_p = t->st;", + " }", "", " /* ptr to pred: */ ntrpt->ostate = (struct H_el *) otrpt;", " ntrpt->st = tt;", @@ -1136,17 +1586,19 @@ " ntrpt->tau = 8; /* record for next move */", " else", " ntrpt->tau = 0;", - "", " store_state(ntrpt, (boq != -1 || (t->atom&2)), oboq);", "#ifdef EVENT_TRACE", " now._event = trpt->o_event;", "#endif", - "", " /* undo move and continue */", " trpt++; /* this is where ovals and ipt are set */", " do_reverse(t, II, _m); /* restore now. */", " trpt--;", "#ifdef CHECK", + " #if NCORE>1", + " enter_critical(GLOBAL_LOCK); /* verbose mode */", + " printf(\"cpu%%d: \", core_id);", + " #endif", " printf(\"%%3d: proc %%d \", depth, II);", " printf(\"reverses %%d, %%d to %%d,\",", " t->forw, tt, t->st);", @@ -1154,43 +1606,48 @@ " t->tp, now._a_t, A_depth);", " printf(\"tau=%%d,%%d]\\n\",", " trpt->tau, (trpt-1)->tau);", + " #if NCORE>1", + " leave_critical(GLOBAL_LOCK);", + " #endif", "#endif", " reached[ot][t->st] = 1;", - " reached[ot][tt] = 1;", + " reached[ot][tt] = 1;", "", " ((P0 *)this)->_p = tt;", " _n |= _m;", " } }", -/* PO */ - "#ifndef NOREDUCE", + "#ifndef NOREDUCE", /* with PO */ " /* preselected - no succ definitely outside stack */", " if ((trpt->tau&32) && !(trpt->tau&64))", " { From = now._nr_pr-1; To = BASE;", - "#ifdef DEBUG", - " printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ", + " #ifdef DEBUG", + " cpu_printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ", " depth, II+1, (int) _n, trpt->tau);", - "#endif", + " #endif", " _n = 0; trpt->tau &= ~32;", " if (II >= BASE)", - " goto Pickup;", + " { goto Pickup;", + " }", " goto MainLoop;", " }", " trpt->tau &= ~(32|64);", - "#endif", -/* PO */ + "#endif", /* PO */ " if (_n != 0)", - " continue;", + " { continue;", + " }", "#ifdef DEBUG", - " printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",", + " printf(\"%%3ld: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",", " depth, II, trpt->tau, boq, now._nr_pr);", "#endif", " if (boq != -1)", " { failedrv++;", - " x = (Trail *) trpt->ostate; /* pre-rv state */", - " if (!x) continue; /* root state */", + " x = (Trail *) trpt->ostate; /* pre-rv state */", + " if (!x)", + " { continue; /* root state */", + " }", " if ((x->tau&8) || (x->tau&32)) /* break atomic or preselect at parent */", " { x->o_pm |= 8; /* mark failure */", - " this = (((uchar *)&now)+proc_offset[otrpt->pr]);", + " this = pptr(otrpt->pr);", "#ifdef VERBOSE", " printf(\"\\treset state of %%d from %%d to %%d\\n\",", " otrpt->pr, ((P0 *)this)->_p, otrpt->st);", @@ -1205,14 +1662,16 @@ "#endif", " }", "#ifdef VERBOSE", - " else printf(\"failed rv, tau at parent: %%d\\n\", x->tau);", + " else", + " { printf(\"failed rv, tau at parent: %%d\\n\", x->tau);", + " }", "#endif", " } else if (now._nr_pr > 0)", " {", " if ((trpt->tau&8)) /* atomic */", " { trpt->tau &= ~(1|8); /* 1=timeout, 8=atomic */", "#ifdef DEBUG", - " printf(\"%%3d: atomic step proc %%d blocks\\n\",", + " printf(\"%%3ld: atomic step proc %%d blocks\\n\",", " depth, II+1);", "#endif", " goto Repeat;", @@ -1227,7 +1686,8 @@ " }", "#ifndef VERI", " if (!noends && !a_cycles && !endstate())", - " uerror(\"invalid end state\");", + " { uerror(\"invalid end state\");", + " }", "#endif", " } }", "}", @@ -1258,12 +1718,12 @@ "", " if (fd < 0) return;", "#ifdef VERI", - " sprintf(snap, \"-2:%%d:-2\\n\", VERI);", - " write(fd, snap, strlen(snap));", + " sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);", + " (void) write(fd, snap, strlen(snap));", "#endif", "#ifdef MERGED", " sprintf(snap, \"-4:-4:-4\\n\");", - " write(fd, snap, strlen(snap));", + " (void) write(fd, snap, strlen(snap));", "#endif", " trcnt = 1;", " putter(trpt, fd);", @@ -1277,15 +1737,129 @@ " } }", " close(fd);", " if (errors >= upto && upto != 0)", - " {", - " wrapup();", + " { wrapup();", " }", "}", "#endif", /* BFS */ 0, }; -static char *Code2c[] = { +static char *Code2d[] = { + "clock_t start_time;", + "#if NCORE>1", + "clock_t crash_stamp;", + "#endif", + "#if !defined(WIN32) && !defined(WIN64)", + "struct tms start_tm;", + "#endif", + "", + "void", + "start_timer(void)", + "{", + "#if defined(WIN32) || defined(WIN64)", + " start_time = clock();", + "#else", + " start_time = times(&start_tm);", + "#endif", + "}", + "", + "void", + "stop_timer(void)", + "{ clock_t stop_time;", + " double delta_time;", + "#if !defined(WIN32) && !defined(WIN64)", + " struct tms stop_tm;", + " stop_time = times(&stop_tm);", + " delta_time = ((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK));", + "#else", + " stop_time = clock();", + " delta_time = ((double) (stop_time - start_time)) / ((double) CLOCKS_PER_SEC);", + "#endif", + " if (readtrail || delta_time < 0.00) return;", + "#if NCORE>1", + " if (core_id == 0 && nstates > (double) 0)", + " { printf(\"\\ncpu%%d: elapsed time %%.3g seconds (%%g states visited)\\n\",", + " core_id, delta_time, nstates);", + " if (delta_time > 0.01)", + " { printf(\"cpu%%d: rate %%g states/second\\n\", core_id, nstates/delta_time);", + " }", + " { void check_overkill(void);", + " check_overkill();", + " } }", + "#else", + " printf(\"\\npan: elapsed time %%.3g seconds\\n\", delta_time);", + " if (delta_time > 0.01)", + " { printf(\"pan: rate %%9.8g states/second\\n\", nstates/delta_time);", + " if (verbose)", + " { printf(\"pan: avg transition delay %%.5g usec\\n\",", + " delta_time/(nstates+truncs));", + " } }", + "#endif", + "}", + "", + "#if NCORE>1", + "#ifdef T_ALERT", + "double t_alerts[17];", + "", + "void", + "crash_report(void)", + "{ int i;", + " printf(\"crash alert intervals:\\n\");", + " for (i = 0; i < 17; i++)", + " { printf(\"%%d\\t%%g\\n\", i, t_alerts[i]);", + "} }", + "#endif", + "", + "void", + "crash_reset(void)", + "{ /* false alarm */", + " if (crash_stamp != (clock_t) 0)", + " {", + "#ifdef T_ALERT", + " double delta_time;", + " int i;", + "#if defined(WIN32) || defined(WIN64)", + " delta_time = ((double) (clock() - crash_stamp)) / ((double) CLOCKS_PER_SEC);", + "#else", + " delta_time = ((double) (times(&start_tm) - crash_stamp)) / ((double) sysconf(_SC_CLK_TCK));", + "#endif", + " for (i = 0; i < 16; i++)", + " { if (delta_time <= (i*30))", + " { t_alerts[i] = delta_time;", + " break;", + " } }", + " if (i == 16) t_alerts[i] = delta_time;", + "#endif", + " if (verbose)", + " printf(\"cpu%%d: crash alert off\\n\", core_id);", + " }", + " crash_stamp = (clock_t) 0;", + "}", + "", + "int", + "crash_test(double maxtime)", + "{ double delta_time;", + " if (crash_stamp == (clock_t) 0)", + " { /* start timing */", + "#if defined(WIN32) || defined(WIN64)", + " crash_stamp = clock();", + "#else", + " crash_stamp = times(&start_tm);", + "#endif", + " if (verbose)", + " { printf(\"cpu%%d: crash detection\\n\", core_id);", + " }", + " return 0;", + " }", + "#if defined(WIN32) || defined(WIN64)", + " delta_time = ((double) (clock() - crash_stamp)) / ((double) CLOCKS_PER_SEC);", + "#else", + " delta_time = ((double) (times(&start_tm) - crash_stamp)) / ((double) sysconf(_SC_CLK_TCK));", + "#endif", + " return (delta_time >= maxtime);", + "}", + "#endif", + "", "void", "do_the_search(void)", "{ int i;", @@ -1340,12 +1914,19 @@ " { now._a_t = 2; /* set the A-bit */", " now._cnt[0] = now._nr_pr + 1;", /* NEW: +1 */ "#ifdef VERBOSE", - " printf(\"%%3d: fairness Rule 1, cnt=%%d, _a_t=%%d\\n\",", + " printf(\"%%3ld: fairness Rule 1, cnt=%%d, _a_t=%%d\\n\",", " depth, now._cnt[now._a_t&1], now._a_t);", "#endif", " }", "#endif", + " c_stack_start = (char *) &i; /* meant to be read-only */", + + "#if defined(HAS_CODE) && defined (C_INIT)", + " C_INIT; /* initialization of data that must precede fork() */", + " c_init_done++;", + "#endif", + "#if defined(C_States) && (HAS_TRACK==1)", " /* capture initial state of tracked C objects */", " c_update((uchar *) &(now.c_state[0]));", @@ -1354,6 +1935,7 @@ "#ifdef HAS_CODE", " if (readtrail) getrail(); /* no return */", "#endif", + " start_timer();", "#ifdef BFS", " bfs();", "#else", @@ -1361,11 +1943,17 @@ " /* initial state of tracked & unmatched objects */", " c_stack((uchar *) &(svtack->c_stack[0]));", "#endif", - "#ifdef RANDOMIZE", - " srand(123);", - "#endif", + + "#if defined(P_RAND) || defined(T_RAND)", + " srand(s_rand);", + "#endif", + + "#if NCORE>1", + " mem_get();", + "#else", " new_state(); /* start 1st DFS */", "#endif", + "#endif", "}", "#ifdef INLINE_REV", @@ -1392,7 +1980,7 @@ "#ifdef EVENT_TRACE", " short oboq = boq;", " uchar ot = (uchar) ((P0 *)this)->_t;", - " if (ot == EVENT_TRACE) boq = -1;", + " if (II == -EVENT_TRACE) boq = -1;", "#define continue { boq = oboq; return 0; }", "#else", "#define continue return 0", @@ -1403,12 +1991,11 @@ "#include FORWARD_MOVES", "P999:", "#ifdef EVENT_TRACE", - " if (ot == EVENT_TRACE) boq = oboq;", + " if (II == -EVENT_TRACE) boq = oboq;", "#endif", " return _m;", "#undef continue", "}", - "#ifdef EVENT_TRACE", "void", "require(char tp, int qid)", @@ -1417,7 +2004,7 @@ "", " if (now._event != endevent)", " for (t = trans[EVENT_TRACE][now._event]; t; t = t->nxt)", - " { if (do_transit(t, EVENT_TRACE))", + " { if (do_transit(t, -EVENT_TRACE))", " { now._event = t->st;", " reached[EVENT_TRACE][t->st] = 1;", "#ifdef VERBOSE", @@ -1446,7 +2033,7 @@ " }", "#endif", " for (t = t->nxt; t; t = t->nxt)", - " { if (do_transit(t, EVENT_TRACE))", + " { if (do_transit(t, -EVENT_TRACE))", " Uerror(\"non-determinism in event-trace\");", " }", " return;", @@ -1470,7 +2057,6 @@ "#endif", "}", "#endif", - "int", "enabled(int iam, int pid)", "{ Trans *t; uchar *othis = this;", @@ -1497,20 +2083,56 @@ "}", "#endif", "void", + "snap_time(void)", + "{ clock_t stop_time;", + " double delta_time;", + "#if !defined(WIN32) && !defined(WIN64)", + " struct tms stop_tm;", + " stop_time = times(&stop_tm);", + " delta_time = ((double) (stop_time - start_time)) / ((double) sysconf(_SC_CLK_TCK));", + "#else", + " stop_time = clock();", + " delta_time = ((double) (stop_time - start_time)) / ((double) CLOCKS_PER_SEC);", + "#endif", + " if (delta_time > 0.01)", + " { printf(\"t= %%8.3g \", delta_time);", + " printf(\"R= %%7.0g\", nstates/delta_time);", + " }", + " printf(\"\\n\");", + " if (quota > 0.1 && delta_time > quota)", + " { printf(\"Time limit of %%6.3g minutes exceeded\\n\", quota/60.0);", + "#if NCORE>1", + " fflush(stdout);", + " leave_critical(GLOBAL_LOCK);", + " sudden_stop(\"time-limit\");", + " exit(1);", + "#endif", + " wrapup();", + " }", + "}", + "void", "snapshot(void)", - "{ static long sdone = (long) 0;", - " long ndone = (unsigned long) nstates/1000000;", - " if (ndone == sdone) return;", - " sdone = ndone;", - " printf(\"Depth= %%7d States= %%7g \", mreached, nstates);", - " printf(\"Transitions= %%7g \", nstates+truncs);", + "{", + "#if NCORE>1", + " enter_critical(GLOBAL_LOCK); /* snapshot */", + " printf(\"cpu%%d: \", core_id);", + "#endif", + " printf(\"Depth= %%7ld States= %%8.3g \",", + "#if NCORE>1", + " (long) (nr_handoffs * z_handoff) +", + "#endif", + " mreached, nstates);", + " printf(\"Transitions= %%8.3g \", nstates+truncs);", "#ifdef MA", " printf(\"Nodes= %%7d \", nr_states);", "#endif", - " printf(\"Memory= %%-6.3f\\n\", memcnt/1000000.);", + " printf(\"Memory= %%9.3f\\t\", memcnt/1048576.);", + " snap_time();", " fflush(stdout);", + "#if NCORE>1", + " leave_critical(GLOBAL_LOCK);", + "#endif", "}", - "#ifdef SC", "void", "stack2disk(void)", @@ -1552,46 +2174,144 @@ "#endif", "uchar *", - "Pptr(int x)", /* as a fct, to avoid a problem with the p9 compiler */ - "{ if (x < 0 || x >= MAXPROC || !proc_offset[x])", /* does not exist */ + "Pptr(int x)", + "{ if (x < 0 || x >= MAXPROC", /* does not exist */ + "#ifdef TRIX", + " || !processes[x])", + "#else", + " || !proc_offset[x])", + "#endif", " return noptr;", " else", " return (uchar *) pptr(x);", + "}\n", + "uchar *", + "Qptr(int x)", + "{ if (x < 0 || x >= MAXQ", + "#ifdef TRIX", + " || !channels[x])", + "#else", + " || !q_offset[x])", + "#endif", + " return noqptr;", + " else", + " return (uchar *) qptr(x);", + "}\n", + + "int qs_empty(void);", + "#if !defined(BFS) && (!defined(BITSTATE) || !defined(MA))", + "#ifdef NSUCC", + "int N_succ[512];", + "void", + "tally_succ(int cnt)", + "{ if (cnt < 512) N_succ[cnt]++;", + " else printf(\"tally_succ: cnt %%d exceeds range\\n\", cnt);", "}", - "int qs_empty(void);", - + "", + "void", + "dump_succ(void)", + "{ int i; double sum = 0.0;", + " double w_avg = 0.0;", + " printf(\"Successor counts:\\n\");", + " for (i = 0; i < 512; i++)", + " { sum += (double) N_succ[i];", + " }", + " for (i = 0; i < 512; i++)", + " { if (N_succ[i] > 0)", + " { printf(\"%%3d\t%%10d\t(%%.4g %%%% of total)\\n\",", + " i, N_succ[i], (100.0 * (double) N_succ[i])/sum);", + " w_avg += (double) i * (double) N_succ[i];", + " } }", + " if (sum > N_succ[0])", + " printf(\"mean %%.4g (without 0: %%.4g)\\n\", w_avg / sum, w_avg / (sum - (double) N_succ[0]));", + "}", + "#endif", + "", + "#if NCLAIMS>1", + "void", + "select_claim(int n)", + "{ int m, i;", + " if (n < 0 || n >= NCLAIMS)", + " { uerror(\"non-existing claim\");", + " } else", + " { m = ((Pclaim *)pptr(0))->_n;", + " if (verbose)", + " { printf(\"%%d: Claim %%s (%%d), from state %%d\\n\",", + " (int) depth, procname[spin_c_typ[n]],", + " n, ((Pclaim *)pptr(0))->c_cur[n]);", + " }", + " ((Pclaim *)pptr(0))->c_cur[m] = ((Pclaim *)pptr(0))->_p;", + " ((Pclaim *)pptr(0))->_t = spin_c_typ[n];", + " ((Pclaim *)pptr(0))->_p = ((Pclaim *)pptr(0))->c_cur[n];", + " ((Pclaim *)pptr(0))->_n = n;", + " for (i = 0; src_all[i].src != (short *) 0; i++)", + " { if (src_all[i].tp == spin_c_typ[n])", + " { src_claim = src_all[i].src;", + " break;", + " } }", + " if (src_all[i].src == (short *) 0)", + " { uerror(\"cannot happen: src_ln ref\");", + " } }", + "}", + "#else", + "void", + "select_claim(int n)", + "{ if (n != 0) uerror(\"non-existing claim\");", + "}", + "#endif", + "", + "#ifdef REVERSE", + " #define FROM_P (BASE)", + " #define UPTO_P (now._nr_pr-1)", + " #define MORE_P (II <= To)", /* p.o. only */ + " #define INI_P (From-1)", /* fairness only */ + " #define ALL_P (II = From; II <= To; II++)", + "#else", + " #define FROM_P (now._nr_pr-1)", + " #define UPTO_P (BASE)", + " #define MORE_P (II >= BASE)", + " #define INI_P (From+1)", + " #define ALL_P (II = From; II >= To; II--)", + "#endif", "/*", " * new_state() is the main DFS search routine in the verifier", " * it has a lot of code ifdef-ed together to support", " * different search modes, which makes it quite unreadable.", - " * if you are studying the code, first use the C preprocessor", + " * if you are studying the code, use the C preprocessor", " * to generate a specific version from the pan.c source,", " * e.g. by saying:", " * gcc -E -DNOREDUCE -DBITSTATE pan.c > ppan.c", - " * and then study the resulting file, rather than this one", + " * and then study the resulting file, instead of this version", " */", - "#if !defined(BFS) && (!defined(BITSTATE) || !defined(MA))", + "", "void", "new_state(void)", "{ Trans *t;", " uchar _n, _m, ot;", - "#ifdef RANDOMIZE", + "#ifdef T_RAND", " short ooi, eoi;", "#endif", + "#ifdef M_LOSS", " uchar delta_m = 0;", "#endif", " short II, JJ = 0, kk;", " int tt;", - " short From = now._nr_pr-1, To = BASE;", + " short From = FROM_P, To = UPTO_P;", + "#ifdef BCS", + " trpt->sched_limit = 0; /* at depth=0 only */", + "#endif", "Down:", "#ifdef CHECK", - " printf(\"%%d: Down - %%s\",", - " depth, (trpt->tau&4)?\"claim\":\"program\");", - " printf(\" %%saccepting [pids %%d-%%d]\\n\",", + " cpu_printf(\"%%d: Down - %%s %%saccepting [pids %%d-%%d]\\n\",", + " depth, (trpt->tau&4)?\"claim\":\"program\",", " (trpt->o_pm&2)?\"\":\"non-\", From, To);", "#endif", + "#ifdef P_RAND", + " trpt->p_skip = -1;", + "#endif", + "#ifdef SC", " if (depth > hiwater)", " { stack2disk();", @@ -1608,23 +2328,54 @@ "#if defined(FULLSTACK) && defined(MA)", " trpt->proviso = 0;", "#endif", + "#ifdef NSUCC", + " trpt->n_succ = 0;", + "#endif", + "#if NCORE>1", + " if (mem_hand_off())", + " {", + "#if SYNC", + " (trpt+1)->o_n = 1; /* not a deadlock: as below */", + "#endif", + "#ifndef LOOPSTATE", + " (trpt-1)->tau |= 16; /* worstcase guess: as below */", + "#endif", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", + " }", + "#endif", + " goto Up;", + " }", + "#endif", + " if (depth >= maxdepth)", - " { truncs++;", - "#if SYNC", - " (trpt+1)->o_n = 1; /* not a deadlock */", - "#endif", - " if (!warned)", + " { if (!warned)", " { warned = 1;", " printf(\"error: max search depth too small\\n\");", " }", - " if (bounded) uerror(\"depth limit reached\");", - " (trpt-1)->tau |= 16; /* worstcase guess */", + " if (bounded)", + " { uerror(\"depth limit reached\");", + " }", + " truncs++;", + "#if SYNC", + " (trpt+1)->o_n = 1; /* not a deadlock */", + "#endif", + "#ifndef LOOPSTATE", + " (trpt-1)->tau |= 16; /* worstcase guess */", + "#endif", + + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", + " }", + "#endif", " goto Up;", " }", "AllOver:", - "#if defined(FULLSTACK) && !defined(MA)", + "#if (defined(FULLSTACK) && !defined(MA)) || NCORE>1", " /* if atomic or rv move, carry forward previous state */", - " trpt->ostate = (trpt-1)->ostate;", /* was: = (struct H_el *) 0;*/ + " trpt->ostate = (trpt-1)->ostate;", "#endif", "#ifdef VERI", " if ((trpt->tau&4) || ((trpt-1)->tau&128))", @@ -1649,6 +2400,11 @@ "#else", " uerror(\"acceptance cycle\");", "#endif", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", + " }", + "#endif", " goto Up;", " }", "#ifdef CHECK", @@ -1658,20 +2414,61 @@ "#endif", " if (!(trpt->tau&8)) /* if no atomic move */", " {", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " uchar was_last = now._last;", + " now._last = 0; /* value not stored */", + "#endif", "#ifdef BITSTATE", "#ifdef CNTRSTACK", /* -> bitstate, reduced, safety */ + " #if defined(BCS) && defined(STORE_CTX)", + " { int xj;", + " for (xj = trpt->sched_limit; xj <= sched_max; xj++)", + " { now._ctx = xj;", + " II = bstore((char *)&now, vsize);", + " trpt->j6 = j1_spin; trpt->j7 = j2;", + " JJ = LL[j1_spin] && LL[j2];", + " if (II != 0) { break; }", + " }", + " now._ctx = 0; /* just in case */", + " }", + " #else", " II = bstore((char *)&now, vsize);", - " trpt->j6 = j1; trpt->j7 = j2;", - " JJ = LL[j1] && LL[j2];", + " trpt->j6 = j1_spin; trpt->j7 = j2;", + " JJ = LL[j1_spin] && LL[j2];", + " #endif", "#else", - "#ifdef FULLSTACK", - " JJ = onstack_now();", /* sets j1 */ - "#else", - "#ifndef NOREDUCE", - " JJ = II; /* worstcase guess for p.o. */", - "#endif", - "#endif", + " #ifdef FULLSTACK", /* bstore after onstack_now, to preserve j1-j4 */ + " #if defined(BCS) && defined(STORE_CTX)", + " { int xj;", + " now._ctx = 0;", + " JJ = onstack_now();", /* mangles j1 */ + " for (xj = trpt->sched_limit; xj <= sched_max; xj++)", + " { now._ctx = xj;", + " II = bstore((char *)&now, vsize);", /* sets j1-j4 */ + " if (II != 0) { break; }", + " }", + " now._ctx = 0;", + " }", + " #else", + " JJ = onstack_now();", /* mangles j1 */ " II = bstore((char *)&now, vsize);", /* sets j1-j4 */ + " #endif", + " #else", + " #if defined(BCS) && defined(STORE_CTX)", + " { int xj;", + " for (xj = trpt->sched_limit; xj <= sched_max; xj++)", + " { now._ctx = xj;", + " II = bstore((char *)&now, vsize);", /* sets j1-j4 */ + " JJ = II; /* worstcase guess for p.o. - order corrected in 5.2.1 */", + " if (II != 0) { break; }", + " }", + " now._ctx = 0;", + " }", + " #else", + " II = bstore((char *)&now, vsize);", /* sets j1-j4 */ + " JJ = II; /* worstcase guess for p.o. - order corrected in 5.2.1 */", + " #endif", + " #endif", "#endif", "#else", "#ifdef MA", @@ -1683,41 +2480,55 @@ "#endif", "#else", " II = hstore((char *)&now, vsize);", + " /* @hash j1_spin II */", "#ifdef FULLSTACK", " JJ = (II == 2)?1:0;", "#endif", "#endif", "#endif", " kk = (II == 1 || II == 2);", + /* actually, BCS implies HAS_LAST */ + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " now._last = was_last; /* restore value */", + "#endif", + /* II==0 new state */ /* II==1 old state */ /* II==2 on current dfs stack */ /* II==3 on 1st dfs stack */ "#ifndef SAFETY", - " if (!fairness && a_cycles)", + "#if NCORE==1 || defined (SEP_STATE)", /* or else we don't know which stack its on */ " if (II == 2 && ((trpt->o_pm&2) || ((trpt-1)->o_pm&2)))", - " { II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */", - "#ifdef VERBOSE", + " #ifndef NOFAIR", + "#if 0", + " if (!fairness || ((now._a_t&1) && now._cnt[1] == 1)) /* 5.1.4 */", + "#else", + " if (a_cycles && !fairness) /* 5.1.6 -- example by Hirofumi Watanabe */", + "#endif", + " #endif", + " {", + " II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */", + "#ifdef VERBOSE", " printf(\"state match on dfs stack\\n\");", - "#endif", + "#endif", " goto same_case;", " }", - + "#endif", "#if defined(FULLSTACK) && defined(BITSTATE)", " if (!JJ && (now._a_t&1) && depth > A_depth)", - " { int oj1 = j1;", + " { int oj1 = j1_spin;", " uchar o_a_t = now._a_t;", " now._a_t &= ~(1|16|32);", /* 1st stack */ - " if (onstack_now())", /* changes j1 */ + " if (onstack_now())", /* changes j1_spin */ " { II = 3;", "#ifdef VERBOSE", " printf(\"state match on 1st dfs stack\\n\");", "#endif", " }", " now._a_t = o_a_t;", /* restore */ - " j1 = oj1;", + " j1_spin = oj1;", " }", "#endif", " if (II == 3 && a_cycles && (now._a_t&1))", @@ -1741,37 +2552,103 @@ "#else", " uerror(\"acceptance cycle\");", "#endif", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", + " }", + "#endif", " goto Up;", " }", " }", "#endif", "#ifndef NOREDUCE", - "#ifndef SAFETY", + " #ifndef SAFETY", + " #if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)", + " if (II != 0 && (!Lstate || Lstate->cpu_id < core_id))", + " { (trpt-1)->tau |= 16;", /* treat as a stack state */ + " }", + " #endif", " if ((II && JJ) || (II == 3))", " { /* marker for liveness proviso */", - " (trpt-1)->tau |= 16;", + " #ifndef LOOPSTATE", + " (trpt-1)->tau |= 16;", /* truncated on stack */ + " #endif", " truncs2++;", " }", "#else", + " #if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)", + " if (!(II != 0 && (!Lstate || Lstate->cpu_id < core_id)))", + " { /* treat as stack state */", + " (trpt-1)->tau |= 16;", + " } else", + " { /* treat as non-stack state */", + " (trpt-1)->tau |= 64;", + " }", + " #endif", " if (!II || !JJ)", " { /* successor outside stack */", " (trpt-1)->tau |= 64;", " }", - "#endif", + " #endif", + "#endif", + "#if defined(BCS) && (defined(NOREDUCE) || !defined(SAFETY))", + /* needed for BCS - cover cases where it would not otherwise be set */ + " if (!II || !JJ)", + " { (trpt-1)->tau |= 64;", + " }", "#endif", " if (II)", " { truncs++;", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", + " if (depth == 0)", + " { return;", + " } }", + "#endif", " goto Up;", " }", " if (!kk)", - " { nstates++;", - " if ((unsigned long) nstates%%1000000 == 0)", - " snapshot();", + " { static long sdone = (long) 0; long ndone;", + " nstates++;", + "#if defined(ZAPH) && defined(BITSTATE)", + " zstates += (double) hfns;", + "#endif", + " ndone = (unsigned long) (nstates/(freq));", + " if (ndone != sdone)", + " { snapshot();", + " sdone = ndone;", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)", + " if (nstates > ((double)(ONE_L<<(ssize+1))))", + " { void resize_hashtable(void);", + " resize_hashtable();", + " }", + "#endif", + "#if defined(ZAPH) && defined(BITSTATE)", + " if (zstates > ((double)(ONE_L<<(ssize-2))))", + " { /* more than half the bits set */", + " void zap_hashtable(void);", + " zap_hashtable();", + " zstates = 0;", + " }", + "#endif", + " }", "#ifdef SVDUMP", " if (vprefix > 0)", + " #ifdef SHO", /* Store Hash Only */ + " /* always use the same hashfunction, for consistency across runs */", + " if (HASH_NR != 0)", + " { int oh = HASH_NR;", + " HASH_NR = 0;", + " d_hash((char *) &now, vsize); /* set K1 */", + " HASH_NR = oh;", + " }", + " if (write(svfd, (uchar *) &K1, sizeof(unsigned long)) != sizeof(unsigned long))", + " #else", " if (write(svfd, (uchar *) &now, vprefix) != vprefix)", - " { fprintf(efd, \"writing %%s.svd failed\\n\", Source);", + " #endif", + " { fprintf(efd, \"writing %%s.svd failed\\n\", PanSource);", " wrapup();", " }", "#endif", @@ -1782,6 +2659,7 @@ " }", "#endif", " }", + "#if defined(FULLSTACK) || defined(CNTRSTACK)", " onstack_put();", "#ifdef DEBUG2", @@ -1793,10 +2671,13 @@ " printf(\"%%d: putting\\n\", depth);", "#endif", "#endif", + "#else", + " #if NCORE>1", + " trpt->ostate = Lstate;", + " #endif", "#endif", " } }", - " if (depth > mreached)", " mreached = depth;", "#ifdef VERI", @@ -1810,11 +2691,13 @@ "#ifdef VERI", " if (now._nr_pr == 0) /* claim terminated */", " uerror(\"end state in claim reached\");", - " check_claim(((P0 *)pptr(0))->_p);", + "", + " if (stopstate[((Pclaim *)pptr(0))->_t][((Pclaim *)pptr(0))->_p])", + " { uerror(\"end state in claim reached\");", + " }", "Stutter:", " if (trpt->tau&4) /* must make a claimmove */", " {", - "#ifndef NOFAIR", " if ((now._a_t&2) /* A-bit set */", " && now._cnt[now._a_t&1] == 1)", @@ -1827,7 +2710,6 @@ "#endif", " }", "#endif", - " II = 0; /* never */", " goto Veri0;", " }", @@ -1835,14 +2717,23 @@ "#ifndef NOREDUCE", " /* Look for a process with only safe transitions */", " /* (special rules apply in the 2nd dfs) */", -"#ifdef SAFETY", - " if (boq == -1 && From != To)", -"#else", - "/* implied: #ifdef FULLSTACK */", " if (boq == -1 && From != To", + "", + "#ifdef SAFETY", + " #if NCORE>1", + " && (depth < z_handoff)", /* not for border states */ + " #endif", + " )", + "#else", + " #if NCORE>1", + " && ((a_cycles) || (!a_cycles && depth < z_handoff))", + " #endif", + " #ifdef BCS", + " && (sched_max > 0 || depth > BASE)", /* no po in initial state if -L0 */ + " #endif", " && (!(now._a_t&1)", " || (a_cycles &&", - "#ifndef BITSTATE", + " #ifndef BITSTATE", "#ifdef MA", "#ifdef VERI", " !((trpt-1)->proviso))", @@ -1852,63 +2743,56 @@ "#else", "#ifdef VERI", " (trpt-1)->ostate &&", - " !(((char *)&((trpt-1)->ostate->state))[0] & 128))", + " !(((char *)&((trpt-1)->ostate->state))[0] & 128))", /* proviso bit in _a_t */ "#else", " !(((char *)&(trpt->ostate->state))[0] & 128))", "#endif", "#endif", - "#else", + " #else", "#ifdef VERI", " (trpt-1)->ostate &&", " (trpt-1)->ostate->proviso == 0)", "#else", " trpt->ostate->proviso == 0)", "#endif", - "#endif", + " #endif", " ))", - "/* #endif */", -"#endif", - " for (II = From; II >= To; II -= 1)", - " {", - "Resume: /* pick up here if preselect fails */", - " this = pptr(II);", - " tt = (int) ((P0 *)this)->_p;", - " ot = (uchar) ((P0 *)this)->_t;", - " if (trans[ot][tt]->atom & 8)", - " { t = trans[ot][tt];", - " if (t->qu[0] != 0)", - " { Ccheck++;", - " if (!q_cond(II, t))", - " continue;", - " Cholds++;", - " }", - " From = To = II;", + "#endif", /* SAFETY */ + " /* attempt Partial Order Reduction as preselect moves */", + "#ifdef BCS", + " if (trpt->sched_limit < sched_max)", /* po only if we can switch */ + "#endif", + " { for ALL_P", + " {", + "Resume: /* pick up here if preselect fails */", + " this = pptr(II);", + " tt = (int) ((P0 *)this)->_p;", + " ot = (uchar) ((P0 *)this)->_t;", + " if (trans[ot][tt]->atom & 8)", + " { t = trans[ot][tt];", + " if (t->qu[0] != 0)", + " { Ccheck++;", + " if (!q_cond(II, t))", + " continue;", + " Cholds++;", + " }", + "SelectIt: From = To = II; /* preselect process */", "#ifdef NIBIS", - " t->om = 0;", - "#endif", - " trpt->tau |= 32; /* preselect marker */", - "#ifdef DEBUG", - "#ifdef NIBIS", - " printf(\"%%3d: proc %%d Pre\", depth, II);", - " printf(\"Selected (om=%%d, tau=%%d)\\n\", ", - " t->om, trpt->tau);", - "#else", - " printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ", - " depth, II, trpt->tau);", - "#endif", - "#endif", - " goto Again;", - " }", - " }", + " t->om = 0;", + "#endif", + " trpt->tau |= 32; /* preselect marker */", + "#ifdef DEBUG", + " printf(\"%%3ld: proc %%d PreSelected (tau=%%d)\\n\", ", + " depth, II, trpt->tau);", + "#endif", + " goto Again;", + " } } }", " trpt->tau &= ~32;", "#endif", "#if !defined(NOREDUCE) || (defined(ETIM) && !defined(VERI))", "Again:", "#endif", - " /* The Main Expansion Loop over Processes */", - - " trpt->o_pm &= ~(8|16|32|64); /* fairness-marks */", - + " trpt->o_pm &= ~(8|16|32|64); /* clear fairness-marks */", "#ifndef NOFAIR", " if (fairness && boq == -1", "#ifdef VERI", @@ -1917,36 +2801,133 @@ " && !(trpt->tau&8))", " { /* A_bit = 1; Cnt = N in acc states with A_bit 0 */", " if (!(now._a_t&2))", /* A-bit not set */ - " {", - " if (a_cycles && (trpt->o_pm&2))", + " { if (a_cycles && (trpt->o_pm&2))", " { /* Accepting state */", " now._a_t |= 2;", - " now._cnt[now._a_t&1] = now._nr_pr + 1;", /* NEW +1 */ + " now._cnt[now._a_t&1] = now._nr_pr + 1;", " trpt->o_pm |= 8;", "#ifdef DEBUG", - " printf(\"%%3d: fairness Rule 1: cnt=%%d, _a_t=%%d\\n\",", + " printf(\"%%3ld: fairness Rule 1: cnt=%%d, _a_t=%%d\\n\",", " depth, now._cnt[now._a_t&1], now._a_t);", "#endif", " }", " } else", /* A-bit set */ " { /* A_bit = 0 when Cnt 0 */", - " if (now._cnt[now._a_t&1] == 1)", /* NEW: 1 iso 0 */ - " { now._a_t &= ~2;", /* reset a-bit */ - " now._cnt[now._a_t&1] = 0;", /* NEW: reset cnt */ + " if (now._cnt[now._a_t&1] == 1)", + " { now._a_t &= ~2;", /* reset a-bit */ + " now._cnt[now._a_t&1] = 0;", " trpt->o_pm |= 16;", "#ifdef DEBUG", - " printf(\"%%3d: fairness Rule 3: _a_t = %%d\\n\",", + " printf(\"%%3ld: fairness Rule 3: _a_t = %%d\\n\",", " depth, now._a_t);", "#endif", " } } }", "#endif", - " for (II = From; II >= To; II -= 1)", + "#ifdef BCS", /* bounded context switching */ + " trpt->bcs = trpt->b_pno = 0; /* initial */", + " if (From != To /* not a PO or atomic move */", + " && depth > BASE) /* there is a prior move */", + " { trpt->b_pno = now._last + BASE;", + " trpt->bcs = B_PHASE1;", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS phase 1 proc %%d limit %%d\\n\",", + " depth, trpt->b_pno, trpt->sched_limit);", + " #endif", + " /* allow only process b_pno to move in this phase */", + " }", + "c_switch: /* jumps here with bcs == B_PHASE2 with or wo B_FORCED added */", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS c_switch phase=%%d pno=%%d [forced %%d]\\n\",", + " depth, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);", + " #endif", + "#endif", + + "#ifdef P_RAND", + " #ifdef REVERSE", + " trpt->p_left = 1 + (To - From);", + " #else", + " trpt->p_left = 1 + (From - To);", + " #endif", + " if (trpt->p_left > 1)", + " { trpt->p_skip = rand() %% (trpt->p_left);", + " } else", + " { trpt->p_skip = -1;", + " }", + "r_switch:", + " #ifdef VERBOSE", + " printf(\"%%3ld: P_RAND r_switch p_skip=%%d p_left=%%d\\n\",", + " depth, trpt->p_skip, trpt->p_left);", + " #endif", + "#endif", + + " /* Main Expansion Loop over Processes */", + " for ALL_P", " {", + "#ifdef P_RAND", + " if (trpt->p_skip >= 0)", + " { trpt->p_skip--; /* skip random nr of procs */", + " #ifdef VERBOSE", + " printf(\"%%3ld: P_RAND skipping %%d [new p_skip=%%d p_left=%%d]\\n\",", + " depth, II, trpt->p_skip, trpt->p_left);", + " #endif", + " continue;", + " }", + " if (trpt->p_left == 0)", + " {", + " #ifdef VERBOSE", + " printf(\"%%3ld: P_RAND done at %%d\\n\", depth, II);", + " #endif", + " break; /* done */", + " }", + " #ifdef VERBOSE", + " printf(\"%%3ld: P_RAND explore %%d [p_left=%%d]\\n\",", + " depth, II, trpt->p_left);", + " #endif", + " trpt->p_left--;", + "#endif", + "#if SYNC", " /* no rendezvous with same proc */", " if (boq != -1 && trpt->pr == II) continue;", "#endif", + + "#ifdef BCS", /* never claim with II==0 cannot get here */ + " if ((trpt->bcs & B_PHASE1)", + " && trpt->b_pno != II)", + " {", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS NotPre II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",", + " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);", + " #endif", + " continue;", /* avoid context switch */ + " }", + " #ifdef VERBOSE", + " else if ((trpt->bcs & B_PHASE1) && trpt->b_pno == II)", + " printf(\"%%3ld: BCS IsPre II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",", + " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);", + " #endif", + + " if (trpt->bcs & B_PHASE2) /* 2nd phase */", + " { if (trpt->b_pno == II) /* was already done in phase 1 */", + " {", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS NoRepeat II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",", + " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);", + " #endif", + " continue;", + " }", + " if (!(trpt->bcs & B_FORCED) /* unless forced */", + " && trpt->sched_limit >= sched_max)", + " {", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS Bound II=%%d bcs=%%d pno=%%d [forced %%d]\\n\",", + " depth, II, trpt->bcs, trpt->b_pno, (trpt->bcs&B_FORCED)?1:0);", + " #endif", + " continue; /* enforce bound */", + " } }", + "#endif", + "#ifdef VERI", "Veri0:", "#endif", @@ -1990,7 +2971,7 @@ " now._cnt[now._a_t&1] = 1;", "#endif", "#ifdef DEBUG", - " printf(\"%%3d: proc %%d fairness \", depth, II);", + " printf(\"%%3ld: proc %%d fairness \", depth, II);", " printf(\"Rule 2: --cnt to %%d (%%d)\\n\",", " now._cnt[now._a_t&1], now._a_t);", "#endif", @@ -2007,27 +2988,31 @@ " (trpt+1)->pr = (uchar) II;", /* for uerror */ " (trpt+1)->st = tt;", - "#ifdef RANDOMIZE", + "#ifdef T_RAND", " for (ooi = eoi = 0, t = trans[ot][tt]; t; t = t->nxt, ooi++)", - " if (strcmp(t->tp, \"else\") == 0)", - " eoi++;", - "", - " if (eoi)", + " { if (strcmp(t->tp, \"else\") == 0", + "#ifdef HAS_UNLESS", + " || t->e_trans != 0", + "#endif", + " )", + " { eoi++;", /* no break, must count ooi */ + " } }", + " if (eoi > 0)", " { t = trans[ot][tt];", - "#ifdef VERBOSE", - " printf(\"randomizer: suppressed, saw else\\n\");", - "#endif", + " #ifdef VERBOSE", + " printf(\"randomizer: suppressed, saw else or escape\\n\");", + " #endif", " } else", " { eoi = rand()%%ooi;", - "#ifdef VERBOSE", + " #ifdef VERBOSE", " printf(\"randomizer: skip %%d in %%d\\n\", eoi, ooi);", - "#endif", + " #endif", " for (t = trans[ot][tt]; t; t = t->nxt)", " if (eoi-- <= 0) break;", " }", - "DOMORE:", + "domore:", " for ( ; t && ooi > 0; t = t->nxt, ooi--)", - "#else", + "#else", /* ie dont randomize */ " for (t = trans[ot][tt]; t; t = t->nxt)", "#endif", " {", @@ -2045,6 +3030,9 @@ " break;", " }", "#endif", + " #if defined(TRIX) && !defined(TRIX_ORIG) && !defined(BFS)", + " (trpt+1)->p_bup = now._ids_[II];", + " #endif", " (trpt+1)->o_t = t;", /* for uerror */ "#ifdef INLINE", "#include FORWARD_MOVES", @@ -2052,42 +3040,71 @@ "#else", " if (!(_m = do_transit(t, II))) continue;", "#endif", + "#ifdef BCS", + " if (depth > BASE", /* has prior move */ + " && II >= BASE", /* not claim */ + " && From != To", /* not atomic or po */ + " #ifndef BCS_NOFIX", + " /* added 5.2.5: prior move was not po */", + " && !((trpt-(BASE+1))->tau & 32)", + " #endif", + " && boq == -1", /* not rv */ + " && (trpt->bcs & B_PHASE2)", + " && trpt->b_pno != II /* context switch */", /* redundant */ + " && !(trpt->bcs & B_FORCED)) /* unless forced */", + " { (trpt+1)->sched_limit = 1 + trpt->sched_limit;", + " #ifdef VERBOSE", + " printf(\"%%3ld: up sched count to %%d\\n\", depth, (trpt+1)->sched_limit);", + " #endif", + " } else", + " { (trpt+1)->sched_limit = trpt->sched_limit;", + " #ifdef VERBOSE", + " printf(\"%%3ld: keep sched count at %%d\\n\", depth, (trpt+1)->sched_limit);", + " #endif", + " }", + "#endif", " if (boq == -1)", -"#ifdef CTL", + "#ifdef CTL", " /* for branching-time, can accept reduction only if */", " /* the persistent set contains just 1 transition */", " { if ((trpt->tau&32) && (trpt->o_pm&1))", - " trpt->tau |= 16;", + " trpt->tau |= 16;", /* CTL */ " trpt->o_pm |= 1; /* we moved */", " }", -"#else", + "#else", " trpt->o_pm |= 1; /* we moved */", -"#endif", + "#endif", + + "#ifdef LOOPSTATE", + " if (loopstate[ot][tt])", + " {", + "#ifdef VERBOSE", + " printf(\"exiting from loopstate:\\n\");", + "#endif", + " trpt->tau |= 16;", /* exiting loopstate */ + " cnt_loops++;", + " }", + "#endif", + "#ifdef PEG", " peg[t->forw]++;", "#endif", - "#if defined(VERBOSE) || defined(CHECK)", "#if defined(SVDUMP)", - " printf(\"%%3d: proc %%d exec %%d \\n\", ", - " depth, II, t->t_id);", + " cpu_printf(\"%%3ld: proc %%d exec %%d \\n\", depth, II, t->t_id);", "#else", - " printf(\"%%3d: proc %%d exec %%d, \", ", - " depth, II, t->forw);", - " printf(\"%%d to %%d, %%s %%s %%s\", ", - " tt, t->st, t->tp,", + " cpu_printf(\"%%3ld: proc %%d exec %%d, %%d to %%d, %%s %%s %%s %%saccepting [tau=%%d]\\n\", ", + " depth, II, t->forw, tt, t->st, t->tp,", " (t->atom&2)?\"atomic\":\"\",", - " (boq != -1)?\"rendez-vous\":\"\");", - "#ifdef HAS_UNLESS", + " (boq != -1)?\"rendez-vous\":\"\",", + " (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);", + "#ifdef HAS_UNLESS", " if (t->e_trans)", - " printf(\" (escapes to state %%d)\",", - " t->st);", - "#endif", - " printf(\" %%saccepting [tau=%%d]\\n\",", - " (trpt->o_pm&2)?\"\":\"non-\", trpt->tau);", + " cpu_printf(\"\\t(escape to state %%d)\\n\", t->st);", "#endif", - "#ifdef RANDOMIZE", - " printf(\" randomizer %%d\\n\", ooi);", + "#endif", + "#ifdef T_RAND", + " cpu_printf(\"\\t(randomizer %%d)\\n\", ooi);", "#endif", "#endif", @@ -2143,9 +3160,10 @@ " trpt->o_ot = ot; trpt->o_tt = tt;", " trpt->o_To = To; trpt->o_m = _m;", " trpt->tau = 0;", -"#ifdef RANDOMIZE", + + "#ifdef T_RAND", " trpt->oo_i = ooi;", -"#endif", + "#endif", " if (boq != -1 || (t->atom&2))", " { trpt->tau |= 8;", "#ifdef VERI", @@ -2171,30 +3189,76 @@ " if (boq == -1 && (t->atom&2))", " { From = To = II; nlinks++;", " } else", - " { From = now._nr_pr-1; To = BASE;", + " { From = FROM_P; To = UPTO_P;", " }", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Push_Stack_Tree(II, t->t_id);", + " }", + "#endif", + "#ifdef TRIX", + " if (processes[II])", /* last move could have been a delproc */ + " { processes[II]->modified = 1; /* transition in II */", + " #ifdef V_TRIX", + " printf(\"%%4d: process %%d modified\\n\", depth, II);", + " } else", + " { printf(\"%%4d: process %%d modified but gone (%%p)\\n\",", + " depth, II, trpt);", + " #endif", + " }", + "#endif", " goto Down; /* pseudo-recursion */", "Up:", + "#ifdef TRIX", + " #ifndef TRIX_ORIG", + " #ifndef BFS", + " now._ids_[trpt->pr] = trpt->p_bup;", + " #endif", + " #else", + " if (processes[trpt->pr])", + " {", + " processes[trpt->pr]->modified = 1; /* reverse move */", + " #ifdef V_TRIX", + " printf(\"%%4d: unmodify pr %%d (%%p)\\n\",", + " depth, trpt->pr, trpt);", + " } else", + " { printf(\"%%4d: unmodify pr %%d (gone) (%%p)\\n\",", + " depth, trpt->pr, trpt);", + " #endif", + " }", + " #endif", + "#endif", "#ifdef CHECK", - " printf(\"%%d: Up - %%s\\n\", depth,", - " (trpt->tau&4)?\"claim\":\"program\");", - "#endif", - "#ifdef MA", - " if (depth <= 0) return;", - " /* e.g., if first state is old, after a restart */", + " cpu_printf(\"%%d: Up - %%s\\n\", depth,", + " (trpt->tau&4)?\"claim\":\"program\");", + "#endif", + "#if NCORE>1", + " iam_alive();", + " #ifdef USE_DISK", + " mem_drain();", + " #endif", + "#endif", + "#if defined(MA) || NCORE>1", + " if (depth <= 0) return;", + " /* e.g., if first state is old, after a restart */", "#endif", "#ifdef SC", - " if (CNT1 > CNT2", - " && depth < hiwater - (HHH-DDD) + 2)", - " {", - " trpt += DDD;", - " disk2stack();", - " maxdepth -= DDD;", - " hiwater -= DDD;", - "if(verbose)", - "printf(\"unzap %%d: %%d\\n\", CNT2, hiwater);", - " }", + " if (CNT1 > CNT2", + " && depth < hiwater - (HHH-DDD) - 2)", /* 5.1.6: was + 2 */ + " {", + " trpt += DDD;", + " disk2stack();", + " maxdepth -= DDD;", + " hiwater -= DDD;", + " if(verbose)", + " printf(\"unzap %%d: %%d\\n\", CNT2, hiwater);", + " }", + "#endif", + + "#ifndef SAFETY", /* moved earlier in version 5.2.5 */ + " if ((now._a_t&1) && depth <= A_depth)", + " return; /* to checkcycles() */", "#endif", "#ifndef NOFAIR", @@ -2203,7 +3267,7 @@ " _n = 1; trpt->o_pm &= ~128;", " depth--; trpt--;", "#if defined(VERBOSE) || defined(CHECK)", - " printf(\"%%3d: reversed fairness default move\\n\", depth);", + " printf(\"%%3ld: reversed fairness default move\\n\", depth);", "#endif", " goto Q999;", " }", @@ -2226,17 +3290,13 @@ "#ifdef EVENT_TRACE", " now._event = trpt->o_event;", "#endif", - "#ifndef SAFETY", - " if ((now._a_t&1) && depth <= A_depth)", - " return; /* to checkcycles() */", - "#endif", " t = trpt->o_t; _n = trpt->o_n;", " ot = trpt->o_ot; II = trpt->pr;", - " tt = trpt->o_tt; this = pptr(II);", + " tt = trpt->o_tt; this = Pptr(II);", " To = trpt->o_To; _m = trpt->o_m;", -"#ifdef RANDOMIZE", + "#ifdef T_RAND", " ooi = trpt->oo_i;", -"#endif", + "#endif", "#ifdef INLINE_REV", " _m = do_reverse(t, II, _m);", "#else", @@ -2245,42 +3305,42 @@ "#endif", "#ifdef VERBOSE", - " printf(\"%%3d: proc %%d \", depth, II);", - " printf(\"reverses %%d, %%d to %%d,\",", - " t->forw, tt, t->st);", - " printf(\" %%s [abit=%%d,adepth=%%d,\", ", - " t->tp, now._a_t, A_depth);", - " printf(\"tau=%%d,%%d]\\n\", ", - " trpt->tau, (trpt-1)->tau);", + " cpu_printf(\"%%3ld: proc %%d reverses %%d, %%d to %%d\\n\",", + " depth, II, t->forw, tt, t->st);", + " cpu_printf(\"\\t%%s [abit=%%d,adepth=%%d,tau=%%d,%%d]\\n\", ", + " t->tp, now._a_t, A_depth, trpt->tau, (trpt-1)->tau);", "#endif", "#ifndef NOREDUCE", " /* pass the proviso tags */", " if ((trpt->tau&8) /* rv or atomic */", " && (trpt->tau&16))", - " (trpt-1)->tau |= 16;", - "#ifdef SAFETY", + " (trpt-1)->tau |= 16;", /* pass upward */ + " #ifdef SAFETY", " if ((trpt->tau&8) /* rv or atomic */", " && (trpt->tau&64))", " (trpt-1)->tau |= 64;", - "#endif", - "#endif", + " #endif", + "#endif", + + "#if defined(BCS) && (defined(NOREDUCE) || !defined(SAFETY))", + /* for BCS, cover cases where 64 is otherwise not handled */ + " if ((trpt->tau&8)", + " && (trpt->tau&64))", + " (trpt-1)->tau |= 64;", + "#endif", + " depth--; trpt--;", + "", + "#ifdef NSUCC", + " trpt->n_succ++;", + "#endif", "#ifdef NIBIS", " (trans[ot][tt])->om = _m; /* head of list */", "#endif", " /* i.e., not set if rv fails */", " if (_m)", - " {", - "#if defined(VERI) && !defined(NP)", - " if (II == 0 && verbose && !reached[ot][t->st])", - " {", - " printf(\"depth %%d: Claim reached state %%d (line %%d)\\n\",", - " depth, t->st, src_claim [t->st]);", - " fflush(stdout);", - " }", - "#endif", - " reached[ot][t->st] = 1;", + " { reached[ot][t->st] = 1;", " reached[ot][tt] = 1;", " }", "#ifdef HAS_UNLESS", @@ -2291,18 +3351,18 @@ " ((P0 *)this)->_p = tt;", " } /* all options */", - "#ifdef RANDOMIZE", + "#ifdef T_RAND", " if (!t && ooi > 0)", /* means we skipped some initial options */ " { t = trans[ot][tt];", - "#ifdef VERBOSE", + " #ifdef VERBOSE", " printf(\"randomizer: continue for %%d more\\n\", ooi);", - "#endif", - " goto DOMORE;", + " #endif", + " goto domore;", " }", - "#ifdef VERBOSE", + " #ifdef VERBOSE", " else", " printf(\"randomizer: done\\n\");", - "#endif", + " #endif", "#endif", "#ifndef NOFAIR", @@ -2312,12 +3372,12 @@ " { if (trpt->o_pm&1)",/* it didn't block */ " {", "#ifdef VERI", - " if (now._cnt[now._a_t&1] == 1)", /* NEW: 1 iso 0 */ - " now._cnt[now._a_t&1] = 2;", /* NEW: 2 iso 1*/ + " if (now._cnt[now._a_t&1] == 1)", + " now._cnt[now._a_t&1] = 2;", "#endif", " now._cnt[now._a_t&1] += 1;", "#ifdef VERBOSE", - " printf(\"%%3d: proc %%d fairness \", depth, II);", + " printf(\"%%3ld: proc %%d fairness \", depth, II);", " printf(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",", " now._cnt[now._a_t&1], now._a_t);", "#endif", @@ -2326,7 +3386,7 @@ " { if (_n > 0)", /* a prev proc didn't */ " {", /* start over */ " trpt->o_pm &= ~64;", - " II = From+1;", + " II = INI_P;", /* after loop incr II == From */ " } } }", "#endif", @@ -2335,23 +3395,66 @@ "#endif", " } /* all processes */", + "#ifdef NSUCC", + " tally_succ(trpt->n_succ);", + "#endif", + + "#ifdef P_RAND", + " if (trpt->p_left > 0)", + " { trpt->p_skip = -1; /* probably rendundant */", + " #ifdef VERBOSE", + " printf(\"%%3ld: P_RAND -- explore remainder\\n\", depth);", + " #endif", + " goto r_switch; /* explore the remaining procs */", + " } else", + " {", + " #ifdef VERBOSE", + " printf(\"%%3ld: P_RAND -- none left\\n\", depth);", + " #endif", + " }", + "#endif", + + "#ifdef BCS", + " if (trpt->bcs & B_PHASE1)", + " { trpt->bcs = B_PHASE2; /* start 2nd phase */", + " if (_n == 0 || !(trpt->tau&64)) /* pre-move unexecutable or led to stackstate */", + " { trpt->bcs |= B_FORCED; /* forced switch */", + " }", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS move to phase 2, _n=%%d %%s\\n\", depth, _n,", + " (trpt->bcs & B_FORCED)?\"forced\":\"free\");", + " #endif", + " From = FROM_P; To = UPTO_P;", + " goto c_switch;", + " }", + "", + " if (_n == 0 /* no process could move */", + " && II >= BASE /* not the never claim */", + " && trpt->sched_limit >= sched_max)", + " { _n = 1;", + " #ifdef VERBOSE", + " printf(\"%%3ld: BCS not a deadlock\\n\", depth);", + " #endif", + " }", + "#endif", + "#ifndef NOFAIR", " /* Fairness: undo Rule 2 */", " if (trpt->o_pm&32) /* remains if proc blocked */", " {", "#ifdef VERI", - " if (now._cnt[now._a_t&1] == 1)", /* NEW: 1 iso 0 */ - " now._cnt[now._a_t&1] = 2;", /* NEW: 2 iso 1 */ + " if (now._cnt[now._a_t&1] == 1)", + " now._cnt[now._a_t&1] = 2;", "#endif", " now._cnt[now._a_t&1] += 1;", "#ifdef VERBOSE", - " printf(\"%%3d: proc -- fairness \", depth);", + " printf(\"%%3ld: proc -- fairness \", depth);", " printf(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",", " now._cnt[now._a_t&1], now._a_t);", "#endif", " trpt->o_pm &= ~32;", " }", -"#ifndef NP", + "#ifndef NP", /* 12/97 non-progress cycles cannot be created * by stuttering extension, here or elsewhere */ @@ -2382,14 +3485,14 @@ "#else", " trpt->tau = 0;", "#endif", - " From = now._nr_pr-1; To = BASE;", + " From = FROM_P; To = UPTO_P;", "#if defined(VERBOSE) || defined(CHECK)", - " printf(\"%%3d: fairness default move \", depth);", + " printf(\"%%3ld: fairness default move \", depth);", " printf(\"(all procs block)\\n\");", "#endif", " goto Down;", " }", -"#endif", + "#endif", "Q999: /* returns here with _n>0 when done */;", " if (trpt->o_pm&8)", @@ -2397,7 +3500,7 @@ " now._cnt[now._a_t&1] = 0;", " trpt->o_pm &= ~8;", "#ifdef VERBOSE", - " printf(\"%%3d: fairness undo Rule 1, _a_t=%%d\\n\",", + " printf(\"%%3ld: fairness undo Rule 1, _a_t=%%d\\n\",", " depth, now._a_t);", "#endif", " }", @@ -2406,7 +3509,7 @@ " now._cnt[now._a_t&1] = 1;", /* NEW: restore cnt */ " trpt->o_pm &= ~16;", "#ifdef VERBOSE", - " printf(\"%%3d: fairness undo Rule 3, _a_t=%%d\\n\",", + " printf(\"%%3ld: fairness undo Rule 3, _a_t=%%d\\n\",", " depth, now._a_t);", "#endif", " }", @@ -2414,15 +3517,22 @@ "#ifndef NOREDUCE", "#ifdef SAFETY", + " #ifdef LOOPSTATE", + " /* at least one move that was preselected at this */", + " /* level, blocked or was a loop control flow point */", + " if ((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))", + " #else", " /* preselected move - no successors outside stack */", " if ((trpt->tau&32) && !(trpt->tau&64))", - " { From = now._nr_pr-1; To = BASE;", - "#ifdef DEBUG", - " printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ", - " depth, II+1, _n, trpt->tau);", - "#endif", + " #endif", + " { From = FROM_P; To = UPTO_P;", + " #ifdef DEBUG", + " printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ", + " depth, II+1, _n, trpt->tau);", + " #endif", " _n = 0; trpt->tau &= ~(16|32|64);", - " if (II >= BASE) /* II already decremented */", + + " if (MORE_P) /* II already decremented */", " goto Resume;", " else", " goto Again;", @@ -2430,19 +3540,18 @@ "#else", " /* at least one move that was preselected at this */", " /* level, blocked or truncated at the next level */", - "/* implied: #ifdef FULLSTACK */", " if ((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))", " {", - "#ifdef DEBUG", - " printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ", - " depth, II+1, (int) _n, trpt->tau);", - "#endif", + " #ifdef DEBUG", + " printf(\"%%3ld: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ", + " depth, II+1, (int) _n, trpt->tau);", + " #endif", " if (a_cycles && (trpt->tau&16))", " { if (!(now._a_t&1))", " {", - "#ifdef DEBUG", - " printf(\"%%3d: setting proviso bit\\n\", depth);", - "#endif", + " #ifdef DEBUG", + " printf(\"%%3ld: setting proviso bit\\n\", depth);", + " #endif", "#ifndef BITSTATE", "#ifdef MA", "#ifdef VERI", @@ -2466,27 +3575,26 @@ " trpt->ostate->proviso = 1;", "#endif", "#endif", - " From = now._nr_pr-1; To = BASE;", + " From = FROM_P; To = UPTO_P;", " _n = 0; trpt->tau &= ~(16|32|64);", " goto Again; /* do full search */", " } /* else accept reduction */", " } else", - " { From = now._nr_pr-1; To = BASE;", + " { From = FROM_P; To = UPTO_P;", " _n = 0; trpt->tau &= ~(16|32|64);", - " if (II >= BASE) /* already decremented */", + " if (MORE_P) /* II already decremented */", " goto Resume;", " else", " goto Again;", " } }", - "/* #endif */", "#endif", "#endif", " if (_n == 0 || ((trpt->tau&4) && (trpt->tau&2)))", " {", "#ifdef DEBUG", - " printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d]\\n\",", - " depth, II, trpt->tau, boq);", + " cpu_printf(\"%%3ld: no move [II=%%d, tau=%%d, boq=%%d]\\n\",", + " depth, II, trpt->tau, boq);", "#endif", "#if SYNC", " /* ok if a rendez-vous fails: */", @@ -2497,15 +3605,14 @@ "#ifdef OTIM", " || endstate()", "#endif", - " || depth >= maxdepth-1) goto Done;", + " || depth >= maxdepth-1) goto Done; /* undo change from 5.2.3 */", " if ((trpt->tau&8) && !(trpt->tau&4))", " { trpt->tau &= ~(1|8);", " /* 1=timeout, 8=atomic */", - " From = now._nr_pr-1; To = BASE;", + " From = FROM_P; To = UPTO_P;", "#ifdef DEBUG", - " printf(\"%%3d: atomic step proc %%d \", depth, II+1);", - " printf(\"unexecutable\\n\");", + " cpu_printf(\"%%3ld: atomic step proc %%d unexecutable\\n\", depth, II+1);", "#endif", "#ifdef VERI", " trpt->tau |= 4; /* switch to claim */", @@ -2525,7 +3632,7 @@ " { trpt->tau |= 1;", " trpt->tau &= ~2;", "#ifdef DEBUG", - " printf(\"%%d: timeout\\n\", depth);", + " cpu_printf(\"%%d: timeout\\n\", depth);", "#endif", " goto Stutter;", " } }", @@ -2535,16 +3642,21 @@ " && !((trpt-1)->tau&4))", "/* blocks inside an atomic */ goto BreakOut;", "#ifdef DEBUG", - " printf(\"%%d: req timeout\\n\",", + " cpu_printf(\"%%d: req timeout\\n\",", " depth);", "#endif", " (trpt-1)->tau |= 2; /* request */", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", + " }", + "#endif", " goto Up;", " }", "#else", "#ifdef DEBUG", - " printf(\"%%d: timeout\\n\", depth);", + " cpu_printf(\"%%d: timeout\\n\", depth);", "#endif", " trpt->tau |= 1;", " goto Again;", @@ -2560,7 +3672,7 @@ " { trpt->tau |= 4; /* claim stuttering */", " trpt->tau |= 128; /* stutter mark */", "#ifdef DEBUG", - " printf(\"%%d: claim stutter\\n\", depth);", + " cpu_printf(\"%%d: claim stutter\\n\", depth);", "#endif", " goto Stutter;", " }", @@ -2585,6 +3697,47 @@ "Done:", " if (!(trpt->tau&8)) /* not in atomic seqs */", " {", + +"#ifndef MA", + "#if defined(FULLSTACK) || defined(CNTRSTACK)", + "#ifdef VERI", + " if (boq == -1", + " && (((trpt->tau&4) && !(trpt->tau&128))", + " || ( (trpt-1)->tau&128)))", + "#else", + " if (boq == -1)", + "#endif", + " {", + "#ifdef DEBUG2", + "#if defined(FULLSTACK)", + " printf(\"%%d: zapping %%u (%%d)\\n\",", + " depth, trpt->ostate,", + " (trpt->ostate)?trpt->ostate->tagged:0);", + "#endif", + "#endif", + " onstack_zap();", + " }", + "#endif", +"#else", + "#ifdef VERI", + " if (boq == -1", + " && (((trpt->tau&4) && !(trpt->tau&128))", + " || ( (trpt-1)->tau&128)))", + "#else", + " if (boq == -1)", + "#endif", + " {", + "#ifdef DEBUG", + " printf(\"%%d: zapping\\n\", depth);", + "#endif", + " onstack_zap();", + "#ifndef NOREDUCE", + " if (trpt->proviso)", + " gstore((char *) &now, vsize, 1);", + "#endif", + " }", +"#endif", + "#ifndef SAFETY", " if (_n != 0", /* we made a move */ "#ifdef VERI", @@ -2601,7 +3754,7 @@ " if (fairness)", /* implies a_cycles */ " {", "#ifdef VERBOSE", - " printf(\"Consider check %%d %%d...\\n\",", + " cpu_printf(\"Consider check %%d %%d...\\n\",", " now._a_t, now._cnt[0]);", "#endif", #if 0 @@ -2624,54 +3777,23 @@ " checkcycles();", " }", "#endif", -"#ifndef MA", - "#if defined(FULLSTACK) || defined(CNTRSTACK)", - "#ifdef VERI", - " if (boq == -1", - " && (((trpt->tau&4) && !(trpt->tau&128))", - " || ( (trpt-1)->tau&128)))", - "#else", - " if (boq == -1)", - "#endif", - " {", - "#ifdef DEBUG2", - "#if defined(FULLSTACK)", - " printf(\"%%d: zapping %%u (%%d)\\n\",", - " depth, trpt->ostate,", - " (trpt->ostate)?trpt->ostate->tagged:0);", - "#endif", - "#endif", - " onstack_zap();", + " }", + " if (depth > 0)", + " {", + "#if NCORE>1 && defined(FULL_TRAIL)", + " if (upto > 0)", + " { Pop_Stack_Tree();", " }", "#endif", -"#else", - "#ifdef VERI", - " if (boq == -1", - " && (((trpt->tau&4) && !(trpt->tau&128))", - " || ( (trpt-1)->tau&128)))", - "#else", - " if (boq == -1)", - "#endif", - " {", - "#ifdef DEBUG", - " printf(\"%%d: zapping\\n\", depth);", - "#endif", - " onstack_zap();", - "#ifndef NOREDUCE", - " if (trpt->proviso)", - " gstore((char *) &now, vsize, 1);", - "#endif", - " }", -"#endif", - " }", - " if (depth > 0) goto Up;", + " goto Up;", + " }", "}\n", "#else", "void new_state(void) { /* place holder */ }", "#endif", /* BFS */ "", "void", - "assert(int a, char *s, int ii, int tt, Trans *t)", + "spin_assert(int a, char *s, int ii, int tt, Trans *t)", "{", " if (!a && !noasserts)", " { char bad[1024];", @@ -2688,7 +3810,7 @@ "int", "Boundcheck(int x, int y, int a1, int a2, Trans *a3)", "{", - " assert((x >= 0 && x < y), \"- invalid array index\",", + " spin_assert((x >= 0 && x < y), \"- invalid array index\",", " a1, a2, a3);", " return x;", "}", @@ -2697,10 +3819,10 @@ "wrap_stats(void)", "{", " if (nShadow>0)", - " printf(\"%%8g states, stored (%%g visited)\\n\",", + " printf(\"%%9.8g states, stored (%%g visited)\\n\",", " nstates - nShadow, nstates);", " else", - " printf(\"%%8g states, stored\\n\", nstates);", + " printf(\"%%9.8g states, stored\\n\", nstates);", "#ifdef BFS", "#if SYNC", " printf(\" %%8g nominal states (- rv and atomic)\\n\", nstates-midrv-nlinks+revrv);", @@ -2714,143 +3836,144 @@ " printf(\" %%8g revrv\\n\", revrv);", "#endif", "#endif", - " printf(\"%%8g states, matched\\n\", truncs);", + " printf(\"%%9.8g states, matched\\n\", truncs);", "#ifdef CHECK", - " printf(\"%%8g matches within stack\\n\",truncs2);", + " printf(\"%%9.8g matches within stack\\n\",truncs2);", "#endif", " if (nShadow>0)", - " printf(\"%%8g transitions (= visited+matched)\\n\",", + " printf(\"%%9.8g transitions (= visited+matched)\\n\",", " nstates+truncs);", " else", - " printf(\"%%8g transitions (= stored+matched)\\n\",", + " printf(\"%%9.8g transitions (= stored+matched)\\n\",", " nstates+truncs);", - " printf(\"%%8g atomic steps\\n\", nlinks);", + " printf(\"%%9.8g atomic steps\\n\", nlinks);", " if (nlost) printf(\"%%g lost messages\\n\", (double) nlost);", "", "#ifndef BITSTATE", - " printf(\"hash conflicts: %%g (resolved)\\n\", hcmp);", + " #ifndef MA", + " printf(\"hash conflicts: %%9.8g (resolved)\\n\", hcmp);", + " #ifndef AUTO_RESIZE", + " if (hcmp > (double) (1< 100.)\\n\\n\",", + " (double)(((double) udmem) * 8.0) / (double) nstates);", + " else", " printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",", " (double)(1<<(ssize-8)) / (double) nstates * 256.0);", " printf(\"bits set per state: %%u (-k%%u)\\n\", hfns, hfns);", - "#if 0", -#ifndef POWOW + " #if 0", " if (udmem)", - " printf(\"total bits available: %%8g (-M%%ld)\\n\",", + " { printf(\"total bits available: %%8g (-M%%ld)\\n\",", " ((double) udmem) * 8.0, udmem/(1024L*1024L));", - " else", -#endif - " printf(\"total bits available: %%8g (-w%%d)\\n\",", - " ((double) (1L << (ssize-4)) * 16.0), ssize);", - "#endif", -"#ifdef COVEST", - " /* this code requires compilation with -lm on some systems */", - " { double pow(double, double);", - " double log(double);", - " unsigned int best_k;", - " double i, n = 30000.0L;", - " double f, p, q, m, c, est = 0.0L, k = (double)hfns;", - " c = (double) nstates / n;", - " m = (double) (1<<(ssize-8)) * 256.0L / c;", - " p = 1.0L - (k / m); q = 1.0L;", - " for (i = 0.0L; i - est < n; i += 1.0L)", - " { q *= p;", - " est += pow(1.0L - q, k);", - " }", - " f = m/i;", - " est *= c;", - " i *= c;", - " /* account for loss from enhanced double hashing */", - " if (hfns > 2) est += i * pow(0.5, (double) ssize * 2.0);", - "", - " if (f < 1.134) best_k = 1;", - " else if (f < 2.348) best_k = 2;", - " else if (f < 3.644) best_k = 3;", - " else best_k = (unsigned int) (pow(3.8L,1.0L/(f+4.2L))*f*.69315L + 0.99999999L);", - "", - " if (best_k != hfns && best_k > ssize)", - " best_k = (unsigned int) 1.0 + ssize/log((double)best_k / (double)ssize + 3.0);", - "", - " if (best_k > 32)", - " best_k = 1 + (unsigned int) (32.0/log((double)best_k/35.0));", - "", - " if (est * (double) nstates < 1.0)", - " { printf(\"prob. of omissions: negligible\\n\");", - " return; /* no hints needed */", - " }", - "", - " if (best_k != hfns)", - " { printf(\"hint: repeating the search with -k%%u \", best_k);", - " printf(\"may increase accuracy\\n\");", - " } else", - " { printf(\"hint: the current setting for -k (-k%%d) \", hfns);", - " printf(\"is likely to be optimal for -w%%d\\n\", ssize);", - " }", - " if (ssize < 32)", - " { printf(\"hint: increasing -w above -w%%d \", ssize);", - " printf(\"will increase accuracy (max is -w34)\\n\");", - " printf(\"(in xspin, increase Estimated State Space Size)\\n\");", - " } }", -"#endif", + " } else", + " { printf(\"total bits available: %%8g (-w%%d)\\n\",", + " ((double) (ONE_L << (ssize-4)) * 16.0), ssize);", + " }", + " #endif", + "#endif", + "#ifdef BFS_DISK", + " printf(\"bfs disk reads: %%ld writes %%ld -- diff %%ld\\n\",", + " bfs_dsk_reads, bfs_dsk_writes, bfs_dsk_writes-bfs_dsk_reads);", + " if (bfs_dsk_read >= 0) (void) close(bfs_dsk_read);", + " if (bfs_dsk_write >= 0) (void) close(bfs_dsk_write);", + " (void) unlink(\"pan_bfs_dsk.tmp\");", "#endif", "}", + "", "void", "wrapup(void)", - "{", - "#if defined(BITSTATE) || !defined(NOCOMP)", - " double nr1, nr2, nr3 = 0.0, nr4, nr5 = 0.0;", + "{ double nr1, nr2, nr3 = 0.0, nr4, nr5 = 0.0;", "#if !defined(MA) && (defined(MEMCNT) || defined(MEMLIM))", " int mverbose = 1;", "#else", " int mverbose = verbose;", "#endif", - "#endif", - + "#if NCORE>1", + " if (verbose) cpu_printf(\"wrapup -- %%d error(s)\\n\", errors);", + " if (core_id != 0)", + " {", + "#ifdef USE_DISK", + " void dsk_stats(void);", + " dsk_stats();", + "#endif", + " if (search_terminated != NULL)", + " { *search_terminated |= 2; /* wrapup */", + " }", + " exit(0); /* normal termination, not an error */", + " }", + "#endif", + "#if !defined(WIN32) && !defined(WIN64)", " signal(SIGINT, SIG_DFL);", - " printf(\"(%%s)\\n\", Version);", + "#endif", + " printf(\"\\n(%%s)\\n\", SpinVersion);", " if (!done) printf(\"Warning: Search not completed\\n\");", "#ifdef SC", " (void) unlink((const char *)stackfile);", "#endif", + "#if NCORE>1", + " if (a_cycles)", + " { printf(\" + Multi-Core (NCORE=%%d)\\n\", NCORE);", + " } else", + " { printf(\" + Multi-Core (NCORE=%%d -z%%ld)\\n\", NCORE, z_handoff);", + " }", + "#endif", "#ifdef BFS", " printf(\" + Using Breadth-First Search\\n\");", "#endif", "#ifndef NOREDUCE", " printf(\" + Partial Order Reduction\\n\");", "#endif", -#if 0 - "#ifdef Q_PROVISO", - " printf(\" + Queue Proviso\\n\");", - "#endif", -#endif + "#ifdef REVERSE", + " printf(\" + Reverse Depth-First Search Order\\n\");", + "#endif", + "#ifdef T_REVERSE", + " printf(\" + Reverse Transition Ordering\\n\");", + "#endif", + "#ifdef T_RAND", + " printf(\" + Randomized Transition Ordering\\n\");", + "#endif", + "#ifdef P_RAND", + " printf(\" + Randomized Process Ordering\\n\");", + "#endif", + "#ifdef BCS", + " printf(\" + Scheduling Restriction (-L%%d)\\n\", sched_max);", + "#endif", + "#ifdef TRIX", + " printf(\" + Tree Index Compression\\n\");", + "#endif", "#ifdef COLLAPSE", " printf(\" + Compression\\n\");", "#endif", "#ifdef MA", " printf(\" + Graph Encoding (-DMA=%%d)\\n\", MA);", - "#ifdef R_XPT", - " printf(\" Restarted from checkpoint %%s.xpt\\n\", Source);", - "#endif", + " #ifdef R_XPT", + " printf(\" Restarted from checkpoint %%s.xpt\\n\", PanSource);", + " #endif", "#endif", "#ifdef CHECK", - "#ifdef FULLSTACK", + " #ifdef FULLSTACK", " printf(\" + FullStack Matching\\n\");", - "#endif", - "#ifdef CNTRSTACK", + " #endif", + " #ifdef CNTRSTACK", " printf(\" + CntrStack Matching\\n\");", - "#endif", + " #endif", "#endif", "#ifdef BITSTATE", " printf(\"\\nBit statespace search for:\\n\");", "#else", - "#ifdef HC", + " #ifdef HC", " printf(\"\\nHash-Compact %%d search for:\\n\", HC);", - "#else", + " #else", " printf(\"\\nFull statespace search for:\\n\");", - "#endif", + " #endif", "#endif", "#ifdef EVENT_TRACE", "#ifdef NEGATED_TRACE", @@ -2860,7 +3983,8 @@ "#endif", "#endif", "#ifdef VERI", - " printf(\"\tnever claim \t+\\n\");", + " printf(\"\tnever claim \t+\");", + " printf(\" (%%s)\\n\", procname[((Pclaim *)pptr(0))->_t]);", " printf(\"\tassertion violations\t\");", " if (noasserts)", " printf(\"- (disabled by -A flag)\\n\");", @@ -2905,9 +4029,13 @@ " else", " printf(\"+\\n\\n\");", "#endif", - " printf(\"State-vector %%d byte, depth reached %%d\", ", - " hmax, mreached);", + " printf(\"State-vector %%d byte, depth reached %%ld\", hmax,", + "#if NCORE>1", + " (nr_handoffs * z_handoff) +", + "#endif", + " mreached);", " printf(\", errors: %%d\\n\", errors);", + " fflush(stdout);", "#ifdef MA", " if (done)", " { extern void dfa_stats(void);", @@ -2920,71 +4048,85 @@ " wrap_stats();", "#ifdef CHECK", " printf(\"stackframes: %%d/%%d\\n\\n\", smax, svmax);", - " printf(\"stats: fa %%d, fh %%d, zh %%d, zn %%d - \",", + " printf(\"stats: fa %%ld, fh %%ld, zh %%ld, zn %%ld - \",", " Fa, Fh, Zh, Zn);", - " printf(\"check %%d holds %%d\\n\", Ccheck, Cholds);", - " printf(\"stack stats: puts %%d, probes %%d, zaps %%d\\n\",", + " printf(\"check %%ld holds %%ld\\n\", Ccheck, Cholds);", + " printf(\"stack stats: puts %%ld, probes %%ld, zaps %%ld\\n\",", " PUT, PROBE, ZAPS);", "#else", " printf(\"\\n\");", "#endif", "", - "#if defined(BITSTATE) || !defined(NOCOMP)", + "#if !defined(BITSTATE) && defined(NOCOMP)", + " if (!verbose) { goto jump_here; }", /* added 5.2.0 */ + "#endif", + "", + "#if 1", /* omitted 5.2.0: defined(BITSTATE) || !defined(NOCOMP) */ " nr1 = (nstates-nShadow)*", " (double)(hmax+sizeof(struct H_el)-sizeof(unsigned));", - "#ifdef BFS", + " #ifdef BFS", " nr2 = 0.0;", - "#else", + " #else", " nr2 = (double) ((maxdepth+3)*sizeof(Trail));", - "#endif", - - "#ifndef BITSTATE", + " #endif", + + " #ifndef BITSTATE", "#if !defined(MA) || defined(COLLAPSE)", - " nr3 = (double) (1L<1 && !defined(SEP_STATE)", + " tmp_nr -= ((double) NCORE * LWQ_SIZE) + GWQ_SIZE;", + " #endif", " if (tmp_nr < 0.0) tmp_nr = 0.;", " printf(\"Stats on memory usage (in Megabytes):\\n\");", - " printf(\"%%-6.3f\tequivalent memory usage for states\",", - " nr1/1000000.);", + " printf(\"%%9.3f\tequivalent memory usage for states\",", + " nr1/1048576.); /* 1024*1024=1048576 */", " printf(\" (stored*(State-vector + overhead))\\n\");", + " #if NCORE>1 && !defined(WIN32) && !defined(WIN64)", + " printf(\"%%9.3f\tshared memory reserved for state storage\\n\",", + " mem_reserved/1048576.);", + " #ifdef SEP_HEAP", + " printf(\"\t\tin %%d local heaps of %%7.3f MB each\\n\",", + " NCORE, mem_reserved/(NCORE*1048576.));", + " #endif", + " printf(\"\\n\");", + " #endif", "#ifdef BITSTATE", -#ifndef POWOW " if (udmem)", - " printf(\"%%-6.3f\tmemory used for hash array (-M%%ld)\\n\",", - " nr3/1000000., udmem/(1024L*1024L));", + " printf(\"%%9.3f\tmemory used for hash array (-M%%ld)\\n\",", + " nr3/1048576., udmem/(1024L*1024L));", " else", -#endif - " printf(\"%%-6.3f\tmemory used for hash array (-w%%d)\\n\",", - " nr3/1000000., ssize);", + " printf(\"%%9.3f\tmemory used for hash array (-w%%d)\\n\",", + " nr3/1048576., ssize);", " if (nr5 > 0.0)", - " printf(\"%%-6.3f\tmemory used for bit stack\\n\",", - " nr5/1000000.);", + " printf(\"%%9.3f\tmemory used for bit stack\\n\",", + " nr5/1048576.);", " remainder = remainder - nr3 - nr5;", "#else", - " printf(\"%%-6.3f\tactual memory usage for states\",", - " tmp_nr/1000000.);", - " remainder = remainder - tmp_nr;", + " printf(\"%%9.3f\tactual memory usage for states\",", + " tmp_nr/1048576.);", + " remainder -= tmp_nr;", " printf(\" (\");", " if (tmp_nr > 0.)", " { if (tmp_nr > nr1) printf(\"unsuccessful \");", @@ -2994,50 +4136,87 @@ " printf(\"less than 1k)\\n\");", "#ifndef MA", " if (tmp_nr > 0.)", - " { printf(\"\tState-vector as stored = %%.0f byte\",", + " { printf(\" \tstate-vector as stored = %%.0f byte\",", " (tmp_nr)/(nstates-nShadow) -", " (double) (sizeof(struct H_el) - sizeof(unsigned)));", " printf(\" + %%ld byte overhead\\n\",", - " sizeof(struct H_el)-sizeof(unsigned));", + " (long int) sizeof(struct H_el)-sizeof(unsigned));", " }", "#endif", "#if !defined(MA) || defined(COLLAPSE)", - " printf(\"%%-6.3f\tmemory used for hash table (-w%%d)\\n\",", - " nr3/1000000., ssize);", - " remainder = remainder - nr3;", + " printf(\"%%9.3f\tmemory used for hash table (-w%%d)\\n\",", + " nr3/1048576., ssize);", + " remainder -= nr3;", "#endif", "#endif", - "#ifndef BFS", - " printf(\"%%-6.3f\tmemory used for DFS stack (-m%%ld)\\n\",", - " nr2/1000000., maxdepth);", - " remainder = remainder - nr2;", - "#endif", - " if (remainder - fragment > 0.0)", - " printf(\"%%-6.3f\tother (proc and chan stacks)\\n\",", - " (remainder-fragment)/1000000.);", - " if (fragment > 0.0)", - " printf(\"%%-6.3f\tmemory lost to fragmentation\\n\",", - " fragment/1000000.);", - " printf(\"%%-6.3f\ttotal actual memory usage\\n\\n\",", - " memcnt/1000000.);", - " }", + " #ifndef BFS", + " printf(\"%%9.3f\tmemory used for DFS stack (-m%%ld)\\n\",", + " nr2/1048576., maxdepth);", + " remainder -= nr2;", + " #endif", + "#if NCORE>1", + " remainder -= ((double) NCORE * LWQ_SIZE) + GWQ_SIZE;", + " printf(\"%%9.3f\tshared memory used for work-queues\\n\",", + " (GWQ_SIZE + (double) NCORE * LWQ_SIZE) /1048576.);", + " printf(\"\t\tin %%d queues of %%7.3f MB each\",", + " NCORE, (double) LWQ_SIZE /1048576.);", + " #ifndef NGQ", + " printf(\" + a global q of %%7.3f MB\\n\",", + " (double) GWQ_SIZE / 1048576.);", + " #else", + " printf(\"\\n\");", + " #endif", + " #endif", + " if (remainder - fragment > 1048576.)", + " printf(\"%%9.3f\tother (proc and chan stacks)\\n\",", + " (remainder-fragment)/1048576.);", + " if (fragment > 1048576.)", + " printf(\"%%9.3f\tmemory lost to fragmentation\\n\",", + " fragment/1048576.);", + " printf(\"%%9.3f\ttotal actual memory usage\\n\\n\",", + " memcnt/1048576.);", + " }", + " #ifndef MA", + " else", + " #endif", + "#endif", + + "#if !defined(BITSTATE) && defined(NOCOMP)", + "jump_here:", + "#endif", + "#ifndef MA", - " else", - "#endif", - "#endif", - "#ifndef MA", - " printf(\"%%-6.3f\tmemory usage (Mbyte)\\n\\n\",", - " memcnt/1000000.);", + " printf(\"%%9.3f\tmemory usage (Mbyte)\\n\\n\",", + " memcnt/1048576.);", "#endif", "#ifdef COLLAPSE", " printf(\"nr of templates: [ globals chans procs ]\\n\");", " printf(\"collapse counts: [ \");", " { int i; for (i = 0; i < 256+2; i++)", " if (ncomps[i] != 0)", - " printf(\"%%d \", ncomps[i]);", + " printf(\"%%d \", (int) ncomps[i]);", " printf(\"]\\n\");", " }", "#endif", + " #ifdef TRIX", + " if (mverbose)", + " { int i;", + " printf(\"TRIX counts:\\n\");", + " printf(\" processes: \");", + " for (i = 0; i < MAXPROC; i++)", + " if (_p_count[i] != 0)", + " { printf(\"%%3d:%%ld \",", + " i, _p_count[i]);", + " }", + " printf(\"\\n channels : \");", + " for (i = 0; i < MAXQ; i++)", + " if (_c_count[i] != 0)", + " { printf(\"%%3d:%%ld \",", + " i, _c_count[i]);", + " }", + " printf(\"\\n\\n\");", + " }", + " #endif", " if ((done || verbose) && !no_rck) do_reach();", "#ifdef PEG", @@ -3053,21 +4232,90 @@ "#ifdef SVDUMP", " if (vprefix > 0) close(svfd);", "#endif", + "#ifdef LOOPSTATE", + " printf(\"%%g loopstates hit\\n\", cnt_loops);", + "#endif", + "#ifdef NSUCC", + " dump_succ();", + "#endif", + "#if NCORE>1 && defined(T_ALERT)", + " crash_report();", + "#endif", " pan_exit(0);", "}\n", "void", "stopped(int arg)", "{ printf(\"Interrupted\\n\");", + "#if NCORE>1", + " was_interrupted = 1;", + "#endif", " wrapup();", " pan_exit(0);", "}", + "", + "#ifdef SFH", "/*", - " * based on Bob Jenkins hash-function from 1996", - " * see: http://www.burtleburtle.net/bob/", + " * super fast hash, based on Paul Hsieh's function", + " * http://www.azillionmonkeys.com/qed/hash.html", " */", - "", -"#if defined(HASH64) || defined(WIN64)", - /* 64-bit Jenkins hash: http://burtleburtle.net/bob/c/lookup8.c */ + "#include ", /* for uint32_t etc */ + " #undef get16bits", + " #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \\", + " || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)", + " #define get16bits(d) (*((const uint16_t *) (d)))", + " #endif", + "", + " #ifndef get16bits", + " #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\\", + " +(uint32_t)(((const uint8_t *)(d))[0]) )", + " #endif", + "", + "void", + "d_sfh(const char *s, int len)", + "{ uint32_t h = len, tmp;", + " int rem;", + "", + " rem = len & 3;", + " len >>= 2;", + "", + " for ( ; len > 0; len--)", + " { h += get16bits(s);", + " tmp = (get16bits(s+2) << 11) ^ h;", + " h = (h << 16) ^ tmp;", + " s += 2*sizeof(uint16_t);", + " h += h >> 11;", + " }", + " switch (rem) {", + " case 3: h += get16bits(s);", + " h ^= h << 16;", + " h ^= s[sizeof(uint16_t)] << 18;", + " h += h >> 11;", + " break;", + " case 2: h += get16bits(s);", + " h ^= h << 11;", + " h += h >> 17;", + " break;", + " case 1: h += *s;", + " h ^= h << 10;", + " h += h >> 1;", + " break;", + " }", + " h ^= h << 3;", + " h += h >> 5;", + " h ^= h << 4;", + " h += h >> 17;", + " h ^= h << 25;", + " h += h >> 6;", + "", + " K1 = h;", + "}", + "#endif", /* SFH */ + "", + "#include ", /* uint32_t etc. */ + "#if defined(HASH64) || defined(WIN64)", + "/* 64-bit Jenkins hash, 1997", + " * http://burtleburtle.net/bob/c/lookup8.c", + " */", "#define mix(a,b,c) \\", "{ a -= b; a -= c; a ^= (c>>43); \\", " b -= c; b -= a; b ^= (a<<9); \\", @@ -3082,56 +4330,119 @@ " b -= c; b -= a; b ^= (a<<18); \\", " c -= a; c -= b; c ^= (b>>22); \\", "}", -"#else", + "#else", + "/* 32-bit Jenkins hash, 2006", + " * http://burtleburtle.net/bob/c/lookup3.c", + " */", + "#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))", + "", "#define mix(a,b,c) \\", - "{ a -= b; a -= c; a ^= (c>>13); \\", - " b -= c; b -= a; b ^= (a<<8); \\", - " c -= a; c -= b; c ^= (b>>13); \\", - " a -= b; a -= c; a ^= (c>>12); \\", - " b -= c; b -= a; b ^= (a<<16); \\", - " c -= a; c -= b; c ^= (b>>5); \\", - " a -= b; a -= c; a ^= (c>>3); \\", - " b -= c; b -= a; b ^= (a<<10); \\", - " c -= a; c -= b; c ^= (b>>15); \\", + "{ a -= c; a ^= rot(c, 4); c += b; \\", + " b -= a; b ^= rot(a, 6); a += c; \\", + " c -= b; c ^= rot(b, 8); b += a; \\", + " a -= c; a ^= rot(c,16); c += b; \\", + " b -= a; b ^= rot(a,19); a += c; \\", + " c -= b; c ^= rot(b, 4); b += a; \\", "}", -"#endif", + "", + "#define final(a,b,c) \\", + "{ c ^= b; c -= rot(b,14); \\", + " a ^= c; a -= rot(c,11); \\", + " b ^= a; b -= rot(a,25); \\", + " c ^= b; c -= rot(b,16); \\", + " a ^= c; a -= rot(c,4); \\", + " b ^= a; b -= rot(a,14); \\", + " c ^= b; c -= rot(b,24); \\", + "}", + "#endif", + "", "void", - "d_hash(uchar *Cp, int Om) /* double bit hash - Jenkins */", - "{ unsigned long a = 0x9e3779b9, b, c = 0, len, length;", - " unsigned long *k = (unsigned long *) Cp;", - "", - " length = len = (unsigned long) ((unsigned long) Om + WS-1)/WS;", - "", + "d_hash(uchar *kb, int nbytes)", + "{ uint8_t *bp;", + "#if defined(HASH64) || defined(WIN64)", + " uint64_t a = 0, b, c, n;", + " uint64_t *k = (uint64_t *) kb;", + "#else", + " uint32_t a = 0, b, c, n;", + " uint32_t *k = (uint32_t *) kb;", + "#endif", + " n = nbytes/WS; /* nr of words */", + " /* extend to multiple of words, if needed */", + " a = WS - (nbytes %% WS);", + " if (a > 0 && a < WS)", + " { n++;", + " bp = kb + nbytes;", + " switch (a) {", + "#if defined(HASH64) || defined(WIN64)", + " case 7: *bp++ = 0; /* fall thru */", + " case 6: *bp++ = 0; /* fall thru */", + " case 5: *bp++ = 0; /* fall thru */", + " case 4: *bp++ = 0; /* fall thru */", + "#endif", + " case 3: *bp++ = 0; /* fall thru */", + " case 2: *bp++ = 0; /* fall thru */", + " case 1: *bp = 0;", + " case 0: break;", + " } }", + "#if defined(HASH64) || defined(WIN64)", " b = HASH_CONST[HASH_NR];", - " while (len >= 3)", + " c = 0x9e3779b97f4a7c13LL; /* arbitrary value */", + " while (n >= 3)", " { a += k[0];", " b += k[1];", " c += k[2];", " mix(a,b,c);", - " k += 3; len -= 3;", - " }", - " c += length;", - " switch (len) {", + " n -= 3;", + " k += 3;", + " }", + " c += (((uint64_t) nbytes)<<3);", + " switch (n) {", " case 2: b += k[1];", " case 1: a += k[0];", + " case 0: break;", " }", " mix(a,b,c);", - " j1 = c&nmask; j3 = a&7;", /* 1st bit */ - " j2 = b&nmask; j4 = (a>>3)&7;", /* 2nd bit */ - " K1 = c; K2 = b;", /* no nmask */ + "#else", /* 32 bit version: */ + " a = c = 0xdeadbeef + (n<<2);", + " b = HASH_CONST[HASH_NR];", + " while (n > 3)", + " { a += k[0];", + " b += k[1];", + " c += k[2];", + " mix(a,b,c);", + " n -= 3;", + " k += 3;", + " }", + " switch (n) { ", + " case 3: c += k[2];", + " case 2: b += k[1];", + " case 1: a += k[0];", + " final(a,b,c);", + " case 0: break;", + " }", + "#endif", + " j1_spin = c&nmask; j3 = a&7; /* 1st bit */", + " j2 = b&nmask; j4 = (a>>3)&7; /* 2nd bit */", + " K1 = c; K2 = b;", "}", + "", "void", "s_hash(uchar *cp, int om)", - "{ d_hash(cp, om); /* sets K1 and K2 */", + "{", + "#if defined(SFH)", + " d_sfh((const char *) cp, om); /* sets K1 */", + "#else", + " d_hash(cp, om); /* sets K1 etc */", + "#endif", "#ifdef BITSTATE", " if (S_Tab == H_tab)", /* state stack in bitstate search */ - " j1 = K1 %% omaxdepth;", + " j1_spin = K1 %% omaxdepth;", " else", "#endif", /* if (S_Tab != H_Tab) */ " if (ssize < 8*WS)", - " j1 = K1&mask;", + " j1_spin = K1&mask;", " else", - " j1 = K1;", + " j1_spin = K1;", "}", "#ifndef RANDSTOR", "int *prerand;", @@ -3150,389 +4461,9 @@ "}", "#endif", "", - "int", - "main(int argc, char *argv[])", - "{ void to_compile(void);\n", - " efd = stderr; /* default */", - "#ifdef BITSTATE", - " bstore = bstore_reg; /* default */", - "#endif", - " while (argc > 1 && argv[1][0] == '-')", - " { switch (argv[1][1]) {", - "#ifndef SAFETY", - "#ifdef NP", - " case 'a': fprintf(efd, \"error: -a disabled\");", - " usage(efd); break;", - "#else", - " case 'a': a_cycles = 1; break;", - "#endif", - "#endif", - " case 'A': noasserts = 1; break;", - " case 'b': bounded = 1; break;", - " case 'c': upto = atoi(&argv[1][2]); break;", - " case 'd': state_tables++; break;", - " case 'e': every_error = 1; Nr_Trails = 1; break;", - " case 'E': noends = 1; break;", - "#ifdef SC", - " case 'F': if (strlen(argv[1]) > 2)", - " stackfile = &argv[1][2];", - " break;", - "#endif", - "#if !defined(SAFETY) && !defined(NOFAIR)", - " case 'f': fairness = 1; break;", - "#endif", - " case 'h': if (!argv[1][2]) usage(efd); else", - " HASH_NR = atoi(&argv[1][2])%%33; break;", - " case 'I': iterative = 2; every_error = 1; break;", - " case 'i': iterative = 1; every_error = 1; break;", - " case 'J': like_java = 1; break; /* Klaus Havelund */", - "#ifdef BITSTATE", - " case 'k': hfns = atoi(&argv[1][2]); break;", - "#endif", - "#ifndef SAFETY", - "#ifdef NP", - " case 'l': a_cycles = 1; break;", - "#else", - " case 'l': fprintf(efd, \"error: -l disabled\");", - " usage(efd); break;", - "#endif", - "#endif", -#ifndef POWOW - "#ifdef BITSTATE", - " case 'M': udmem = atoi(&argv[1][2]); break;", - " case 'G': udmem = atoi(&argv[1][2]); udmem *= 1024; break;", - "#else", - " case 'M': case 'G':", - " fprintf(stderr, \"-M and -G affect only -DBITSTATE\\n\");", - " break;", - "#endif", -#endif - " case 'm': maxdepth = atoi(&argv[1][2]); break;", - " case 'n': no_rck = 1; break;", - "#ifdef SVDUMP", - " case 'p': vprefix = atoi(&argv[1][2]); break;", - "#endif", - " case 'q': strict = 1; break;", - "#ifdef HAS_CODE", - " case 'r':", - "samething: readtrail = 1;", - " if (isdigit(argv[1][2]))", - " whichtrail = atoi(&argv[1][2]);", - " break;", - " case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]); break;", - " case 'C': coltrace = 1; goto samething;", - " case 'g': gui = 1; goto samething;", - " case 'S': silent = 1; break;", - "#endif", - " case 'R': Nrun = atoi(&argv[1][2]); break;", - "#ifdef BITSTATE", - " case 's': hfns = 1; break;", - "#endif", - " case 'T': TMODE = 0444; break;", - " case 't': if (argv[1][2]) tprefix = &argv[1][2]; break;", - " case 'V': printf(\"Generated by %%s\\n\", Version);", - " to_compile(); pan_exit(0); break;", - " case 'v': verbose = 1; break;", - " case 'w': ssize = atoi(&argv[1][2]); break;", - " case 'Y': signoff = 1; break;", - " case 'X': efd = stdout; break;", - " default : fprintf(efd, \"saw option -%%c\\n\", argv[1][1]); usage(efd); break;", - " }", - " argc--; argv++;", - " }", - " if (iterative && TMODE != 0666)", - " { TMODE = 0666;", - " fprintf(efd, \"warning: -T ignored when -i or -I is used\\n\");", - " }", - "#if defined(WIN32) || defined(WIN64)", - " if (TMODE == 0666)", - " TMODE = _S_IWRITE | _S_IREAD;", - " else", - " TMODE = _S_IREAD;", - "#endif", - "#ifdef OHASH", - " fprintf(efd, \"warning: -DOHASH no longer supported (directive ignored)\\n\");", - "#endif", - "#ifdef JHASH", - " fprintf(efd, \"warning: -DJHASH no longer supported (directive ignored)\\n\");", - "#endif", - "#ifdef HYBRID_HASH", - " fprintf(efd, \"warning: -DHYBRID_HASH no longer supported (directive ignored)\\n\");", - "#endif", - "#ifdef NOCOVEST", - " fprintf(efd, \"warning: -DNOCOVEST no longer supported (directive ignored)\\n\");", - "#endif", - "#ifdef BITSTATE", - "#ifdef BCOMP", - " fprintf(efd, \"warning: -DBCOMP no longer supported (directive ignored)\\n\");", - "#endif", - " if (hfns <= 0)", - " { hfns = 1;", - " fprintf(efd, \"warning: using -k%%d as minimal usable value\\n\", hfns);", - " }", - "#endif", - " omaxdepth = maxdepth;", - "#ifdef BITSTATE", - " if (WS == 4 && ssize > 34)", /* 32-bit word size */ - " { ssize = 34;", - " fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);", - "/*", - " * -w35 would not work: 35-3 = 32 but 1^31 is the largest", - " * power of 2 that can be represented in an unsigned long", - " */", - " }", - "#else", - " if (WS == 4 && ssize > 27)", - " { ssize = 27;", - " fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);", - "/*", - " * for emalloc, the lookup table size multiplies by 4 for the pointers", - " * the largest power of 2 that can be represented in a ulong is 1^31", - " * hence the largest number of lookup table slots is 31-4 = 27", - " */", - " }", - - "#endif", - "#ifdef SC", - " hiwater = HHH = maxdepth-10;", - " DDD = HHH/2;", - " if (!stackfile)", - " { stackfile = (char *) emalloc(strlen(Source)+4+1);", - " sprintf(stackfile, \"%%s._s_\", Source);", - " }", - " if (iterative)", - " { fprintf(efd, \"error: cannot use -i or -I with -DSC\\n\");", - " pan_exit(1);", - " }", - "#endif", - - "#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)", - " fprintf(efd, \"error: -D?_XPT requires -DMA\\n\");", - " exit(1);", - "#endif", - - " if (iterative && a_cycles)", - " fprintf(efd, \"warning: -i or -I work for safety properties only\\n\");", - - "#ifdef BFS", - "#if defined(SC)", - " fprintf(efd, \"error: -DBFS not compatible with -DSC\\n\");", - " exit(1);", - "#endif", - "#if defined(HAS_LAST)", - " fprintf(efd, \"error: -DBFS not compatible with _last\\n\");", - " exit(1);", - "#endif", - "#if defined(REACH)", - " fprintf(efd, \"warning: -DREACH redundant when -DBFS is used\\n\");", - "#endif", - "#if defined(HAS_STACK)", - " fprintf(efd, \"error: cannot use UnMatched qualifier on c_track with BFS\\n\");", - " exit(1);", - "#endif", - "#endif", - - "#if defined(MERGED) && defined(PEG)", - " fprintf(efd, \"error: to allow -DPEG use: spin -o3 -a %%s\\n\", Source);", - " fprintf(efd, \" to turn off transition merge optimization\\n\");", - " pan_exit(1);", - "#endif", - "#ifdef HC", - "#ifdef NOCOMP", - " fprintf(efd, \"error: cannot combine -DHC and -DNOCOMP\\n\");", - " pan_exit(1);", - "#endif", - "#ifdef BITSTATE", - " fprintf(efd, \"error: cannot combine -DHC and -DBITSTATE\\n\");", - " pan_exit(1);", - "#endif", - "#endif", - "#if defined(SAFETY) && defined(NP)", - " fprintf(efd, \"error: cannot combine -DNP and -DSAFETY\\n\");", - " pan_exit(1);", - "#endif", - "#ifdef MA", - "#ifdef BITSTATE", - " fprintf(efd, \"error: cannot combine -DMA and -DBITSTATE\\n\");", - " pan_exit(1);", - "#endif", - " if (MA <= 0)", - " { fprintf(efd, \"usage: -DMA=N with N > 0 and < VECTORSZ\\n\");", - " pan_exit(1);", - " }", - "#endif", - "#ifdef COLLAPSE", - "#if defined(BITSTATE)", - " fprintf(efd, \"error: cannot combine -DBITSTATE and -DCOLLAPSE\\n\");", - " pan_exit(1);", - "#endif", - "#if defined(NOCOMP)", - " fprintf(efd, \"error: cannot combine -DNOCOMP and -DCOLLAPSE\\n\");", - " pan_exit(1);", - "#endif", - "#endif", - " if (maxdepth <= 0 || ssize <= 1) usage(efd);", - "#if SYNC>0 && !defined(NOREDUCE)", - " if (a_cycles && fairness)", - " { fprintf(efd, \"error: p.o. reduction not compatible with \");", - " fprintf(efd, \"fairness (-f) in models\\n\");", - " fprintf(efd, \" with rendezvous operations: \");", - " fprintf(efd, \"recompile with -DNOREDUCE\\n\");", - " pan_exit(1);", - " }", - "#endif", - "#if defined(REM_VARS) && !defined(NOREDUCE)", - " { fprintf(efd, \"warning: p.o. reduction not compatible with \");", - " fprintf(efd, \"remote varrefs (use -DNOREDUCE)\\n\");", - " }", - "#endif", - "#if defined(NOCOMP) && !defined(BITSTATE)", - " if (a_cycles)", - " { fprintf(efd, \"error: -DNOCOMP voids -l and -a\\n\");", - " pan_exit(1);", - " }", - "#endif", - - "#ifdef MEMLIM", /* MEMLIM setting takes precedence */ - " memlim = (double) MEMLIM * (double) (1<<20); /* size in Mbyte */", - "#else", - "#ifdef MEMCNT", - "#if MEMCNT<31", - " memlim = (double) (1< 1) HASH_NR = Nrun - 1;", - "#endif", - " if (Nrun < 1 || Nrun > 32)", - " { fprintf(efd, \"error: invalid arg for -R\\n\");", - " usage(efd);", - " }", - "#ifndef SAFETY", - " if (fairness && !a_cycles)", - " { fprintf(efd, \"error: -f requires -a or -l\\n\");", - " usage(efd);", - " }", - "#if ACCEPT_LAB==0", - " if (a_cycles)", - "#ifndef VERI", - " { fprintf(efd, \"error: no accept labels defined \");", - " fprintf(efd, \"in model (for option -a)\\n\");", - " usage(efd);", - " }", - "#else", - " { fprintf(efd, \"warning: no explicit accept labels \");", - " fprintf(efd, \"defined in model (for -a)\\n\");", - " }", - "#endif", - "#endif", - "#endif", - "#if !defined(NOREDUCE)", - "#if defined(HAS_ENABLED)", - " fprintf(efd, \"error: reduced search precludes \");", - " fprintf(efd, \"use of 'enabled()'\\n\");", - " pan_exit(1);", - "#endif", - "#if defined(HAS_PCVALUE)", - " fprintf(efd, \"error: reduced search precludes \");", - " fprintf(efd, \"use of 'pcvalue()'\\n\");", - " pan_exit(1);", - "#endif", - "#if defined(HAS_BADELSE)", - " fprintf(efd, \"error: reduced search precludes \");", - " fprintf(efd, \"using 'else' combined with i/o stmnts\\n\");", - " pan_exit(1);", - "#endif", - "#if defined(HAS_LAST)", - " fprintf(efd, \"error: reduced search precludes \");", - " fprintf(efd, \"use of _last\\n\");", - " pan_exit(1);", - "#endif", - "#endif", - - "#if SYNC>0 && !defined(NOREDUCE)", - "#ifdef HAS_UNLESS", - " fprintf(efd, \"warning: use of a rendezvous stmnts in the escape\\n\");", - " fprintf(efd, \"\tof an unless clause, if present, could make p.o. reduction\\n\");", - " fprintf(efd, \"\tinvalid (use -DNOREDUCE to avoid this)\\n\");", - "#ifdef BFS", - " fprintf(efd, \"\t(this type of rv is also not compatible with -DBFS)\\n\");", - "#endif", - "#endif", - "#endif", - "#if SYNC>0 && defined(BFS)", - " fprintf(efd, \"warning: use of rendezvous in BFS mode \");", - " fprintf(efd, \"does not preserve all invalid endstates\\n\");", - "#endif", - "#if !defined(REACH) && !defined(BITSTATE)", - " if (iterative != 0 && a_cycles == 0)", - " fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");", - "#endif", - "#if defined(BITSTATE) && defined(REACH)", - " fprintf(efd, \"warning: -DREACH voided by -DBITSTATE\\n\");", - "#endif", - "#if defined(MA) && defined(REACH)", - " fprintf(efd, \"warning: -DREACH voided by -DMA\\n\");", - "#endif", - "#if defined(FULLSTACK) && defined(CNTRSTACK)", - " fprintf(efd, \"error: cannot combine\");", - " fprintf(efd, \" -DFULLSTACK and -DCNTRSTACK\\n\");", - " pan_exit(1);", - "#endif", - "#if defined(VERI)", - "#if ACCEPT_LAB>0", - "#ifndef BFS", - " if (!a_cycles", - "#ifdef HAS_CODE", - " && !readtrail", - "#endif", - " && !state_tables)", - " { fprintf(efd, \"warning: never claim + accept labels \");", - " fprintf(efd, \"requires -a flag to fully verify\\n\");", - " }", - "#else", - " if (", - "#ifdef HAS_CODE", - " !readtrail", - "#endif", - " && !state_tables)", - " { fprintf(efd, \"warning: verification in BFS mode \");", - " fprintf(efd, \"is restricted to safety properties\\n\");", - " }", - "#endif", - "#endif", - "#endif", - "#ifndef SAFETY", - " if (!a_cycles", - "#ifdef HAS_CODE", - " && !readtrail", - "#endif", - " && !state_tables)", - " { fprintf(efd, \"hint: this search is more efficient \");", - " fprintf(efd, \"if pan.c is compiled -DSAFETY\\n\");", - " }", - "#ifndef NOCOMP", - " if (!a_cycles)", - " S_A = 0;", - " else", - " { if (!fairness)", - " S_A = 1; /* _a_t */", - "#ifndef NOFAIR", - " else /* _a_t and _cnt[NFAIR] */", - " S_A = (&(now._cnt[0]) - (uchar *) &now) + NFAIR - 2;", - " /* -2 because first two uchars in now are masked */", - "#endif", - " }", - "#endif", - "#endif", - " signal(SIGINT, stopped);", - - /******************* 4.2.5 ********************/ + "void", + "set_masks(void) /* 4.2.5 */", + "{", " if (WS == 4 && ssize >= 32)", " { mask = 0xffffffff;", "#ifdef BITSTATE", @@ -3545,21 +4476,625 @@ " nmask = mask;", "#endif", " } else if (WS == 8)", - " { mask = ((1L<>3;", "#else", " nmask = mask;", "#endif", " } else if (WS != 4)", - " { fprintf(stderr, \"pan: wordsize %%ld not supported\\n\", WS);", + " { fprintf(stderr, \"pan: wordsize %%ld not supported\\n\", (long int) WS);", " exit(1);", " } else /* WS == 4 and ssize < 32 */", - " { mask = ((1L<>3);", " }", - /****************** end **********************/ - + "}", + "", + "static long reclaim_size;", + "static char *reclaim_mem;", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)", + "#if NCORE>1", + " #error cannot combine AUTO_RESIZE with NCORE>1 yet", + "#endif", + "static struct H_el **N_tab;", + "void", + "reverse_capture(struct H_el *p)", + "{ if (!p) return;", + " reverse_capture(p->nxt);", + " /* last element of list moves first */", + " /* to preserve list-order */", + " j2 = p->m_K1;", + " if (ssize < 8*WS) /* probably always true */", + " { j2 &= mask;", + " }", + " p->nxt = N_tab[j2];", + " N_tab[j2] = p;", + "}", + "void", + "resize_hashtable(void)", + "{", + " if (WS == 4 && ssize >= 27 - 1)", + " { return; /* cannot increase further */", + " }", + "", + " ssize += 2; /* 4x size @htable ssize */", + "", + " printf(\"pan: resizing hashtable to -w%%d.. \", ssize);", + "", + " N_tab = (struct H_el **)", + " emalloc((ONE_L<1", + "int", + "find_claim(char *s)", + "{ int i, j;", + " for (i = 0; procname[i] != \":np_:\"; i++)", + " { if (strcmp(s, procname[i]) == 0)", + " { for (j = 0; j < NCLAIMS; j++)", + " { if (spin_c_typ[j] == i)", + " { return j;", + " } }", + " break;", + " } }", + " printf(\"pan: error: cannot find claim '%%s'\\n\", s);", + " exit(1);", + " return -1; /* unreachable */", + "}", + "#endif", + "", + "int", + "main(int argc, char *argv[])", + "{ void to_compile(void);\n", + " efd = stderr; /* default */", + "", + " if (G_long != sizeof(long)", + " || G_int != sizeof(int))", + " { printf(\"spin: error, the version of spin \");", + " printf(\"that generated this pan.c assumed a different \");", + " printf(\"wordsize (%%d iso %%d)\\n\", G_long, (int) sizeof(long));", + " exit(1);", + " }", + "", + "#if defined(T_RAND) && (T_RAND>0)", + " s_rand = T_RAND;", /* so that -RS can override */ + "#elif defined(P_RAND) && (P_RAND>0)", + " s_rand = P_RAND;", + "#endif", /* else, could use time as seed... */ + "", + "#ifdef PUTPID", + " { char *ptr = strrchr(argv[0], '/');", + " if (ptr == NULL)", + " { ptr = argv[0];", + " } else", + " { ptr++;", + " }", + " progname = emalloc(strlen(ptr));", + " strcpy(progname, ptr);", + " /* printf(\"progname: %%s\\n\", progname); */", + " }", + "#endif", + "", + "#ifdef BITSTATE", + " bstore = bstore_reg; /* default */", + "#endif", + "#if NCORE>1", + " { int i, j;", + " strcpy(o_cmdline, \"\");", + " for (j = 1; j < argc; j++)", + " { strcat(o_cmdline, argv[j]);", + " strcat(o_cmdline, \" \");", + " }", + " /* printf(\"Command Line: %%s\\n\", o_cmdline); */", + " if (strlen(o_cmdline) >= sizeof(o_cmdline))", + " { Uerror(\"option list too long\");", + " } }", + "#endif", + " while (argc > 1 && argv[1][0] == '-')", + " { switch (argv[1][1]) {", + "#ifndef SAFETY", + "#ifdef NP", + " case 'a': fprintf(efd, \"error: -a disabled\");", + " usage(efd); break;", + "#else", + " case 'a': a_cycles = 1; break;", + "#endif", + "#endif", + " case 'A': noasserts = 1; break;", + " case 'b': bounded = 1; break;", + "#ifdef HAS_CODE", + " case 'C': coltrace = 1; goto samething;", + "#endif", + " case 'c': upto = atoi(&argv[1][2]); break;", + " case 'D': dodot++; state_tables++; break;", + " case 'd': state_tables++; break;", + " case 'e': every_error = 1; upto = 0; Nr_Trails = 1; break;", + " case 'E': noends = 1; break;", + "#ifdef SC", + " case 'F': if (strlen(argv[1]) > 2)", + " stackfile = &argv[1][2];", + " break;", + "#endif", + "#if !defined(SAFETY) && !defined(NOFAIR)", + " case 'f': fairness = 1; break;", + "#endif", + "#ifdef HAS_CODE", + " case 'g': gui = 1; goto samething;", + "#endif", + " case 'h': if (!argv[1][2]) usage(efd); else", + " HASH_NR = atoi(&argv[1][2])%%100; break;", + " case 'I': iterative = 2; every_error = 1; break;", + " case 'i': iterative = 1; every_error = 1; break;", + " case 'J': like_java = 1; break; /* Klaus Havelund */", + "#ifdef BITSTATE", + " case 'k': hfns = atoi(&argv[1][2]); break;", + "#endif", + "#ifdef BCS", + " case 'L':", + " sched_max = atoi(&argv[1][2]);", + " if (sched_max > 255) /* stored as one byte */", + " { fprintf(efd, \"warning: using max bound (255)\\n\");", + " sched_max = 255;", + " }", + " #ifndef NOREDUCE", + " if (sched_max == 0)", + " { fprintf(efd, \"warning: with (default) bound -L0, \");", + " fprintf(efd, \"using -DNOREDUCE performs better\\n\");", + " }", + " #endif", + " break;", + "#endif", + "#ifndef SAFETY", + "#ifdef NP", + " case 'l': a_cycles = 1; break;", + "#else", + " case 'l': fprintf(efd, \"error: -l disabled\");", + " usage(efd); break;", + "#endif", + "#endif", + "#ifdef BITSTATE", + " case 'M': udmem = atoi(&argv[1][2]); break;", + " case 'G': udmem = atoi(&argv[1][2]); udmem *= 1024; break;", + "#else", + " case 'M': case 'G':", + " fprintf(stderr, \"-M and -G affect only -DBITSTATE\\n\");", + " break;", + "#endif", + " case 'm': maxdepth = atoi(&argv[1][2]); break;", +"#ifndef NOCLAIM", + " case 'N':", + "#if NCLAIMS>1", + " if (isdigit(argv[1][2]))", + " whichclaim = atoi(&argv[1][2]);", + " else if (isalpha(argv[1][2]))", + " { claimname = &argv[1][2];", + " } else if (argc > 2 && argv[2][0] != '-') /* check next arg */", + " { claimname = argv[2];", + " argc--; argv++; /* skip next arg */", + " }", + "#else", + " #if NCLAIMS==1", + " fprintf(stderr, \"warning: only one claim defined, -N ignored\\n\");", + " #else", + " fprintf(stderr, \"warning: no claims defined, -N ignored\\n\");", + " #endif", + " if (!isdigit(argv[1][2]) && argc > 2 && argv[2][0] != '-')", + " { argc--; argv++;", + " }", + "#endif", +"#endif", + " break;\n", + " case 'n': no_rck = 1; break;", + " case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]);", + " if (argv[2][0] != '-') /* check next arg */", + " { trailfilename = argv[2];", + " argc--; argv++; /* skip next arg */", + " }", + " break;", + "#ifdef SVDUMP", + " case 'p': vprefix = atoi(&argv[1][2]); break;", + "#endif", + "#if NCORE==1", + " case 'Q': quota = (double) 60.0 * (double) atoi(&argv[1][2]);", + " #ifndef FREQ", + " freq /= 10.; /* for better resolution */", + " #endif", + " break;", + "#endif", + " case 'q': strict = 1; break;", + " case 'R':", + "#if defined(T_RAND) || defined(P_RAND) || defined(RANDSTOR)", + " if (argv[1][2] == 'S') /* e.g., -RS76842 */", + " { s_rand = atoi(&argv[1][3]);", + " } else", + "#endif", + " { Nrun = atoi(&argv[1][2]);", + " }", + " break;", + "#ifdef HAS_CODE", + " case 'r':", + "samething: readtrail = 1;", + " if (isdigit(argv[1][2]))", + " whichtrail = atoi(&argv[1][2]);", + " else if (argc > 2 && argv[2][0] != '-') /* check next arg */", + " { trailfilename = argv[2];", + " argc--; argv++; /* skip next arg */", + " }", + " break;", + " case 'S': silent = 1; goto samething;", + "#endif", + "#ifdef BITSTATE", + " case 's': hfns = 1; break;", + "#endif", + " case 'T': TMODE = 0444; break;", + " case 't': if (argv[1][2]) tprefix = &argv[1][2]; break;", + " case 'V': start_timer(); printf(\"Generated by %%s\\n\", SpinVersion);", + " to_compile(); pan_exit(2); break;", + " case 'v': verbose++; break;", + " case 'w': ssize = atoi(&argv[1][2]); break;", + " case 'Y': signoff = 1; break;", + " case 'X': efd = stdout; break;", + " case 'x': exclusive = 1; break;", + "#if NCORE>1", + " /* -B ip is passthru to proxy of remote ip address: */", + " case 'B': argc--; argv++; break;", + " case 'Q': worker_pids[0] = atoi(&argv[1][2]); break;", + " /* -Un means that the nth worker should be instantiated as a proxy */", + " case 'U': proxy_pid = atoi(&argv[1][2]); break;", + " /* -W means that this copy is started by a cluster-server as a remote */", + " /* this flag is passed to ./pan_proxy, which interprets it */", + " case 'W': remote_party++; break;", + " case 'Z': core_id = atoi(&argv[1][2]);", + " if (verbose)", + " { printf(\"cpu%%d: pid %%d parent %%d\\n\",", + " core_id, getpid(), worker_pids[0]);", + " }", + " break;", + " case 'z': z_handoff = atoi(&argv[1][2]); break;", + "#else", + " case 'z': break; /* ignored for single-core */", + "#endif", + " default : fprintf(efd, \"saw option -%%c\\n\", argv[1][1]); usage(efd); break;", + " }", + " argc--; argv++;", + " }", + " if (iterative && TMODE != 0666)", + " { TMODE = 0666;", + " fprintf(efd, \"warning: -T ignored when -i or -I is used\\n\");", + " }", + "#if defined(HASH32) && !defined(SFH)", + " if (WS > 4)", + " { fprintf(efd, \"strong warning: compiling -DHASH32 on a 64-bit machine\\n\");", + " fprintf(efd, \" without -DSFH can slow down performance a lot\\n\");", + " }", + "#endif", + "#if defined(WIN32) || defined(WIN64)", + " if (TMODE == 0666)", + " TMODE = _S_IWRITE | _S_IREAD;", + " else", + " TMODE = _S_IREAD;", + "#endif", + "#if NCORE>1", + " store_proxy_pid = proxy_pid; /* for checks in mem_file() and someone_crashed() */", + " if (core_id != 0) { proxy_pid = 0; }", + " #ifndef SEP_STATE", + " if (core_id == 0 && a_cycles)", + " { fprintf(efd, \"hint: this search may be more efficient \");", + " fprintf(efd, \"if pan.c is compiled -DSEP_STATE\\n\");", + " }", + " #endif", + " if (z_handoff < 0)", + " { z_handoff = 20; /* conservative default - for non-liveness checks */", + " }", + "#if defined(NGQ) || defined(LWQ_FIXED)", + " LWQ_SIZE = (double) (128.*1048576.);", + "#else", + " LWQ_SIZE = (double) ( z_handoff + 2.) * (double) sizeof(SM_frame);", + /* the added margin of +2 is not really necessary */ + "#endif", + " #if NCORE>2", + " if (a_cycles)", + " { fprintf(efd, \"warning: the intended nr of cores to be used in liveness mode is 2\\n\");", + " #ifndef SEP_STATE", + " fprintf(efd, \"warning: without -DSEP_STATE there is no guarantee that all liveness violations are found\\n\");", + " #endif", + " }", /* it still works though, the later cores get states from the global q */ + " #endif", + " #ifdef HAS_HIDDEN", + " #error cannot use hidden variables when compiling multi-core", + " #endif", + "#endif", + "#ifdef BITSTATE", + " if (hfns <= 0)", + " { hfns = 1;", + " fprintf(efd, \"warning: using -k%%d as minimal usable value\\n\", hfns);", + " }", + "#endif", + " omaxdepth = maxdepth;", + "#ifdef BITSTATE", + " if (WS == 4 && ssize > 34)", /* 32-bit word size */ + " { ssize = 34;", + " fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);", + "/*", + " * -w35 would not work: 35-3 = 32 but 1^31 is the largest", + " * power of 2 that can be represented in an unsigned long", + " */", + " }", + "#else", + " if (WS == 4 && ssize > 27)", + " { ssize = 27;", + " fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);", + "/*", + " * for emalloc, the lookup table size multiplies by 4 for the pointers", + " * the largest power of 2 that can be represented in a ulong is 1^31", + " * hence the largest number of lookup table slots is 31-4 = 27", + " */", + " }", + + "#endif", + "#ifdef SC", + " hiwater = HHH = maxdepth-10;", + " DDD = HHH/2;", + " if (!stackfile)", + " { stackfile = (char *) emalloc(strlen(PanSource)+4+1);", + " sprintf(stackfile, \"%%s._s_\", PanSource);", + " }", + " if (iterative)", + " { fprintf(efd, \"error: cannot use -i or -I with -DSC\\n\");", + " pan_exit(1);", + " }", + "#endif", + + "#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)", + " #warning -DR_XPT and -DW_XPT assume -DMA (ignored)", + "#endif", + + " if (iterative && a_cycles)", + " fprintf(efd, \"warning: -i or -I work for safety properties only\\n\");", + + "#ifdef BFS", + " #ifdef SC", + " #error -DBFS not compatible with -DSC", + " #endif", + " #ifdef HAS_LAST", + " #error -DBFS not compatible with _last", + " #endif", + " #ifdef HAS_STACK", + " #error cannot use c_track UnMatched with BFS", + " #endif", + " #ifdef BCS", + " #error -DBFS not compatible with -DBCS", + " #endif", + " #ifdef REACH", + " #warning -DREACH is redundant when -DBFS is used", + " #endif", + "#endif", + + "#ifdef TRIX", + " #ifdef BITSTATE", + " #error cannot combine -DTRIX and -DBITSTATE", + " #endif", + " #ifdef COLLAPSE", + " #error cannot combine -DTRIX and -DCOLLAPSE", + " #endif", + " #ifdef MA", + " #error cannot combine -DTRIX and -DMA", + " #endif", + "#endif", + + "#ifdef BCS", + " #ifdef P_RAND", + " #error cannot combine -DBCS and -DP_RAND", + " #endif", + " #ifdef BFS", + " #error cannot combine -DBCS and -DBFS", + " #endif", + "#endif", + + "#if defined(MERGED) && defined(PEG)", + " #error to use -DPEG use: spin -o3 -a", + "#endif", + "#ifdef HC", + " #ifdef SFH", /* cannot happen -- undef-ed in this case */ + " #error cannot combine -DHC and -DSFH", + " /* use of NOCOMP is the real reason */", + " #else", + " #ifdef NOCOMP", + " #error cannot combine -DHC and -DNOCOMP", + " #endif", + " #endif", + " #ifdef BITSTATE", + " #error cannot combine -DHC and -DBITSTATE", + " #endif", + "#endif", + "#if defined(SAFETY) && defined(NP)", + " #error cannot combine -DNP and -DBFS or -DSAFETY", + "#endif", + "#ifdef MA", + " #ifdef BITSTATE", + " #error cannot combine -DMA and -DBITSTATE", + " #endif", + " #if MA <= 0", + " #error usage: -DMA=N with N > 0 and N < VECTORSZ", + " #endif", + "#endif", + "#ifdef COLLAPSE", + " #ifdef BITSTATE", + " #error cannot combine -DBITSTATE and -DCOLLAPSE", + " #endif", + " #ifdef SFH", + " #error cannot combine -DCOLLAPSE and -DSFH", + " /* use of NOCOMP is the real reason */", + " #else", + " #ifdef NOCOMP", + " #error cannot combine -DCOLLAPSE and -DNOCOMP", + " #endif", + " #endif", + "#endif", + " if (maxdepth <= 0 || ssize <= 1) usage(efd);", + "#if SYNC>0 && !defined(NOREDUCE)", + " if (a_cycles && fairness)", + " { fprintf(efd, \"error: p.o. reduction not compatible with \");", + " fprintf(efd, \"fairness (-f) in models\\n\");", + " fprintf(efd, \" with rendezvous operations: \");", + " fprintf(efd, \"recompile with -DNOREDUCE\\n\");", + " pan_exit(1);", + " }", + "#endif", + "#if defined(REM_VARS) && !defined(NOREDUCE)", + " #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)", + "#endif", + "#if defined(NOCOMP) && !defined(BITSTATE)", + " if (a_cycles)", + " { fprintf(efd, \"error: use of -DNOCOMP voids -l and -a\\n\");", + " pan_exit(1);", + " }", + "#endif", + + "#ifdef MEMLIM", + " memlim = ((double) MEMLIM) * (double) (1<<20); /* size in Mbyte */", + "#endif", + + "#ifndef BITSTATE", + " if (Nrun > 1) HASH_NR = Nrun - 1;", + "#endif", + " if (Nrun < 1 || Nrun > 32)", + " { fprintf(efd, \"error: invalid arg for -R\\n\");", + " usage(efd);", + " }", + "#ifndef SAFETY", + " if (fairness && !a_cycles)", + " { fprintf(efd, \"error: -f requires -a or -l\\n\");", + " usage(efd);", + " }", + " #if ACCEPT_LAB==0", + " if (a_cycles)", + " { fprintf(efd, \"error: no accept labels defined \");", + " fprintf(efd, \"in model (for option -a)\\n\");", + " usage(efd);", + " }", + " #endif", + "#endif", + "#ifndef NOREDUCE", + " #ifdef HAS_ENABLED", + " #error use of enabled() requires -DNOREDUCE", + " #endif", + " #ifdef HAS_PCVALUE", + " #error use of pcvalue() requires -DNOREDUCE", + " #endif", + " #ifdef HAS_BADELSE", + " #error use of 'else' combined with i/o stmnts requires -DNOREDUCE", + " #endif", + " #if defined(HAS_LAST) && !defined(BCS)", + " #error use of _last requires -DNOREDUCE", + " #endif", + "#endif", + + "#if SYNC>0 && !defined(NOREDUCE)", + " #ifdef HAS_UNLESS", + " fprintf(efd, \"warning: use of a rendezvous stmnts in the escape\\n\");", + " fprintf(efd, \"\tof an unless clause, if present, could make p.o. reduction\\n\");", + " fprintf(efd, \"\tinvalid (use -DNOREDUCE to avoid this)\\n\");", + " #ifdef BFS", + " fprintf(efd, \"\t(this type of rv is also not compatible with -DBFS)\\n\");", + " #endif", + " #endif", + "#endif", + "#if SYNC>0 && defined(BFS)", + " #warning use of rendezvous with BFS does not preserve all invalid endstates", + "#endif", + "#if !defined(REACH) && !defined(BITSTATE)", + " if (iterative != 0 && a_cycles == 0)", + " { fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");", + " }", + "#endif", + "#if defined(BITSTATE) && defined(REACH)", + " #warning -DREACH is voided by -DBITSTATE", + "#endif", + "#if defined(MA) && defined(REACH)", + " #warning -DREACH is voided by -DMA", + "#endif", + "#if defined(FULLSTACK) && defined(CNTRSTACK)", + " #error cannot combine -DFULLSTACK and -DCNTRSTACK", + "#endif", + "#if defined(VERI)", + " #if ACCEPT_LAB>0", + " #ifndef BFS", + " if (!a_cycles", + " #ifdef HAS_CODE", + " && !readtrail", + " #endif", + " #if NCORE>1", + " && core_id == 0", + " #endif", + " && !state_tables)", + " { fprintf(efd, \"warning: never claim + accept labels \");", + " fprintf(efd, \"requires -a flag to fully verify\\n\");", + " }", + " #else", + " if (!state_tables", + " #ifdef HAS_CODE", + " && !readtrail", + " #endif", + " )", + " { fprintf(efd, \"warning: verification in BFS mode \");", + " fprintf(efd, \"is restricted to safety properties\\n\");", + " }", + " #endif", + " #endif", + "#endif", + "#ifndef SAFETY", + " if (!a_cycles", + " #ifdef HAS_CODE", + " && !readtrail", + " #endif", + " #if NCORE>1", + " && core_id == 0", + " #endif", + " && !state_tables)", + " { fprintf(efd, \"hint: this search is more efficient \");", + " fprintf(efd, \"if pan.c is compiled -DSAFETY\\n\");", + " }", + " #ifndef NOCOMP", + " if (!a_cycles)", + " { S_A = 0;", + " } else", + " { if (!fairness)", + " { S_A = 1; /* _a_t */", + " #ifndef NOFAIR", + " } else /* _a_t and _cnt[NFAIR] */", + " { S_A = (&(now._cnt[0]) - (uchar *) &now) + NFAIR - 2;", + " /* -2 because first two uchars in now are masked */", + " #endif", + " } }", + " #endif", + "#endif", + " signal(SIGINT, stopped);", + " set_masks();", "#ifdef BFS", " trail = (Trail *) emalloc(6*sizeof(Trail));", " trail += 3;", @@ -3570,14 +5105,14 @@ "#ifdef SVDUMP", " if (vprefix > 0)", " { char nm[64];", - " sprintf(nm, \"%%s.svd\", Source);", - " if ((svfd = creat(nm, 0666)) < 0)", + " sprintf(nm, \"%%s.svd\", PanSource);", + " if ((svfd = creat(nm, TMODE)) < 0)", " { fprintf(efd, \"couldn't create %%s\\n\", nm);", " vprefix = 0;", " } }", "#endif", "#ifdef RANDSTOR", - " srand(123);", + " srand(s_rand);", "#endif", "#if SYNC>0 && ASYNC==0", " set_recvs();", @@ -3591,6 +5126,7 @@ "void", "usage(FILE *fd)", "{", + " fprintf(fd, \"%%s\\n\", SpinVersion);", " fprintf(fd, \"Valid Options are:\\n\");", "#ifndef SAFETY", "#ifdef NP", @@ -3606,6 +5142,7 @@ " fprintf(fd, \"\t-b consider it an error to exceed the depth-limit\\n\");", " fprintf(fd, \"\t-cN stop at Nth error \");", " fprintf(fd, \"(defaults to -c1)\\n\");", + " fprintf(fd, \"\t-D print state tables in dot-format and stop\\n\");", " fprintf(fd, \"\t-d print state tables and stop\\n\");", " fprintf(fd, \"\t-e create trails for all errors\\n\");", " fprintf(fd, \"\t-E ignore invalid end states\\n\");", @@ -3622,6 +5159,9 @@ "#ifdef BITSTATE", " fprintf(fd, \"\t-kN set N bits per state (defaults to 3)\\n\");", "#endif", + "#ifdef BCS", + " fprintf(fd, \"\t-LN set scheduling restriction to N (default 0)\\n\");", + "#endif", "#ifndef SAFETY", "#ifdef NP", " fprintf(fd, \"\t-l find non-progress cycles\\n\");", @@ -3631,17 +5171,20 @@ " fprintf(fd, \"compilation with -DNP\\n\");", "#endif", "#endif", -#ifndef POWOW "#ifdef BITSTATE", " fprintf(fd, \"\t-MN use N Megabytes for bitstate hash array\\n\");", " fprintf(fd, \"\t-GN use N Gigabytes for bitstate hash array\\n\");", "#endif", -#endif " fprintf(fd, \"\t-mN max depth N steps (default=10k)\\n\");", + "#if NCLAIMS>1", + " fprintf(fd, \"\t-N cn -- use the claim named cn\\n\");", + " fprintf(fd, \"\t-Nn -- use claim number n\\n\");", + "#endif", " fprintf(fd, \"\t-n no listing of unreached states\\n\");", "#ifdef SVDUMP", " fprintf(fd, \"\t-pN create svfile (save N bytes per state)\\n\");", "#endif", + " fprintf(fd, \"\t-QN set time-limit on execution of N minutes\\n\");", " fprintf(fd, \"\t-q require empty chans in valid end states\\n\");", "#ifdef HAS_CODE", " fprintf(fd, \"\t-r read and execute trail - can add -v,-n,-PN,-g,-C\\n\");", @@ -3651,6 +5194,9 @@ " fprintf(fd, \"\t-g read and execute trail + msc gui support\\n\");", " fprintf(fd, \"\t-S silent replay: only user defined printfs show\\n\");", "#endif", + "#if defined(T_RAND) || defined(P_RAND) || defined(RANDSTOR)", + " fprintf(fd, \"\t-RSN use randomization seed N\\n\");", + "#endif", "#ifdef BITSTATE", " fprintf(fd, \"\t-RN repeat run Nx with N \");", " fprintf(fd, \"[1..32] independent hash functions\\n\");", @@ -3662,38 +5208,37 @@ " fprintf(fd, \"\t-v verbose -- filenames in unreached state listing\\n\");", " fprintf(fd, \"\t-wN hashtable of 2^N entries \");", " fprintf(fd, \"(defaults to -w%%d)\\n\", ssize);", + " fprintf(fd, \"\t-x do not overwrite an existing trail file\\n\");", + "#if NCORE>1", + " fprintf(fd, \"\t-zN handoff states below depth N to 2nd cpu (multi_core)\\n\");", + "#endif", + "#ifdef HAS_CODE", + " fprintf(fd, \"\\n\toptions -r, -C, -PN, -g, and -S can optionally be followed by\\n\");", + " fprintf(fd, \"\ta filename argument, as in \'-r filename\', naming the trailfile\\n\");", + "#endif", + "#if NCORE>1", + " multi_usage(fd);", + "#endif", " exit(1);", "}", "", "char *", "Malloc(unsigned long n)", "{ char *tmp;", - "#if defined(MEMCNT) || defined(MEMLIM)", - " if (memcnt+ (double) n > memlim) goto err;", - "#endif", -"#if 1", + "#ifdef MEMLIM", + " if (memcnt + (double) n > memlim)", + " { printf(\"pan: reached -DMEMLIM bound\\n\");", + " goto err;", + " }", + "#endif", " tmp = (char *) malloc(n);", " if (!tmp)", -"#else", - /* on linux machines, a large amount of memory is set aside - * for malloc, whether it is used or not - * using sbrk would make this memory arena inaccessible - * the reason for using sbrk was originally to provide a - * small additional speedup (since this memory is never released) - */ - " tmp = (char *) sbrk(n);", - " if (tmp == (char *) -1L)", -"#endif", - " {", - "#if defined(MEMCNT) || defined(MEMLIM)", + " { printf(\"pan: out of memory\\n\");", + "#ifdef MEMLIM", "err:", - "#endif", - " printf(\"pan: out of memory\\n\");", - "#if defined(MEMCNT) || defined(MEMLIM)", " printf(\"\t%%g bytes used\\n\", memcnt);", " printf(\"\t%%g bytes more needed\\n\", (double) n);", - " printf(\"\t%%g bytes limit\\n\",", - " memlim);", + " printf(\"\t%%g bytes limit\\n\", memlim);", "#endif", "#ifdef COLLAPSE", " printf(\"hint: to reduce memory, recompile with\\n\");", @@ -3714,6 +5259,15 @@ " printf(\" -DBITSTATE # supertrace, approximation\\n\");", "#endif", "#endif", + "#if NCORE>1", + " #ifdef FULL_TRAIL", + " printf(\" omit -DFULL_TRAIL or use pan -c0 to reduce memory\\n\");", + " #endif", + " #ifdef SEP_STATE", + " printf(\"hint: to reduce memory, recompile without\\n\");", + " printf(\" -DSEP_STATE # may be faster, but uses more memory\\n\");", + " #endif", + "#endif", " wrapup();", " }", " memcnt += (double) n;", @@ -3757,6 +5311,9 @@ "Uerror(char *str)", "{ /* always fatal */", " uerror(str);", + "#if NCORE>1", + " sudden_stop(\"Uerror\");", + "#endif", " wrapup();", "}\n", "#if defined(MA) && !defined(SAFETY)", @@ -3820,7 +5377,7 @@ " tt = trpt->o_tt; this = pptr(II);", " _m = do_reverse(t, II, trpt->o_m);", "#ifdef VERBOSE", - " printf(\"%%3d: proc %%d \", depth, II);", + " printf(\"%%3ld: proc %%d \", depth, II);", " printf(\"reverses %%d, %%d to %%d,\",", " t->forw, tt, t->st);", " printf(\" %%s [abit=%%d,adepth=%%d,\", ", @@ -3868,8 +5425,15 @@ "", " if (unwinding) return; /* 1.4.2 */", " if (strncmp(str, laststr, 254))", - " printf(\"pan: %%s (at depth %%ld)\\n\", str,", - " (depthfound==-1)?depth:depthfound);", + "#if NCORE>1", + " cpu_printf(\"pan:%%d: %%s (at depth %%ld)\\n\", errors+1, str,", + "#else", + " printf(\"pan:%%d: %%s (at depth %%ld)\\n\", errors+1, str,", + "#endif", + "#if NCORE>1", + " (nr_handoffs * z_handoff) + ", + "#endif", + " ((depthfound==-1)?depth:depthfound));", " strncpy(laststr, str, 254);", " errors++;", "#ifdef HAS_CODE", @@ -3891,13 +5455,16 @@ " depth = od;", " }", "#endif", -"#ifdef BFS", + "#if NCORE>1", + " writing_trail = 1;", + "#endif", + "#ifdef BFS", " if (depth > 1) trpt--;", " nuerror(str);", " if (depth > 1) trpt++;", -"#else", + "#else", " putrail();", -"#endif", + "#endif", "#if defined(MA) && !defined(SAFETY)", " if (strstr(str, \" cycle\"))", " { if (every_error)", @@ -3905,20 +5472,33 @@ " wrapup(); /* no recovery from unwind */", " }", "#endif", + "#if NCORE>1", + " if (search_terminated != NULL)", + " { *search_terminated |= 4; /* uerror */", + " }", + " writing_trail = 0;", + "#endif", " }", " if (!is_cycle)", " { depth--; trpt--; /* undo */", " }", -"#ifndef BFS", + "#ifndef BFS", " if (iterative != 0 && maxdepth > 0)", - " { maxdepth = (iterative == 1)?(depth-1):(depth/2);", + " { if (maxdepth > depth)", + " { maxdepth = (iterative == 1)?(depth+1):(depth/2);", + " }", " warned = 1;", " printf(\"pan: reducing search depth to %%ld\\n\",", " maxdepth);", " } else", -"#endif", + "#endif", " if (errors >= upto && upto != 0)", + " {", + "#if NCORE>1", + " sudden_stop(\"uerror\");", + "#endif", " wrapup();", + " }", " depthfound = -1;", "}\n", "int", @@ -3930,13 +5510,14 @@ " || strncmp(T->tp, \"goto :\", 6) == 0)", " return 1; /* not reported */", "", - " printf(\"\\tline %%d\", lno);", - " if (verbose)", " for (j = 0; j < sizeof(mp); j++)", " if (i >= mp[j].from && i <= mp[j].upto)", - " { printf(\", \\\"%%s\\\"\", mp[j].fnm);", + " { printf(\"\\t%%s:%%d\", mp[j].fnm, lno);", " break;", " }", + " if (j >= sizeof(mp)) /* fnm not found in list */", + " { printf(\"\\t%%s:%%d\", PanSource, lno); /* use default */", + " }", " printf(\", state %%d\", i);", " if (strcmp(T->tp, \"\") != 0)", " { char *q;", @@ -3951,45 +5532,107 @@ "}\n", "void", "r_ck(uchar *which, int N, int M, short *src, S_F_MAP *mp)", - "{ int i, m=0;\n", - "#ifdef VERI", - " if (M == VERI && !verbose) return;", - "#endif", - " printf(\"unreached in proctype %%s\\n\", procname[M]);", + "{ int i, m=0;", + "", + " if ((enum btypes) Btypes[M] == N_CLAIM", + " && claimname != NULL && strcmp(claimname, procname[M]) != 0)", + " { return;", + " }", + "", + " switch ((enum btypes) Btypes[M]) {", + " case P_PROC:", + " case A_PROC:", + " printf(\"unreached in proctype %%s\\n\", procname[M]);", + " break;", + " case I_PROC:", + " printf(\"unreached in init\\n\");", + " break;", + " case E_TRACE:", + " case N_TRACE:", + " case N_CLAIM:", + " default:", + " printf(\"unreached in claim %%s\\n\", procname[M]);", + " break;", + " }", " for (i = 1; i < N; i++)", -#if 0 - " if (which[i] == 0 /* && trans[M][i] */)", -#else - " if (which[i] == 0", - " && (mapstate[M][i] == 0", - " || which[mapstate[M][i]] == 0))", -#endif - " m += xrefsrc((int) src[i], mp, M, i);", - " else", - " m++;", + " { if (which[i] == 0", + " && (mapstate[M][i] == 0", + " || which[mapstate[M][i]] == 0))", + " { m += xrefsrc((int) src[i], mp, M, i);", + " } else", + " { m++;", + " } }", " printf(\"\t(%%d of %%d states)\\n\", N-1-m, N-1);", - "}\n", + "}", + "#if NCORE>1 && !defined(SEP_STATE)", + "static long rev_trail_cnt;", + "", + "#ifdef FULL_TRAIL", + "void", + "rev_trail(int fd, volatile Stack_Tree *st_tr)", + "{ long j; char snap[64];", + "", + " if (!st_tr)", + " { return;", + " }", + " rev_trail(fd, st_tr->prv);", + "#ifdef VERBOSE", + " printf(\"%%d (%%d) LRT [%%d,%%d] -- %%9u (root %%9u)\\n\",", + " depth, rev_trail_cnt, st_tr->pr, st_tr->t_id, st_tr, stack_last[core_id]);", + "#endif", + " if (st_tr->pr != 255)", /* still needed? */ + " { sprintf(snap, \"%%ld:%%d:%%d\\n\", ", + " rev_trail_cnt++, st_tr->pr, st_tr->t_id);", + " j = strlen(snap);", + " if (write(fd, snap, j) != j)", + " { printf(\"pan: error writing trailfile\\n\");", + " close(fd);", + " wrapup();", + " return;", + " }", + " } else /* handoff point */", + " { if (a_cycles)", + " { (void) write(fd, \"-1:-1:-1\\n\", 9);", + " } }", + "}", + "#endif", /* FULL_TRAIL */ + "#endif", /* NCORE>1 */ + "", "void", "putrail(void)", - "{ int fd; long i, j;", - " Trail *trl;", + "{ int fd;", "#if defined VERI || defined(MERGED)", " char snap[64];", "#endif", - "", + "#if NCORE==1 || defined(SEP_STATE) || !defined(FULL_TRAIL)", + " long i, j;", + " Trail *trl;", + "#endif", " fd = make_trail();", " if (fd < 0) return;", "#ifdef VERI", - " sprintf(snap, \"-2:%%d:-2\\n\", VERI);", - " write(fd, snap, strlen(snap));", + " sprintf(snap, \"-2:%%d:-2\\n\", (uchar) ((P0 *)pptr(0))->_t);", + " if (write(fd, snap, strlen(snap)) < 0) return;", "#endif", "#ifdef MERGED", " sprintf(snap, \"-4:-4:-4\\n\");", - " write(fd, snap, strlen(snap));", - "#endif", - " for (i = 1; i <= depth; i++)", + " if (write(fd, snap, strlen(snap)) < 0) return;", + "#endif", + "#if NCORE>1 && !defined(SEP_STATE) && defined(FULL_TRAIL)", + " rev_trail_cnt = 1;", + " enter_critical(GLOBAL_LOCK);", + " rev_trail(fd, stack_last[core_id]);", + " leave_critical(GLOBAL_LOCK);", + "#else", + " i = 1; /* trail starts at position 1 */", + " #if NCORE>1 && defined(SEP_STATE)", + " if (cur_Root.m_vsize > 0) { i++; depth++; }", + " #endif", + " for ( ; i <= depth; i++)", " { if (i == depthfound+1)", - " write(fd, \"-1:-1:-1\\n\", 9);", + " { if (write(fd, \"-1:-1:-1\\n\", 9) != 9)", + " { goto notgood;", + " } }", " trl = getframe(i);", " if (!trl->o_t) continue;", " if (trl->o_pm&128) continue;", @@ -3997,12 +5640,16 @@ " i, trl->pr, trl->o_t->t_id);", " j = strlen(snap);", " if (write(fd, snap, j) != j)", - " { printf(\"pan: error writing trailfile\\n\");", + " {", + "notgood: printf(\"pan: error writing trailfile\\n\");", " close(fd);", " wrapup();", - " }", - " }", + " } }", + "#endif", " close(fd);", + "#if NCORE>1", + " cpu_printf(\"pan: wrote trailfile\\n\");", + "#endif", "}\n", "void", "sv_save(void) /* push state vector onto save stack */", @@ -4022,13 +5669,16 @@ "#if SYNC", " svtack->o_boq = boq;", "#endif", + "#ifdef TRIX", + " sv_populate();", + "#endif", " svtack->o_delta = vsize; /* don't compress */", " memcpy((char *)(svtack->body), (char *) &now, vsize);", "#if defined(C_States) && defined(HAS_STACK) && (HAS_TRACK==1)", " c_stack((uchar *) &(svtack->c_stack[0]));", "#endif", "#ifdef DEBUG", - " printf(\"%%d: sv_save\\n\", depth);", + " cpu_printf(\"%%d: sv_save\\n\", depth);", "#endif", "}\n", "void", @@ -4038,7 +5688,9 @@ "#if SYNC", " boq = svtack->o_boq;", "#endif", - + "#ifdef TRIX", + " re_populate();", + "#endif", "#if defined(C_States) && (HAS_TRACK==1)", "#ifdef HAS_STACK", " c_unstack((uchar *) &(svtack->c_stack[0]));", @@ -4049,78 +5701,130 @@ " if (vsize != svtack->o_delta)", " Uerror(\"sv_restor\");", " if (!svtack->lst)", - " Uerror(\"error: v_restor\");", + " Uerror(\"error: sv_restor\");", " svtack = svtack->lst;", "#ifdef DEBUG", - " printf(\" sv_restor\\n\");", + " cpu_printf(\" sv_restor\\n\");", "#endif", "}\n", "void", "p_restor(int h)", - "{ int i; char *z = (char *) &now;\n", + "{ int i;", + " char *z = (char *) &now;\n", + "#ifndef TRIX", " proc_offset[h] = stack->o_offset;", " proc_skip[h] = (uchar) stack->o_skip;", + "#else", + " char *oi;", + " #ifdef V_TRIX", + " printf(\"%%4d: p_restor %%d\\n\", depth, h);", + " #endif", + "#endif", "#ifndef XUSAFE", " p_name[h] = stack->o_name;", "#endif", - "#ifndef NOCOMP", + "#ifdef TRIX", + " vsize += sizeof(char *);", + " #ifndef BFS", + " if (processes[h] != NULL || freebodies == NULL)", + " { Uerror(\"processes error\");", + " }", + " processes[h] = freebodies;", + " freebodies = freebodies->nxt;", + " processes[h]->nxt = (TRIX_v6 *) 0;", + " processes[h]->modified = 1; /* p_restor */", + " #endif", + " processes[h]->parent_pid = stack->parent;", + " processes[h]->psize = stack->o_delta;", + " memcpy((char *)pptr(h), stack->b_ptr, stack->o_delta);", + " oi = stack->b_ptr;", + "#else", + " #ifndef NOCOMP", " for (i = vsize + stack->o_skip; i > vsize; i--)", " Mask[i-1] = 1; /* align */", - "#endif", + " #endif", " vsize += stack->o_skip;", " memcpy(z+vsize, stack->body, stack->o_delta);", " vsize += stack->o_delta;", - "#ifndef NOVSZ", - " now._vsz = vsize;", - "#endif", - "#ifndef NOCOMP", - " for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)", - " Mask[vsize - i] = 1; /* pad */", - " Mask[proc_offset[h]] = 1; /* _pid */", - "#endif", + " #ifndef NOCOMP", + " for (i = 1; i <= Air[((P0 *)pptr(h))->_t]; i++)", + " Mask[vsize - i] = 1; /* pad */", + " Mask[proc_offset[h]] = 1; /* _pid */", + " #endif", " if (BASE > 0 && h > 0)", " ((P0 *)pptr(h))->_pid = h-BASE;", " else", " ((P0 *)pptr(h))->_pid = h;", + "#endif", + " now._nr_pr += 1;", + "#ifndef NOVSZ", + " now._vsz = vsize;", + "#endif", " i = stack->o_delqs;", - " now._nr_pr += 1;", - " if (!stack->lst) /* debugging */", + " if (!stack->lst)", " Uerror(\"error: p_restor\");", " stack = stack->lst;", " this = pptr(h);", " while (i-- > 0)", " q_restor();", + "#ifdef TRIX", + " re_mark_all(1); /* p_restor - all chans move up in _ids_ */", + " now._ids_[h] = oi; /* restor the original contents */", + "#endif", "}\n", "void", "q_restor(void)", - "{ char *z = (char *) &now;", - "#ifndef NOCOMP", - " int k, k_end;", - "#endif", - " q_offset[now._nr_qs] = stack->o_offset;", - " q_skip[now._nr_qs] = (uchar) stack->o_skip;", - "#ifndef XUSAFE", - " q_name[now._nr_qs] = stack->o_name;", - "#endif", + "{ int h = now._nr_qs;", + "#ifdef TRIX", + " #ifdef V_TRIX", + " printf(\"%%4d: q_restor %%d\\n\", depth, h);", + " #endif", + " vsize += sizeof(char *);", + " #ifndef BFS", + " if (channels[h] != NULL || freebodies == NULL)", + " { Uerror(\"channels error\");", + " }", + " channels[h] = freebodies;", + " freebodies = freebodies->nxt;", + " channels[h]->nxt = (TRIX_v6 *) 0;", + " channels[h]->modified = 1; /* q_restor */", + " #endif", + " channels[h]->parent_pid = stack->parent;", + " channels[h]->psize = stack->o_delta;", + " memcpy((char *)qptr(h), stack->b_ptr, stack->o_delta);", + " now._ids_[now._nr_pr + h] = stack->b_ptr;", + "#else", + " char *z = (char *) &now;", + " #ifndef NOCOMP", + " int k, k_end;", + " #endif", + " q_offset[h] = stack->o_offset;", + " q_skip[h] = (uchar) stack->o_skip;", " vsize += stack->o_skip;", " memcpy(z+vsize, stack->body, stack->o_delta);", " vsize += stack->o_delta;", + "#endif", + "#ifndef XUSAFE", + " q_name[h] = stack->o_name;", + "#endif", "#ifndef NOVSZ", " now._vsz = vsize;", "#endif", " now._nr_qs += 1;", "#ifndef NOCOMP", + "#ifndef TRIX", " k_end = stack->o_offset;", " k = k_end - stack->o_skip;", - "#if SYNC", - "#ifndef BFS", - " if (q_zero(now._nr_qs)) k_end += stack->o_delta;", - "#endif", - "#endif", + " #if SYNC", + " #ifndef BFS", + " if (q_zero(now._nr_qs)) k_end += stack->o_delta;", + " #endif", + " #endif", " for ( ; k < k_end; k++)", " Mask[k] = 1;", "#endif", - " if (!stack->lst) /* debugging */", + "#endif", + " if (!stack->lst)", " Uerror(\"error: q_restor\");", " stack = stack->lst;", "}", @@ -4163,7 +5867,46 @@ "#ifndef NOCOMP", " int o_vsize = vsize;", "#endif", - " if (h+1 != (int) now._nr_pr) return 0;\n", + " if (h+1 != (int) now._nr_pr)", + " { return 0;", + " }", + "#ifdef TRIX", + " #ifdef V_TRIX", + " printf(\"%%4d: delproc %%d -- parent %%d\\n\", depth, h, processes[h]->parent_pid);", + " if (now._nr_qs > 0)", + " printf(\" top channel: %%d -- parent %%d\\n\", now._nr_qs-1, channels[now._nr_qs-1]->parent_pid);", + " #endif", + " while (now._nr_qs > 0", + " && channels[now._nr_qs-1]->parent_pid == processes[h]->parent_pid)", + " { delq(sav);", + " i++;", + " }", + " d = processes[h]->psize;", + " if (sav)", + " { if (!stack->nxt)", + " { stack->nxt = (_Stack *) emalloc(sizeof(_Stack));", + " stack->nxt->lst = stack;", + " smax++;", + " }", + " stack = stack->nxt;", + " #ifndef XUSAFE", + " stack->o_name = p_name[h];", + " #endif", + " stack->parent = processes[h]->parent_pid;", + " stack->o_delta = d;", + " stack->o_delqs = i;", + " stack->b_ptr = now._ids_[h];", /* new 6.1 */ + " }", + " memset((char *)pptr(h), 0, d);", + " #ifndef BFS", + " processes[h]->nxt = freebodies;", + " freebodies = processes[h];", + " processes[h] = (TRIX_v6 *) 0;", + " #endif", + " vsize -= sizeof(char *);", + " now._nr_pr -= 1;", + " re_mark_all(-1); /* delproc - all chans move down in _ids_ */", + "#else", " while (now._nr_qs", " && q_offset[now._nr_qs-1] > proc_offset[h])", " { delq(sav);", @@ -4172,80 +5915,104 @@ " d = vsize - proc_offset[h];", " if (sav)", " { if (!stack->nxt)", - " { stack->nxt = (Stack *)", - " emalloc(sizeof(Stack));", - " stack->nxt->body = ", - " emalloc(Maxbody*sizeof(char));", + " { stack->nxt = (_Stack *) emalloc(sizeof(_Stack));", + " stack->nxt->body = emalloc(Maxbody * sizeof(char));", " stack->nxt->lst = stack;", " smax++;", " }", " stack = stack->nxt;", " stack->o_offset = proc_offset[h];", - "#if VECTORSZ>32000", + " #if VECTORSZ>32000", " stack->o_skip = (int) proc_skip[h];", - "#else", + " #else", " stack->o_skip = (short) proc_skip[h];", - "#endif", - "#ifndef XUSAFE", + " #endif", + " #ifndef XUSAFE", " stack->o_name = p_name[h];", - "#endif", + " #endif", " stack->o_delta = d;", " stack->o_delqs = i;", " memcpy(stack->body, (char *)pptr(h), d);", " }", " vsize = proc_offset[h];", - " now._nr_pr = now._nr_pr - 1;", + " now._nr_pr -= 1;", " memset((char *)pptr(h), 0, d);", " vsize -= (int) proc_skip[h];", + " #ifndef NOCOMP", + " for (i = vsize; i < o_vsize; i++)", + " Mask[i] = 0; /* reset */", + " #endif", + "#endif", "#ifndef NOVSZ", " now._vsz = vsize;", "#endif", - "#ifndef NOCOMP", - " for (i = vsize; i < o_vsize; i++)", - " Mask[i] = 0; /* reset */", - "#endif", " return 1;", "}\n", "void", "delq(int sav)", "{ int h = now._nr_qs - 1;", + "#ifdef TRIX", + " int d = channels[now._nr_qs - 1]->psize;", + "#else", " int d = vsize - q_offset[now._nr_qs - 1];", + "#endif", "#ifndef NOCOMP", " int k, o_vsize = vsize;", "#endif", " if (sav)", " { if (!stack->nxt)", - " { stack->nxt = (Stack *)", - " emalloc(sizeof(Stack));", - " stack->nxt->body = ", - " emalloc(Maxbody*sizeof(char));", + " { stack->nxt = (_Stack *) emalloc(sizeof(_Stack));", + "#ifndef TRIX", + " stack->nxt->body = emalloc(Maxbody * sizeof(char));", + "#endif", " stack->nxt->lst = stack;", " smax++;", " }", " stack = stack->nxt;", + "#ifdef TRIX", + " stack->parent = channels[h]->parent_pid;", + " stack->b_ptr = now._ids_[h];", /* new 6.1 */ + "#else", " stack->o_offset = q_offset[h];", - "#if VECTORSZ>32000", + " #if VECTORSZ>32000", " stack->o_skip = (int) q_skip[h];", + " #else", + " stack->o_skip = (short) q_skip[h];", + " #endif", + "#endif", + " #ifndef XUSAFE", + " stack->o_name = q_name[h];", + " #endif", + " stack->o_delta = d;", + "#ifndef TRIX", + " memcpy(stack->body, (char *)qptr(h), d);", + "#endif", + " }", + "#ifdef TRIX", + " vsize -= sizeof(char *);", + " #ifdef V_TRIX", + " printf(\"%%4d: delq %%d parent %%d\\n\", depth, h, channels[h]->parent_pid);", + " #endif", "#else", - " stack->o_skip = (short) q_skip[h];", - "#endif", - "#ifndef XUSAFE", - " stack->o_name = q_name[h];", - "#endif", - " stack->o_delta = d;", - " memcpy(stack->body, (char *)qptr(h), d);", - " }", " vsize = q_offset[h];", - " now._nr_qs = now._nr_qs - 1;", + " vsize -= (int) q_skip[h];", + " #ifndef NOCOMP", + " for (k = vsize; k < o_vsize; k++)", + " Mask[k] = 0; /* reset */", + " #endif", + "#endif", + " now._nr_qs -= 1;", " memset((char *)qptr(h), 0, d);", - " vsize -= (int) q_skip[h];", + "#ifdef TRIX", + " #ifndef BFS", + " channels[h]->nxt = freebodies;", + " freebodies = channels[h];", + " channels[h] = (TRIX_v6 *) 0;", + " #endif", + "#endif", "#ifndef NOVSZ", " now._vsz = vsize;", "#endif", - "#ifndef NOCOMP", - " for (k = vsize; k < o_vsize; k++)", - " Mask[k] = 0; /* reset */", - "#endif", "}\n", "int", "qs_empty(void)", @@ -4297,31 +6064,29 @@ " /* for (i = 0; i < n; i++) printf(\"%%d,\", v[i]); */", " printf(\"\\n\");", " }", - " printf(\"%%d: cycle check starts\\n\", depth);", + " printf(\"%%ld: cycle check starts\\n\", depth);", "#endif", " now._a_t |= (1|16|32);", " /* 1 = 2nd DFS; (16|32) to help hasher */", - "#ifndef NOFAIR", -#if 0 - " if (fairness)", - " { now._a_t &= ~2; /* pre-apply Rule 3 */", - " now._cnt[1] = 0;", /* reset both a-bit and cnt=0 */ - " /* avoid matching seed on claim stutter on this state */", - " }", -#else + "#ifndef NOFAIR", " now._cnt[1] = now._cnt[0];", -#endif - "#endif", + "#endif", " memcpy((char *)&A_Root, (char *)&now, vsize);", " A_depth = depthfound = depth;", + + "#if NCORE>1", + " mem_put_acc();", /* handoff accept states */ + "#else", " new_state(); /* start 2nd DFS */", + "#endif", + " now._a_t = o_a_t;", "#ifndef NOFAIR", " now._cnt[1] = o_cnt;", "#endif", " A_depth = 0; depthfound = -1;", "#ifdef DEBUG", - " printf(\"%%d: cycle check returns\\n\", depth);", + " printf(\"%%ld: cycle check returns\\n\", depth);", "#endif", "#ifdef FULLSTACK", "#ifndef MA", @@ -4367,8 +6132,39 @@ " emalloc(sizeof(struct H_el)+n-sizeof(unsigned));", "}\n", "#else", - "#define grab_state(n) (struct H_el *) \\", - " emalloc(sizeof(struct H_el)+n-sizeof(unsigned));", + + "#if NCORE>1", + "struct H_el *", + "grab_state(int n)", + "{ struct H_el *grab_shared(int);", + " return grab_shared(sizeof(struct H_el)+n-sizeof(unsigned));", + "}", + "#else", + " #ifndef AUTO_RESIZE", + " #define grab_state(n) (struct H_el *) \\", + " emalloc(sizeof(struct H_el)+n-sizeof(unsigned long));", + " #else", + " struct H_el *", + " grab_state(int n)", + " { struct H_el *p;", + " int cnt = sizeof(struct H_el)+n-sizeof(unsigned long);", + "", + " if (reclaim_size >= cnt+WS)", + " { if ((cnt & (WS-1)) != 0) /* alignment */", + " { cnt += WS - (cnt & (WS-1));", + " }", + " p = (struct H_el *) reclaim_mem;", + " reclaim_mem += cnt;", + " reclaim_size -= cnt;", + " memset(p, 0, cnt);", + " } else", + " { p = (struct H_el *) emalloc(cnt);", + " }", + " return p;", + " }", + " #endif", + "#endif", + "#endif", "#ifdef COLLAPSE", "unsigned long", @@ -4376,15 +6172,18 @@ "{ struct H_el *tmp, *ntmp; long m;", " struct H_el *olst = (struct H_el *) 0;", " s_hash((uchar *)v, n);", - " tmp = H_tab[j1];", + + "#if NCORE>1 && !defined(SEP_STATE)", + " enter_critical(CS_ID); /* uses spinlock - 1..128 */", + "#endif", + " tmp = H_tab[j1_spin];", " if (!tmp)", " { tmp = grab_state(n);", - " H_tab[j1] = tmp;", + " H_tab[j1_spin] = tmp;", " } else", " for ( ;; olst = tmp, tmp = tmp->nxt)", - " { m = memcmp(((char *)&(tmp->state)), v, n);", - " if (n == tmp->ln)", - " {", + " { if (n == tmp->ln)", + " { m = memcmp(((char *)&(tmp->state)), v, n);", " if (m == 0)", " goto done;", " if (m < 0)", @@ -4392,7 +6191,7 @@ "Insert: ntmp = grab_state(n);", " ntmp->nxt = tmp;", " if (!olst)", - " H_tab[j1] = ntmp;", + " H_tab[j1_spin] = ntmp;", " else", " olst->nxt = ntmp;", " tmp = ntmp;", @@ -4410,15 +6209,29 @@ " else if (!tmp->nxt)", " goto Append;", " }", + "#if NCORE>1 && !defined(SEP_STATE)", + " enter_critical(GLOBAL_LOCK);", + "#endif", " m = ++ncomps[tp];", + "#if NCORE>1 && !defined(SEP_STATE)", + " leave_critical(GLOBAL_LOCK);", + "#endif", "#ifdef FULLSTACK", " tmp->tagged = m;", "#else", " tmp->st_id = m;", "#endif", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE)", + " tmp->m_K1 = K1;", + "#endif", " memcpy(((char *)&(tmp->state)), v, n);", " tmp->ln = n;", "done:", + + "#if NCORE>1 && !defined(SEP_STATE)", + " leave_critical(CS_ID); /* uses spinlock */", + "#endif", + "#ifdef FULLSTACK", " return tmp->tagged;", "#else", @@ -4600,11 +6413,58 @@ " char *vv = vin;", " char *v = (char *) &comp_now;", " int i;", - " for (i = 0; i < n; i++, vv++)", - " if (!Mask[i]) *v++ = *vv;", - " for (i = 0; i < WS-1; i++)", - " *v++ = 0;", - " v -= i;", + " #ifndef NO_FAST_C", /* disable faster compress */ + " int r = 0, unroll = n/8;", /* most sv are much longer */ + " if (unroll > 0)", + " { i = 0;", + " while (r++ < unroll)", + " { /* unroll 8 times, avoid ifs */", + " /* 1 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 2 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 3 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 4 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 5 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 6 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 7 */ *v = *vv++; v += 1 - Mask[i++];", + " /* 8 */ *v = *vv++; v += 1 - Mask[i++];", + " }", + " r = n - i; /* the rest, at most 7 */", + " switch (r) {", + " case 7: *v = *vv++; v += 1 - Mask[i++];", + " case 6: *v = *vv++; v += 1 - Mask[i++];", + " case 5: *v = *vv++; v += 1 - Mask[i++];", + " case 4: *v = *vv++; v += 1 - Mask[i++];", + " case 3: *v = *vv++; v += 1 - Mask[i++];", + " case 2: *v = *vv++; v += 1 - Mask[i++];", + " case 1: *v = *vv++; v += 1 - Mask[i++];", + " case 0: break;", + " }", + "#if 1", + " n = i = v - (char *)&comp_now; /* bytes written so far */", + "#endif", + " r = (n+WS-1)/WS; /* in words, rounded up */", + " r *= WS; /* total bytes to fill */", + " i = r - i; /* remaining bytes */", + " switch (i) {", /* fill word */ + " case 7: *v++ = 0; /* fall thru */", + " case 6: *v++ = 0;", + " case 5: *v++ = 0;", + " case 4: *v++ = 0;", + " case 3: *v++ = 0;", + " case 2: *v++ = 0;", + " case 1: *v++ = 0;", + " case 0: break;", + " default: Uerror(\"unexpected wordsize\");", + " }", + " v -= i;", + " } else", + " #endif", + " { for (i = 0; i < n; i++, vv++)", + " if (!Mask[i]) *v++ = *vv;", + " for (i = 0; i < WS-1; i++)", + " *v++ = 0;", + " v -= i;", + " }", "#if 0", " printf(\"compress %%d -> %%d\\n\",", " n, v - (char *)&comp_now);", @@ -4630,7 +6490,13 @@ "onstack_zap(void)", "{ struct H_el *v, *w, *last = 0;", " struct H_el **tmp = H_tab;", - " char *nv; int n, m;\n", + " char *nv; int n, m;", + " static char warned = 0;", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " uchar was_last = now._last;", + " now._last = 0;", + "#endif", + "", " H_tab = S_Tab;", "#ifndef NOCOMP", " nv = (char *) &comp_now;", @@ -4648,7 +6514,7 @@ " s_hash((uchar *)nv, n);", "#endif", " H_tab = tmp;", - " for (v = S_Tab[j1]; v; Zh++, last=v, v=v->nxt)", + " for (v = S_Tab[j1_spin]; v; Zh++, last=v, v=v->nxt)", " { m = memcmp(&(v->state), nv, n);", " if (m == 0)", " goto Found;", @@ -4656,14 +6522,21 @@ " break;", " }", "/* NotFound: */", - " Uerror(\"stack out of wack - zap\");", - " return;", + "#ifndef ZAPH", + " /* seen this happen, likely harmless in multicore */", + " if (warned == 0)", + " { /* Uerror(\"stack out of wack - zap\"); */", + " cpu_printf(\"pan: warning, stack incomplete\\n\");", + " warned = 1;", + " }", + "#endif", + " goto done;", "Found:", " ZAPS++;", " if (last)", " last->nxt = v->nxt;", " else", - " S_Tab[j1] = v->nxt;", + " S_Tab[j1_spin] = v->nxt;", " v->tagged = (unsigned) n;", "#if !defined(NOREDUCE) && !defined(SAFETY)", " v->proviso = 0;", @@ -4672,39 +6545,57 @@ " for (w = Free_list; w; Fa++, last=w, w = w->nxt)", " { if ((int) w->tagged <= n)", " { if (last)", - " { v->nxt = w; /* was: v->nxt = w->nxt; */", + " { v->nxt = w;", " last->nxt = v;", " } else", " { v->nxt = Free_list;", " Free_list = v;", " }", - " return;", + " goto done;", " }", " if (!w->nxt)", " { w->nxt = v;", - " return;", + " goto done;", " } }", " Free_list = v;", + "done:", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " now._last = was_last;", + "#endif", + " return;", "}", "void", "onstack_put(void)", "{ struct H_el **tmp = H_tab;", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " uchar was_last = now._last;", + " now._last = 0;", + "#endif", " H_tab = S_Tab;", " if (hstore((char *)&now, vsize) != 0)", "#if defined(BITSTATE) && defined(LC)", " printf(\"pan: warning, double stack entry\\n\");", "#else", + " #ifndef ZAPH", " Uerror(\"cannot happen - unstack_put\");", + " #endif", "#endif", " H_tab = tmp;", " trpt->ostate = Lstate;", " PUT++;", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " now._last = was_last;", + "#endif", "}", "int", "onstack_now(void)", "{ struct H_el *tmp;", " struct H_el **tmp2 = H_tab;", " char *v; int n, m = 1;\n", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " uchar was_last = now._last;", + " now._last = 0;", + "#endif", " H_tab = S_Tab;", "#ifdef NOCOMP", "#if defined(BITSTATE) && defined(LC)", @@ -4722,13 +6613,16 @@ " s_hash((uchar *)v, n);", "#endif", " H_tab = tmp2;", - " for (tmp = S_Tab[j1]; tmp; Zn++, tmp = tmp->nxt)", + " for (tmp = S_Tab[j1_spin]; tmp; Zn++, tmp = tmp->nxt)", " { m = memcmp(((char *)&(tmp->state)),v,n);", " if (m <= 0)", " { Lstate = (struct H_el *) tmp;", " break;", " } }", " PROBE++;", + "#if defined(BCS) && defined(NO_LAST) && defined(HAS_LAST)", + " now._last = was_last;", + "#endif", " return (m == 0);", "}", "#endif", @@ -4738,19 +6632,32 @@ "void", "hinit(void)", "{", -"#ifdef MA", - "#ifdef R_XPT", - " { void r_xpoint(void);", - " r_xpoint();", - " }", - "#else", - " dfa_init((unsigned short) (MA+a_cycles));", - "#endif", -"#endif", -"#if !defined(MA) || defined(COLLAPSE)", - " H_tab = (struct H_el **)", - " emalloc((1L<1 && !defined(COLLAPSE)", + " if (!readtrail)", + " { void init_HT(unsigned long);", + " init_HT(0L);", + " }", + "#endif", + "#endif", + " #endif", + " #if !defined(MA) || defined(COLLAPSE)", + "#if NCORE>1", + " if (!readtrail)", + " { void init_HT(unsigned long);", + " init_HT((unsigned long) (ONE_L<= MA)", " { printf(\"pan: error, MA too small, recompile pan.c\");", " printf(\" with -DMA=N with N>%%d\\n\", n);", " Uerror(\"aborting\");", " }", - " if (n > (int) maxgs) maxgs = (unsigned int) n;", - + " if (n > (int) maxgs)", + " { maxgs = (unsigned int) n;", + " }", " for (i = 0; i < n; i++)", - " Info[i] = v[i];", + " { Info[i] = v[i];", + " }", " for ( ; i < MA-1; i++)", - " Info[i] = 0;", + " { Info[i] = 0;", + " }", " Info[MA-1] = pbit;", " if (a_cycles) /* place _a_t at the end */", - " { Info[MA] = Info[0]; Info[0] = 0; }", + " { Info[MA] = Info[0];", + " Info[0] = 0;", + " }", + "", + "#if NCORE>1 && !defined(SEP_STATE)", + " enter_critical(GLOBAL_LOCK); /* crude, but necessary */", + " /* to make this mode work, also replace emalloc with grab_shared inside store MA routines */", + "#endif", + "", " if (!dfa_store(Info))", " { if (pbit == 0", " && (now._a_t&1)", @@ -4819,16 +6738,17 @@ " { Info[MA-1] = 4; /* off-stack bit */", " nShadow++;", " if (!dfa_member(MA-1))", - " {", - "#ifdef VERBOSE", - " printf(\"intersected 1st dfs stack\\n\");", - "#endif", - " return 3;", + " { ret_val = 3;", + " #ifdef VERBOSE", + " printf(\"intersected 1st dfs stack\\n\");", + " #endif", + " goto done;", " } } }", - "#ifdef VERBOSE", + " ret_val = 0;", + " #ifdef VERBOSE", " printf(\"new state\\n\");", - "#endif", - " return 0; /* new state */", + " #endif", + " goto done;", " }", "#ifdef FULLSTACK", " if (pbit == 0)", @@ -4837,23 +6757,29 @@ " trpt->proviso = dfa_member(MA-1);", "#endif", " Info[MA-1] = 4; /* off-stack bit */", - " if (dfa_member(MA-1)) {", + " if (dfa_member(MA-1))", + " { ret_val = 1; /* off-stack */", + " #ifdef VERBOSE", + " printf(\"old state\\n\");", + " #endif", + " } else", + " { ret_val = 2; /* on-stack */", + " #ifdef VERBOSE", + " printf(\"on-stack\\n\");", + " #endif", + " }", + " goto done;", + " }", + "#endif", + " ret_val = 1;", "#ifdef VERBOSE", - " printf(\"old state\\n\");", - "#endif", - " return 1; /* off-stack */", - " } else {", - "#ifdef VERBOSE", - " printf(\"on-stack\\n\");", - "#endif", - " return 2; /* on-stack */", - " }", - " }", - "#endif", - "#ifdef VERBOSE", - " printf(\"old state\\n\");", - "#endif", - " return 1; /* old state */", + " printf(\"old state\\n\");", + "#endif", + "done:", + "#if NCORE>1 && !defined(SEP_STATE)", + " leave_critical(GLOBAL_LOCK);", + "#endif", + " return ret_val; /* old state */", "}", "#endif", @@ -4873,34 +6799,138 @@ "}", "#endif", + "#ifdef TRIX", + "void", + "sv_populate(void)", + "{ int i, cnt = 0;", + " TRIX_v6 **base = processes;", + " int bound = now._nr_pr; /* MAXPROC+1; */", + "#ifdef V_TRIX", + " printf(\"%%4d: sv_populate\\n\", depth);", + "#endif", + "again:", + " for (i = 0; i < bound; i++)", + " { if (base[i] != NULL)", + " { struct H_el *tmp;", + " int m, n; uchar *v;", + "#ifndef BFS", + " if (base[i]->modified == 0)", + " { cnt++;", + " #ifdef V_TRIX", + " printf(\"%%4d: %%s %%d not modified\\n\",", + " depth, (base == processes)?\"proc\":\"chan\", i);", + " #endif", + " continue;", + " }", + " #ifndef V_MOD", + " base[i]->modified = 0;", + " #endif", + "#endif", + "#ifdef TRIX_RIX", + " if (base == processes)", + " { ((P0 *)pptr(i))->_pid = 0;", + " }", + "#endif", + " n = base[i]->psize;", + " v = base[i]->body;", + " s_hash(v, n); /* sets j1_spin */", + " tmp = H_tab[j1_spin];", + " if (!tmp) /* new */", + " { tmp = grab_state(n);", + " H_tab[j1_spin] = tmp;", + " m = 1; /* non-zero */", + " } else", + " { struct H_el *ntmp, *olst = (struct H_el *) 0;", + " for (;; hcmp++, olst = tmp, tmp = tmp->nxt)", + " { m = memcmp(((char *)&(tmp->state)), v, n);", + " if (m == 0) /* match */", + " { break;", + " } else if (m < 0) /* insert */", + " { ntmp = grab_state(n);", + " ntmp->nxt = tmp;", + " if (!olst)", + " H_tab[j1_spin] = ntmp;", + " else", + " olst->nxt = ntmp;", + " tmp = ntmp;", + " break;", + " } else if (!tmp->nxt) /* append */", + " { tmp->nxt = grab_state(n);", + " tmp = tmp->nxt;", + " break;", + " } } }", + " if (m != 0)", + " { memcpy((char *)&(tmp->state), v, n);", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE)", + " tmp->m_K1 = K1; /* set via s_hash */", + "#endif", + " if (base == processes)", + " { _p_count[i]++;", + " } else", + " { _c_count[i]++;", + " } }", + " now._ids_[cnt++] = (char *)&(tmp->state);", + "#ifdef TRIX_RIX", + " if (base == processes)", + " { ((P0 *)pptr(i))->_pid = i;", + " }", + "#endif", + " } }", +#if 0 + if a process appears or disappears: always secure a full sv_populate + (channels come and go only with a process) + + only one process can disappear per step + but any nr of channels can be removed at the same time + if a process disappears, all subsequent entries + are then in the wrong place in the _ids_ list + and need to be recomputed + but we do not need to fill out with zeros + because vsize prevents them being used +#endif + " /* do the same for all channels */", + " if (base == processes)", + " { base = channels;", + " bound = now._nr_qs; /* MAXQ+1; */", + " goto again;", + " }", + "}", + "#endif\n", "int", "hstore(char *vin, int nin) /* hash table storage */", - "{ struct H_el *tmp, *ntmp, *olst = (struct H_el *) 0;", + "{ struct H_el *ntmp;", + " struct H_el *tmp, *olst = (struct H_el *) 0;", " char *v; int n, m=0;", "#ifdef HC", " uchar rem_a;", "#endif", + + "#ifdef TRIX", + " sv_populate(); /* update proc and chan ids */", + "#endif", + "#ifdef NOCOMP", /* defined by BITSTATE */ - "#if defined(BITSTATE) && defined(LC)", + " #if defined(BITSTATE) && defined(LC)", " if (S_Tab == H_tab)", " { v = (char *) &comp_now;", " n = compact_stack(vin, nin);", " } else", " { v = vin; n = nin;", " }", - "#else", + " #else", " v = vin; n = nin;", - "#endif", + " #endif", "#else", " v = (char *) &comp_now;", " #ifdef HC", - " rem_a = now._a_t;", /* 4.3.0 */ + " rem_a = now._a_t;", /* new 5.0 */ " now._a_t = 0;", /* for hashing/state matching to work right */ " #endif", - " n = compress(vin, nin);", /* with HC, this calls s_hash */ + " n = compress(vin, nin);", /* with HC, this calls s_hash -- but on vin, not on v... */ " #ifdef HC", - " now._a_t = rem_a;", /* 4.3.0 */ - " #endif", + " now._a_t = rem_a;", /* new 5.0 */ + " #endif", + /* with HC4 -a, compress copies K1 and K2 into v[], leaving v[0] free for the a-bit */ "#ifndef SAFETY", " if (S_A)", " { v[0] = 0; /* _a_t */", @@ -4911,15 +6941,30 @@ "#endif", " m = 0;", " }", - "#endif", + " #endif", "#endif", "#if !defined(HC) && !(defined(BITSTATE) && defined(LC))", " s_hash((uchar *)v, n);", "#endif", - " tmp = H_tab[j1];", + "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " enter_critical(CS_ID); /* uses spinlock */", + "#endif", + + " tmp = H_tab[j1_spin];", " if (!tmp)", " { tmp = grab_state(n);", - " H_tab[j1] = tmp;", + "#if NCORE>1", + " if (!tmp)", + " { /* if we get here -- we've already issued a warning */", + " /* but we want to allow the normal distributed termination */", + " /* to collect the stats on all cpus in the wrapup */", + " #if !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", + " return 1; /* allow normal termination */", + " }", + "#endif", + " H_tab[j1_spin] = tmp;", " } else", " { for (;; hcmp++, olst = tmp, tmp = tmp->nxt)", " { /* skip the _a_t and the _cnt bytes */", @@ -4971,6 +7016,10 @@ "#endif", "#endif", + "#if NCORE>1", + " Lstate = (struct H_el *) tmp;", + "#endif", + "#ifdef FULLSTACK", "#ifndef SAFETY", /* or else wasnew == 0 */ " if (wasnew)", @@ -4982,17 +7031,31 @@ " {", "intersect:", "#ifdef CHECK", + "#if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + "#endif", " printf(\"1st dfs-stack intersected on state %%d+\\n\",", " (int) tmp->st_id);", "#endif", + + "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + "#endif", + " return 3;", " }", "#ifdef CHECK", + "#if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + "#endif", " printf(\"\tNew state %%d+\\n\", (int) tmp->st_id);", "#endif", "#ifdef DEBUG", " dumpstate(1, (char *)&(tmp->state),n,tmp->tagged);", "#endif", + "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + "#endif", " return 0;", " } else", "#endif", @@ -5014,41 +7077,95 @@ " goto intersect;", "#endif", "#ifdef CHECK", + "#if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + "#endif", " printf(\"\tStack state %%d\\n\", (int) tmp->st_id);", "#endif", "#ifdef DEBUG", " dumpstate(0, (char *)&(tmp->state),n,tmp->tagged);", "#endif", + "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + "#endif", " return 2; /* match on stack */", " }", "#else", " if (wasnew)", " {", "#ifdef CHECK", + "#if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + "#endif", " printf(\"\tNew state %%d+\\n\", (int) tmp->st_id);", "#endif", "#ifdef DEBUG", " dumpstate(1, (char *)&(tmp->state), n, 0);", "#endif", + "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + "#endif", " return 0;", " }", "#endif", "#ifdef CHECK", + "#if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + "#endif", " printf(\"\tOld state %%d\\n\", (int) tmp->st_id);", "#endif", "#ifdef DEBUG", " dumpstate(0, (char *)&(tmp->state), n, 0);", "#endif", + "#if defined(BCS)", + " #ifdef CONSERVATIVE", + " if (tmp->ctx_low > trpt->sched_limit)", + " { tmp->ctx_low = trpt->sched_limit;", + " tmp->ctx_pid[(now._last)/8] = 1 << ((now._last)%8); /* new */", + " #ifdef CHECK", + " #if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + " #endif", + " printf(\"\t\tRevisit with fewer context switches\\n\");", + " #endif", + " nstates--;", + " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", + " return 0;", + " } else if ((tmp->ctx_low == trpt->sched_limit", + " && (tmp->ctx_pid[(now._last)/8] & ( 1 << ((now._last)%8) )) == 0 ))", + " { tmp->ctx_pid[(now._last)/8] |= 1 << ((now._last)%8); /* add */", + " #ifdef CHECK", + " #if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + " #endif", + " printf(\"\t\tRevisit with same nr of context switches\\n\");", + " #endif", + " nstates--;", + " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", + " return 0;", + " }", + " #endif", + "#endif", "#ifdef REACH", - " if (tmp->D > depth)", - " { tmp->D = depth;", - "#ifdef CHECK", - " printf(\"\t\tReVisiting (from smaller depth)\\n\");", - "#endif", - " nstates--;", + " if (tmp->D > depth)", + " { tmp->D = depth;", + " #ifdef CHECK", + " #if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + " #endif", + " printf(\"\t\tReVisiting (from smaller depth)\\n\");", + " #endif", + " nstates--;", + " #if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", #if 0 - possible variation of iterative search for shortest counter-example (pan -i - and pan -I) suggested by Pierre Moro (for safety properties): + a possible variation of iterative search for shortest counter-example + (pan -i and pan -I) suggested by Pierre Moro (for safety properties): state revisits on shorter depths do not start until after the first counter-example is found. this assumes that the max search depth is set large enough that a first (possibly long) counter-example @@ -5056,22 +7173,34 @@ if set too short, this variant can miss the counter-example, even if it would otherwise be shorter than the depth-limit. (p.m. unsure if this preserves the guarantee of finding the - shortest counter-example - so not enabled yet) - " if (errors > 0 && iterative)", /* Moro */ + shortest counter-example - so not enabled by default) + " if (errors > 0 && iterative)", /* Moro */ #endif - " return 0;", - " }", - "#endif", - "#if defined(BFS) && defined(Q_PROVISO)", + " return 0;", + " }", + "#endif", + "#if (defined(BFS) && defined(Q_PROVISO)) || NCORE>1", " Lstate = (struct H_el *) tmp;", "#endif", + "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + "#endif", " return 1; /* match outside stack */", " } else if (m < 0)", " { /* insert state before tmp */", " ntmp = grab_state(n);", + "#if NCORE>1", + " if (!ntmp)", + " {", + " #if !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", + " return 1; /* allow normal termination */", + " }", + "#endif", " ntmp->nxt = tmp;", " if (!olst)", - " H_tab[j1] = ntmp;", + " H_tab[j1_spin] = ntmp;", " else", " olst->nxt = ntmp;", " tmp = ntmp;", @@ -5082,18 +7211,36 @@ "Append:", "#endif", " tmp->nxt = grab_state(n);", + "#if NCORE>1", + " if (!tmp->nxt)", + " {", + " #if !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", + " return 1; /* allow normal termination */", + " }", + "#endif", " tmp = tmp->nxt;", " break;", " } }", " }", "#ifdef CHECK", " tmp->st_id = (unsigned) nstates;", + "#if NCORE>1", + " printf(\"cpu%%d: \", core_id);", + "#endif", "#ifdef BITSTATE", " printf(\" Push state %%d\\n\", ((int) nstates) - 1);", "#else", " printf(\" New state %%d\\n\", (int) nstates);", "#endif", "#endif", + "#if defined(BCS)", + " tmp->ctx_low = trpt->sched_limit;", + " #ifdef CONSERVATIVE", + " tmp->ctx_pid[(now._last)/8] = 1 << ((now._last)%8); /* new limit */", + " #endif", + "#endif", "#if !defined(SAFETY) || defined(REACH)", " tmp->D = depth;", "#endif", @@ -5116,24 +7263,38 @@ " }", "#endif", "#endif", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE)", + " tmp->m_K1 = K1;", + "#endif", " memcpy(((char *)&(tmp->state)), v, n);", "#ifdef FULLSTACK", " tmp->tagged = (S_A)?V_A:(depth+1);", "#ifdef DEBUG", - " dumpstate(-1, v, n, tmp->tagged);", + " dumpstate(-1, v, n, tmp->tagged);", "#endif", " Lstate = (struct H_el *) tmp;", "#else", - "#ifdef DEBUG", - " dumpstate(-1, v, n, 0);", - "#endif", - "#endif", + " #ifdef DEBUG", + " dumpstate(-1, v, n, 0);", + " #endif", + " #if NCORE>1", + " Lstate = (struct H_el *) tmp;", + " #endif", + "#endif", + + "/* #if NCORE>1 && !defined(SEP_STATE) */", + "#if NCORE>1", + " #ifdef V_PROVISO", + " tmp->cpu_id = core_id;", + " #endif", + " #if !defined(SEP_STATE) && !defined(BITSTATE)", + " leave_critical(CS_ID);", + " #endif", + "#endif", + " return 0;", "}", "#endif", "#include TRANSITIONS", - "void", - "do_reach(void)", - "{", 0, }; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen2.c --- a/sys/src/cmd/spin/pangen2.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen2.c Tue Mar 06 23:34:10 2012 +0100 @@ -1,6 +1,6 @@ /***** spin: pangen2.c *****/ -/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* Copyright (c) 1989-2009 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 */ @@ -8,6 +8,7 @@ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ +/* (c) 2007: small additions for V5.0 to support multi-core verifications */ #include "spin.h" #include "version.h" @@ -20,24 +21,25 @@ #define blurb(fd, e) { fprintf(fd, "\n"); if (!merger) fprintf(fd, "\t\t/* %s:%d */\n", \ e->n->fn->name, e->n->ln); } -#define tr_map(m, e) { if (!merger) fprintf(tt, "\t\ttr_2_src(%d, %s, %d);\n", \ +#define tr_map(m, e) { if (!merger) fprintf(tt, "\t\ttr_2_src(%d, \"%s\", %d);\n", \ m, e->n->fn->name, e->n->ln); } extern ProcList *rdy; extern RunList *run; extern Symbol *Fname, *oFname, *context; extern char *claimproc, *eventmap; -extern int lineno, verbose, Npars, Mpars; +extern int lineno, verbose, Npars, Mpars, nclaims; extern int m_loss, has_remote, has_remvar, merger, rvopt, separate; -extern int Ntimeouts, Etimeouts, deadvar; -extern int u_sync, u_async, nrRdy; +extern int Ntimeouts, Etimeouts, deadvar, old_scope_rules; +extern int u_sync, u_async, nrRdy, Unique; extern int GenCode, IsGuard, Level, TestOnly; extern short has_stack; extern char *NextLab[]; -FILE *tc, *th, *tt, *tm, *tb; - -int OkBreak = -1; +FILE *tc, *th, *tt, *tb; +static FILE *tm; + +int OkBreak = -1, has_hidden = 0; /* has_hidden set in sym.c and structs.c */ short nocast=0; /* to turn off casts in lvalues */ short terse=0; /* terse printing of varnames */ short no_arrays=0; @@ -52,9 +54,7 @@ short has_unless=0; /* spec contains unless statements */ short has_provided=0; /* spec contains PROVIDED clauses on procs */ short has_code=0; /* spec contains c_code, c_expr, c_state */ -short _isok=0; /* checks usage of predefined variable _ */ short evalindex=0; /* evaluate index of var names */ -short withprocname=0; /* prefix local varnames with procname */ int mst=0; /* max nr of state/process */ int claimnr = -1; /* claim process, if any */ int eventmapnr = -1; /* event trace, if any */ @@ -74,8 +74,11 @@ static int uniq=1; static int multi_needed, multi_undo; static short AllGlobal=0; /* set if process has provided clause */ +static short withprocname=0; /* prefix local varnames with procname */ +static short _isok=0; /* checks usage of predefined variable _ */ int has_global(Lextok *); +void Fatal(char *, char *); static int getweight(Lextok *); static int scan_seq(Sequence *); static void genconditionals(void); @@ -98,12 +101,31 @@ return -1; } +int +pid_is_claim(int p) /* Pid (p->tn) to type (p->b) */ +{ ProcList *r; + + for (r = rdy; r; r = r->nxt) + { if (r->tn == p) return (r->b == N_CLAIM); + } + printf("spin: error, cannot find pid %d\n", p); + return 0; +} + static void reverse_procs(RunList *q) { if (!q) return; reverse_procs(q->nxt); - fprintf(tc, " Addproc(%d);\n", q->tn); + fprintf(tc, " Addproc(%d);\n", q->tn); +} + +static void +forward_procs(RunList *q) +{ + if (!q) return; + fprintf(tc, " Addproc(%d);\n", q->tn); + forward_procs(q->nxt); } static void @@ -111,6 +133,15 @@ { fprintf(th, "#define _T5 %d\n", uniq++); fprintf(th, "#define _T2 %d\n", uniq++); + + if (Unique < (1 << (8*sizeof(unsigned char)) )) /* was uniq before */ + { fprintf(th, "#define T_ID unsigned char\n"); + } else if (Unique < (1 << (8*sizeof(unsigned short)) )) + { fprintf(th, "#define T_ID unsigned short\n"); + } else + { fprintf(th, "#define T_ID unsigned int\n"); + } + fprintf(tm, "\tcase _T5:\t/* np_ */\n"); if (separate == 2) @@ -151,51 +182,72 @@ void gensrc(void) { ProcList *p; - - if (!(tc = fopen(Cfile[0].nm[separate], "w")) /* main routines */ - || !(th = fopen(Cfile[1].nm[separate], "w")) /* header file */ - || !(tt = fopen(Cfile[2].nm[separate], "w")) /* transition matrix */ - || !(tm = fopen(Cfile[3].nm[separate], "w")) /* forward moves */ - || !(tb = fopen(Cfile[4].nm[separate], "w"))) /* backward moves */ + int i; + + disambiguate(); /* avoid name-clashes between scopes */ + + if (!(tc = fopen(Cfile[0].nm[separate], MFLAGS)) /* main routines */ + || !(th = fopen(Cfile[1].nm[separate], MFLAGS)) /* header file */ + || !(tt = fopen(Cfile[2].nm[separate], MFLAGS)) /* transition matrix */ + || !(tm = fopen(Cfile[3].nm[separate], MFLAGS)) /* forward moves */ + || !(tb = fopen(Cfile[4].nm[separate], MFLAGS))) /* backward moves */ { printf("spin: cannot create pan.[chtmfb]\n"); alldone(1); } - fprintf(th, "#define Version \"%s\"\n", Version); - fprintf(th, "#define Source \"%s\"\n\n", oFname->name); + fprintf(th, "#define SpinVersion \"%s\"\n", SpinVersion); + fprintf(th, "#define PanSource \""); + for (i = 0; oFname->name[i] != '\0'; i++) + { char c = oFname->name[i]; + if (c == '\\' || c == ' ') /* Windows path */ + { fprintf(th, "\\"); + } + fprintf(th, "%c", c); + } + fprintf(th, "\"\n\n"); + + fprintf(th, "#define G_long %d\n", (int) sizeof(long)); + fprintf(th, "#define G_int %d\n", (int) sizeof(int)); + + fprintf(th, "#ifdef WIN64\n"); + fprintf(th, " #define ONE_L ((unsigned long) 1)\n"); + fprintf(th, " #define long long long\n"); + fprintf(th, "#else\n"); + fprintf(th, " #define ONE_L (1L)\n"); + fprintf(th, "#endif\n"); + if (separate != 2) - fprintf(th, "char *TrailFile = Source; /* default */\n"); + { fprintf(th, "char *TrailFile = PanSource; /* default */\n"); + fprintf(th, "char *trailfilename;\n"); + } fprintf(th, "#if defined(BFS)\n"); - fprintf(th, "#ifndef SAFETY\n"); - fprintf(th, "#define SAFETY\n"); + fprintf(th, " #ifndef SAFETY\n"); + fprintf(th, " #define SAFETY\n"); + fprintf(th, " #endif\n"); + fprintf(th, " #ifndef XUSAFE\n"); + fprintf(th, " #define XUSAFE\n"); + fprintf(th, " #endif\n"); fprintf(th, "#endif\n"); - fprintf(th, "#ifndef XUSAFE\n"); - fprintf(th, "#define XUSAFE\n"); - fprintf(th, "#endif\n"); - fprintf(th, "#endif\n"); fprintf(th, "#ifndef uchar\n"); - fprintf(th, "#define uchar unsigned char\n"); + fprintf(th, " #define uchar unsigned char\n"); fprintf(th, "#endif\n"); fprintf(th, "#ifndef uint\n"); - fprintf(th, "#define uint unsigned int\n"); + fprintf(th, " #define uint unsigned int\n"); fprintf(th, "#endif\n"); if (sizeof(void *) > 4) /* 64 bit machine */ - { fprintf(th, "#ifndef HASH32\n"); - fprintf(th, "#define HASH64\n"); + { fprintf(th, "#if !defined(HASH32) && !defined(HASH64)\n"); + fprintf(th, " #define HASH64\n"); fprintf(th, "#endif\n"); } -#if 0 - if (sizeof(long)==sizeof(int)) - fprintf(th, "#define long int\n"); -#endif + if (separate == 1 && !claimproc) { Symbol *n = (Symbol *) emalloc(sizeof(Symbol)); Sequence *s = (Sequence *) emalloc(sizeof(Sequence)); claimproc = n->name = "_:never_template:_"; - ready(n, ZN, s, 0, ZN); + ready(n, ZN, s, 0, ZN, N_CLAIM); } if (separate == 2) { if (has_remote) @@ -212,15 +264,21 @@ fprintf(th, "#define DELTA %d\n", DELTA); fprintf(th, "#ifdef MA\n"); + fprintf(th, " #if NCORE>1 && !defined(SEP_STATE)\n"); + fprintf(th, " #define SEP_STATE\n"); + fprintf(th, " #endif\n"); fprintf(th, "#if MA==1\n"); /* user typed -DMA without size */ - fprintf(th, "#undef MA\n#define MA 100\n"); + fprintf(th, " #undef MA\n"); + fprintf(th, " #define MA 100\n"); fprintf(th, "#endif\n#endif\n"); fprintf(th, "#ifdef W_XPT\n"); - fprintf(th, "#if W_XPT==1\n"); /* user typed -DW_XPT without size */ - fprintf(th, "#undef W_XPT\n#define W_XPT 1000000\n"); - fprintf(th, "#endif\n#endif\n"); + fprintf(th, " #if W_XPT==1\n"); /* user typed -DW_XPT without size */ + fprintf(th, " #undef W_XPT\n"); + fprintf(th, " #define W_XPT 1000000\n"); + fprintf(th, " #endif\n"); + fprintf(th, "#endif\n"); fprintf(th, "#ifndef NFAIR\n"); - fprintf(th, "#define NFAIR 2 /* must be >= 2 */\n"); + fprintf(th, " #define NFAIR 2 /* must be >= 2 */\n"); fprintf(th, "#endif\n"); if (Ntimeouts) fprintf(th, "#define NTIM %d\n", Ntimeouts); @@ -230,6 +288,8 @@ fprintf(th, "#define REM_VARS 1\n"); if (has_remote) fprintf(th, "#define REM_REFS %d\n", has_remote); /* not yet used */ + if (has_hidden) + fprintf(th, "#define HAS_HIDDEN %d\n", has_hidden); if (has_last) fprintf(th, "#define HAS_LAST %d\n", has_last); if (has_sorted) @@ -239,8 +299,11 @@ if (has_random) fprintf(th, "#define HAS_RANDOM %d\n", has_random); fprintf(th, "#define HAS_CODE\n"); /* doesn't seem to cause measurable overhead */ + fprintf(th, "#if defined(RANDSTORE) && !defined(RANDSTOR)\n"); + fprintf(th, " #define RANDSTOR RANDSTORE\n"); /* xspin uses RANDSTORE... */ + fprintf(th, "#endif\n"); if (has_stack) - fprintf(th, "#define HAS_STACK\n"); + fprintf(th, "#define HAS_STACK %d\n", has_stack); if (has_enabled) fprintf(th, "#define HAS_ENABLED 1\n"); if (has_unless) @@ -256,7 +319,7 @@ || has_badelse || has_last) { fprintf(th, "#ifndef NOREDUCE\n"); - fprintf(th, "#define NOREDUCE 1\n"); + fprintf(th, " #define NOREDUCE 1\n"); fprintf(th, "#endif\n"); } if (has_np) @@ -265,18 +328,31 @@ fprintf(th, "#define MERGED 1\n"); doless: - fprintf(th, "#ifdef NP /* includes np_ demon */\n"); + fprintf(th, "#if !defined(HAS_LAST) && defined(BCS)\n"); + fprintf(th, " #define HAS_LAST 1 /* use it, but */\n"); + fprintf(th, " #ifndef STORE_LAST\n"); /* unless the user insists */ + fprintf(th, " #define NO_LAST 1 /* dont store it */\n"); + fprintf(th, " #endif\n"); + fprintf(th, "#endif\n"); + + fprintf(th, "#if defined(BCS) && defined(BITSTATE)\n"); + fprintf(th, " #ifndef NO_CTX\n"); + fprintf(th, " #define STORE_CTX 1\n"); + fprintf(th, " #endif\n"); + fprintf(th, "#endif\n"); + + fprintf(th, "#ifdef NP\n"); if (!has_np) - fprintf(th, "#define HAS_NP 2\n"); - fprintf(th, "#define VERI %d\n", nrRdy); - fprintf(th, "#define endclaim 3 /* none */\n"); + fprintf(th, " #define HAS_NP 2\n"); + fprintf(th, " #define VERI %d /* np_ */\n", nrRdy); fprintf(th, "#endif\n"); if (claimproc) - { claimnr = fproc(claimproc); - /* NP overrides claimproc */ - fprintf(th, "#if !defined(NOCLAIM) && !defined NP\n"); - fprintf(th, "#define VERI %d\n", claimnr); - fprintf(th, "#define endclaim endstate%d\n", claimnr); + { claimnr = fproc(claimproc); /* the default claim */ + fprintf(th, "#ifndef NOCLAIM\n"); + fprintf(th, " #define NCLAIMS %d\n", nclaims); + fprintf(th, " #ifndef NP\n"); + fprintf(th, " #define VERI %d\n", claimnr); + fprintf(th, " #endif\n"); fprintf(th, "#endif\n"); } if (eventmap) @@ -291,7 +367,7 @@ fprintf(th, " char *fnm; int from; int upto;\n"); fprintf(th, "} S_F_MAP;\n"); - fprintf(tc, "/*** Generated by %s ***/\n", Version); + fprintf(tc, "/*** Generated by %s ***/\n", SpinVersion); fprintf(tc, "/*** From source: %s ***/\n\n", oFname->name); ntimes(tc, 0, 1, Pre0); @@ -304,6 +380,10 @@ case 2: fprintf(tc, "#include \"pan_t.h\"\n"); break; } + fprintf(tc, "#ifdef LOOPSTATE\n"); + fprintf(tc, "double cnt_loops;\n"); + fprintf(tc, "#endif\n"); + fprintf(tc, "State A_Root; /* seed-state for cycles */\n"); fprintf(tc, "State now; /* the full state-vector */\n"); plunk_c_fcts(tc); /* State can be used in fcts */ @@ -314,9 +394,9 @@ fprintf(tc, "extern int verbose; extern long depth;\n"); fprintf(tc, "#ifndef NOBOUNDCHECK\n"); - fprintf(tc, "#define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n"); + fprintf(tc, " #define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n"); fprintf(tc, "#else\n"); - fprintf(tc, "#define Index(x, y)\tx\n"); + fprintf(tc, " #define Index(x, y)\tx\n"); fprintf(tc, "#endif\n"); c_preview(); /* sets hastrack */ @@ -335,7 +415,7 @@ fprintf(tt, "}\n\n"); fprintf(tt, "void\nputpeg(int n, int m)\n"); fprintf(tt, "{ printf(\"%%5d\ttrans %%4d \", m, n);\n"); - fprintf(tt, " printf(\"file %%s line %%3d\\n\",\n"); + fprintf(tt, " printf(\"%%s:%%d\\n\",\n"); fprintf(tt, " T_SRC[n].fl, T_SRC[n].ln);\n"); fprintf(tt, "}\n"); if (!merger) @@ -360,12 +440,12 @@ fprintf(tm, "#define rand pan_rand\n"); fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n"); - fprintf(tm, " printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n"); + fprintf(tm, " cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n"); fprintf(tm, "#endif\n"); fprintf(tm, " switch (t->forw) {\n"); } else { fprintf(tt, "#ifndef PEG\n"); - fprintf(tt, "#define tr_2_src(m,f,l)\n"); + fprintf(tt, " #define tr_2_src(m,f,l)\n"); fprintf(tt, "#endif\n"); fprintf(tt, "void\nset_claim(void)\n{\tTrans *T;\n"); fprintf(tt, "\textern Trans ***trans;\n"); @@ -374,7 +454,7 @@ fprintf(tm, "#define rand pan_rand\n"); fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n"); - fprintf(tm, " printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n"); + fprintf(tm, " cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n"); fprintf(tm, "#endif\n"); fprintf(tm, " switch (forw) {\n"); } @@ -404,11 +484,12 @@ fprintf(tb, " case 0: goto R999; /* nothing to undo */\n"); for (p = rdy; p; p = p->nxt) - putproc(p); - + { putproc(p); + } if (separate != 2) - { fprintf(th, "struct {\n"); + { + fprintf(th, "struct {\n"); fprintf(th, " int tp; short *src;\n"); fprintf(th, "} src_all[] = {\n"); for (p = rdy; p; p = p->nxt) @@ -416,9 +497,12 @@ p->tn, p->tn); fprintf(th, " { 0, (short *) 0 }\n"); fprintf(th, "};\n"); - fprintf(th, "short *frm_st0;\n"); /* records src states for transitions in never claim */ - } else - { fprintf(th, "extern short *frm_st0;\n"); + + fprintf(th, "S_F_MAP *flref[] = {\n"); /* 5.3.0 */ + for (p = rdy; p; p = p->nxt) + { fprintf(th, " src_file%d%c\n", p->tn, p->nxt?',':' '); + } + fprintf(th, "};\n"); } gencodetable(th); @@ -456,18 +540,27 @@ if (!run) fatal("no runable process", (char *)0); fprintf(tc, "void\n"); fprintf(tc, "active_procs(void)\n{\n"); +#if 1 + fprintf(tc, " if (!permuted) {\n"); reverse_procs(run); + fprintf(tc, " } else {\n"); + forward_procs(run); + fprintf(tc, " }\n"); +#else + reverse_procs(run); +#endif fprintf(tc, "}\n"); ntimes(tc, 0, 1, Dfa); ntimes(tc, 0, 1, Xpt); fprintf(th, "#define NTRANS %d\n", uniq); fprintf(th, "#ifdef PEG\n"); - fprintf(th, "long peg[NTRANS];\n"); + fprintf(th, " long peg[NTRANS];\n"); fprintf(th, "#endif\n"); - + fprintf(th, "void select_claim(int);\n"); if (u_sync && !u_async) - spit_recvs(th, tc); + { spit_recvs(th, tc); + } } else { genheader(); fprintf(th, "#define FORWARD_MOVES\t\"pan_t.m\"\n"); @@ -475,9 +568,9 @@ fprintf(th, "#define TRANSITIONS\t\"pan_t.t\"\n"); fprintf(tc, "extern int Maxbody;\n"); fprintf(tc, "#if VECTORSZ>32000\n"); - fprintf(tc, "extern int proc_offset[];\n"); + fprintf(tc, " extern int proc_offset[];\n"); fprintf(tc, "#else\n"); - fprintf(tc, "extern short proc_offset[];\n"); + fprintf(tc, " extern short proc_offset[];\n"); fprintf(tc, "#endif\n"); fprintf(tc, "extern uchar proc_skip[];\n"); fprintf(tc, "extern uchar *reached[];\n"); @@ -491,7 +584,7 @@ fprintf(tc, "\textern State now;\n"); fprintf(tc, "\textern void set_claim(void);\n\n"); fprintf(tc, "#ifdef PROV\n"); - fprintf(tc, "#include PROV\n"); + fprintf(tc, " #include PROV\n"); fprintf(tc, "#endif\n"); fprintf(tc, "\tset_claim();\n"); genother(); @@ -509,8 +602,6 @@ fprintf(tc, "int\nrev_claim(int backw)\n{ return 0; }\n"); fprintf(tc, "#include TRANSITIONS\n"); } - if (separate != 1) - ntimes(tc, 0, 1, Nvr1); if (separate != 2) { c_wrapper(tc); @@ -537,13 +628,13 @@ fprintf(tc, "%s(", pre); if (!(s->hidden&1)) { if (s->context) - fprintf(tc, "((P%d *)this)->", pid); + fprintf(tc, "(int) ( ((P%d *)this)->", pid); else - fprintf(tc, "now."); + fprintf(tc, "(int) ( now."); } fprintf(tc, "%s", s->name); - if (qln > 1) fprintf(tc, "[%d]", ai); - fprintf(tc, ")"); + if (qln > 1 || s->isarray) fprintf(tc, "[%d]", ai); + fprintf(tc, ") )"); } struct AA { char TT[9]; char CC[8]; }; @@ -717,7 +808,7 @@ { Pid = p->tn; Det = p->det; - if (Pid == claimnr + if (pid_is_claim(Pid) && separate == 1) { fprintf(th, "extern uchar reached%d[];\n", Pid); #if 0 @@ -727,16 +818,16 @@ Pid, p->s->maxel, p->n->name); #endif fprintf(th, "extern short src_ln%d[];\n", Pid); + fprintf(th, "extern uchar *loopstate%d;\n", Pid); fprintf(th, "extern S_F_MAP src_file%d[];\n", Pid); fprintf(th, "#define endstate%d %d\n", Pid, p->s->last?p->s->last->seqno:0); - fprintf(th, "#define src_claim src_ln%d\n", claimnr); - return; } - if (Pid != claimnr + if (!pid_is_claim(Pid) && separate == 2) { fprintf(th, "extern short src_ln%d[];\n", Pid); + fprintf(th, "extern uchar *loopstate%d;\n", Pid); return; } @@ -744,15 +835,19 @@ fprintf(th, "\n#define nstates%d %d\t/* %s */\n", Pid, p->s->maxel, p->n->name); - if (Pid == claimnr) - fprintf(th, "#define nstates_claim nstates%d\n", Pid); if (Pid == eventmapnr) fprintf(th, "#define nstates_event nstates%d\n", Pid); - fprintf(th, "#define endstate%d %d\n", - Pid, p->s->last->seqno); - fprintf(tm, "\n /* PROC %s */\n", p->n->name); - fprintf(tb, "\n /* PROC %s */\n", p->n->name); + fprintf(th, "#define endstate%d %d\n", Pid, p->s->last?p->s->last->seqno:0); + + if (p->b == N_CLAIM || p->b == E_TRACE || p->b == N_TRACE) + { fprintf(tm, "\n /* CLAIM %s */\n", p->n->name); + fprintf(tb, "\n /* CLAIM %s */\n", p->n->name); + } + else + { fprintf(tm, "\n /* PROC %s */\n", p->n->name); + fprintf(tb, "\n /* PROC %s */\n", p->n->name); + } fprintf(tt, "\n /* proctype %d: %s */\n", Pid, p->n->name); fprintf(tt, "\n trans[%d] = (Trans **)", Pid); fprintf(tt, " emalloc(%d*sizeof(Trans *));\n\n", p->s->maxel); @@ -761,7 +856,6 @@ { fprintf(th, "\n#define in_s_scope(x_y3_) 0"); fprintf(tc, "\n#define in_r_scope(x_y3_) 0"); } - put_seq(p->s, 2, 0); if (Pid == eventmapnr) { fprintf(th, "\n\n"); @@ -947,8 +1041,8 @@ if (e->n->ntyp == D_STEP) { int inherit = (e->status&(ATOM|L_ATOM)); fprintf(tm, "\tcase %d: ", uniq++); - fprintf(tm, "/* STATE %d - line %d %s - [", - e->seqno, e->n->ln, e->n->fn->name); + fprintf(tm, "/* STATE %d - %s:%d - [", + e->seqno, e->n->fn->name, e->n->ln); comment(tm, e->n, 0); fprintf(tm, "] */\n\t\t"); @@ -1024,7 +1118,7 @@ struct CaseCache *nxt; } CaseCache; -CaseCache *casing[6]; +static CaseCache *casing[6]; static int identical(Lextok *p, Lextok *q) @@ -1076,6 +1170,9 @@ if (stopat) while (f && f->seqno != stopat) { f = findnext(f); + if (!f) + { break; + } switch (f->n->ntyp) { case GOTO: case '.': @@ -1084,8 +1181,7 @@ break; default: return f; - } - } + } } return (Element *) 0; } @@ -1107,18 +1203,16 @@ if (!stopat_a && !stopat_b) return 1; - for (;;) - { - f = advance(a, stopat_a); - g = advance(b, stopat_b); - if (!f && !g) - return 1; - if (f && g) - return identical(f->n, g->n); - else - return 0; - } - return 1; + f = advance(a, stopat_a); + g = advance(b, stopat_b); + + if (!f && !g) + return 1; + + if (f && g) + return identical(f->n, g->n); + + return 0; } static CaseCache * @@ -1258,18 +1352,18 @@ } static void -doforward(FILE *tm, Element *e) +doforward(FILE *tm_fd, Element *e) { FSM_use *u; - putstmnt(tm, e->n, e->seqno); + putstmnt(tm_fd, e->n, e->seqno); if (e->n->ntyp != ELSE && Det) - { fprintf(tm, ";\n\t\tif (trpt->o_pm&1)\n\t\t"); - fprintf(tm, "\tuerror(\"non-determinism in D_proctype\")"); + { fprintf(tm_fd, ";\n\t\tif (trpt->o_pm&1)\n\t\t"); + fprintf(tm_fd, "\tuerror(\"non-determinism in D_proctype\")"); } if (deadvar && !has_code) for (u = e->dead; u; u = u->nxt) - { fprintf(tm, ";\n\t\t/* dead %d: %s */ ", + { fprintf(tm_fd, ";\n\t\t/* dead %d: %s */ ", u->special, u->var->name); switch (u->special) { @@ -1281,10 +1375,10 @@ } if (e->n->ntyp != 'r') { XZ.sym = u->var; - fprintf(tm, "\n#ifdef HAS_CODE\n"); - fprintf(tm, "\t\tif (!readtrail)\n"); - fprintf(tm, "#endif\n\t\t\t"); - putname(tm, "", &XZ, 0, " = 0"); + fprintf(tm_fd, "\n#ifdef HAS_CODE\n"); + fprintf(tm_fd, "\t\tif (!readtrail)\n"); + fprintf(tm_fd, "#endif\n\t\t\t"); + putname(tm_fd, "", &XZ, 0, " = 0"); break; } /* else fall through */ case 1: /* dead after read -- add asgn of rval -- needs bup */ @@ -1292,20 +1386,20 @@ CnT[YZcnt]++; /* this step added bups */ if (multi_oval) { check_needed(); - fprintf(tm, "(trpt+1)->bup.ovals[%d] = ", + fprintf(tm_fd, "(trpt+1)->bup.ovals[%d] = ", multi_oval-1); multi_oval++; } else - fprintf(tm, "(trpt+1)->bup.oval = "); - putname(tm, "", &YZ[YZmax], 0, ";\n"); - fprintf(tm, "#ifdef HAS_CODE\n"); - fprintf(tm, "\t\tif (!readtrail)\n"); - fprintf(tm, "#endif\n\t\t\t"); - putname(tm, "", &YZ[YZmax], 0, " = 0"); + fprintf(tm_fd, "(trpt+1)->bup.oval = "); + putname(tm_fd, "", &YZ[YZmax], 0, ";\n"); + fprintf(tm_fd, "#ifdef HAS_CODE\n"); + fprintf(tm_fd, "\t\tif (!readtrail)\n"); + fprintf(tm_fd, "#endif\n\t\t\t"); + putname(tm_fd, "", &YZ[YZmax], 0, " = 0"); YZmax++; break; } } - fprintf(tm, ";\n\t\t"); + fprintf(tm_fd, ";\n\t\t"); } static int @@ -1412,7 +1506,7 @@ { int bupcase = 0, casenr = uniq, fromcache = 0; CaseCache *Cached = (CaseCache *) 0; Element *f, *g; - int j, nrbups, mark, target; + int j, nrbups, mark, ntarget; extern int ccache; mark = (e->status&ATOM); /* could lose atomicity in a merge chain */ @@ -1439,15 +1533,15 @@ fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno); if (ccache - && Pid != claimnr + && !pid_is_claim(Pid) && Pid != eventmapnr && (Cached = prev_case(e, Pid))) { bupcase = Cached->b; casenr = Cached->m; fromcache = 1; - fprintf(tm, "/* STATE %d - line %d %s - [", - e->seqno, e->n->ln, e->n->fn->name); + fprintf(tm, "/* STATE %d - %s:%d - [", + e->seqno, e->n->fn->name, e->n->ln); comment(tm, e->n, 0); fprintf(tm, "] (%d:%d - %d) same as %d (%d:%d - %d) */\n", e->merge_start, e->merge, e->merge_in, @@ -1457,8 +1551,8 @@ goto gotit; } - fprintf(tm, "\tcase %d: /* STATE %d - line %d %s - [", - uniq++, e->seqno, e->n->ln, e->n->fn->name); + fprintf(tm, "\tcase %d: /* STATE %d - %s:%d - [", + uniq++, e->seqno, e->n->fn->name, e->n->ln); comment(tm, e->n, 0); nrbups = (e->merge || e->merge_start) ? nrhops(e) : nr_bup(e); fprintf(tm, "] (%d:%d:%d - %d) */\n\t\t", @@ -1467,7 +1561,7 @@ if (nrbups > MAXMERGE-1) fatal("merge requires more than 256 bups", (char *)0); - if (e->n->ntyp != 'r' && Pid != claimnr && Pid != eventmapnr) + if (e->n->ntyp != 'r' && !pid_is_claim(Pid) && Pid != eventmapnr) fprintf(tm, "IfNotBlocked\n\t\t"); if (multi_needed != 0 || multi_undo != 0) @@ -1482,18 +1576,29 @@ memset(CnT, 0, sizeof(CnT)); YZmax = YZcnt = 0; -/* NEW 4.2.6 */ - if (Pid == claimnr) - { - fprintf(tm, "\n#if defined(VERI) && !defined(NP)\n\t\t"); - fprintf(tm, "{ static int reported%d = 0;\n\t\t", e->seqno); - /* source state changes in retrans and must be looked up in frm_st0[t->forw] */ +/* new 4.2.6, revised 6.0.0 */ + if (pid_is_claim(Pid)) + { fprintf(tm, "\n#if defined(VERI) && !defined(NP)\n"); +fprintf(tm, "#if NCLAIMS>1\n"); + fprintf(tm, "\t\t{ static int reported%d = 0;\n", e->seqno); + fprintf(tm, "\t\t int nn = (int) ((Pclaim *)this)->_n;\n\t\t"); fprintf(tm, " if (verbose && !reported%d)\n\t\t", e->seqno); - fprintf(tm, " { printf(\"depth %%d: Claim reached state %%d (line %%d)\\n\",\n\t\t"); - fprintf(tm, " depth, frm_st0[t->forw], src_claim[%d]);\n\t\t", e->seqno); + fprintf(tm, " {\tprintf(\"depth %%ld: Claim %%s (%%d), state %%d (line %%d)\\n\",\n\t\t"); + fprintf(tm, " \t\tdepth, procname[spin_c_typ[nn]], nn, "); + fprintf(tm, "(int) ((Pclaim *)this)->_p, src_claim[ (int) ((Pclaim *)this)->_p ]);\n\t\t"); fprintf(tm, " reported%d = 1;\n\t\t", e->seqno); fprintf(tm, " fflush(stdout);\n\t\t"); fprintf(tm, "} }\n"); +fprintf(tm, "#else\n"); + fprintf(tm, "{ static int reported%d = 0;\n\t\t", e->seqno); + fprintf(tm, " if (verbose && !reported%d)\n\t\t", e->seqno); + fprintf(tm, " { printf(\"depth %%d: Claim, state %%d (line %%d)\\n\",\n\t\t"); + fprintf(tm, " (int) depth, (int) ((Pclaim *)this)->_p, "); + fprintf(tm, "src_claim[ (int) ((Pclaim *)this)->_p ]);\n\t\t"); + fprintf(tm, " reported%d = 1;\n\t\t", e->seqno); + fprintf(tm, " fflush(stdout);\n\t\t"); + fprintf(tm, "} }\n"); +fprintf(tm, "#endif\n"); fprintf(tm, "#endif\n\t\t"); } /* end */ @@ -1504,32 +1609,32 @@ doforward(tm, e); if (e->merge_start) - target = e->merge_start; + ntarget = e->merge_start; else - target = e->merge; - - if (target) + ntarget = e->merge; + + if (ntarget) { f = e; more: if (f->n->ntyp == GOTO) { g = get_lab(f->n, 1); - if (g->seqno == target) + if (g->seqno == ntarget) f = g; else - f = huntele(g, f->status, target); + f = huntele(g, f->status, ntarget); } else f = f->nxt; - if (f && f->seqno != target) + if (f && f->seqno != ntarget) { if (!f->merge && !f->merge_single) { fprintf(tm, "/* stop at bad hop %d, %d */\n\t\t", - f->seqno, target); + f->seqno, ntarget); goto out; } fprintf(tm, "/* merge: "); comment(tm, f->n, 0); - fprintf(tm, "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, target); + fprintf(tm, "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, ntarget); fprintf(tm, "reached[%d][%d] = 1;\n\t\t", Pid, f->seqno); YZcnt++; lab_transfer(e, f); @@ -1547,8 +1652,8 @@ multi_needed = 0; didcase = 0; - if (target) - lastfirst(target, e, casenr); /* mergesteps only */ + if (ntarget) + lastfirst(ntarget, e, casenr); /* mergesteps only */ dobackward(e, casenr); /* the original step */ @@ -1758,8 +1863,8 @@ { fprintf(tt, "#if 0\n\t/* dead link: */\n"); deadlink = 1; if (verbose&32) - printf("spin: line %3d %s, Warning: condition is always false\n", - g->n->ln, g->n->fn?g->n->fn->name:""); + printf("spin: warning, %s:%d: condition is always false\n", + g->n->fn?g->n->fn->name:"", g->n->ln); } else deadlink = 0; if (0) printf(" settr %d %d\n", a, 0); @@ -1867,7 +1972,7 @@ case BREAK: if (e->nxt) { f = find_target(huntele(e->nxt, e->status, -1)); - break; /* 4.3.0 -- was missing */ + break; /* new 5.0 -- was missing */ } /* else fall through */ default: @@ -1888,6 +1993,26 @@ } static int +seq_has_el(Sequence *s, Element *g) /* new to version 5.0 */ +{ Element *f; + SeqList *h; + + for (f = s->frst; f; f = f->nxt) /* g in same atomic? */ + { if (f == g) + { return 1; + } + if (f->status & CHECK3) + { continue; + } + f->status |= CHECK3; /* protect against cycles */ + for (h = f->sub; h; h = h->nxt) + { if (h->this && seq_has_el(h->this, g)) + { return 1; + } } } + return 0; +} + +static int scan_seq(Sequence *s) { Element *f, *g; SeqList *h; @@ -1896,20 +2021,22 @@ { if ((f->status&CHECK2) || has_global(f->n)) return 1; - if (f->n->ntyp == GOTO) /* may reach other atomic */ - { -#if 0 - /* if jumping from an atomic without globals into - * one with globals, this does the wrong thing + if (f->n->ntyp == GOTO /* may exit or reach other atomic */ + && !(f->status & D_ATOM)) /* cannot jump from d_step */ + { /* consider jump from an atomic without globals into + * an atomic with globals * example by Claus Traulsen, 22 June 2007 */ g = target(f); +#if 1 + if (g && !seq_has_el(s, g)) /* not internal to this atomic/dstep */ + +#else if (g && !(f->status & L_ATOM) && !(g->status & (ATOM|L_ATOM))) #endif - { fprintf(tt, " /* mark-down line %d */\n", - f->n->ln); + { fprintf(tt, "\t/* mark-down line %d status %d = %d */\n", f->n->ln, f->status, (f->status & D_ATOM)); return 1; /* assume worst case */ } } for (h = f->sub; h; h = h->nxt) @@ -1937,9 +2064,25 @@ return result; } +static int +proc_is_safe(const Lextok *n) +{ ProcList *p; + /* not safe unless no local var inits are used */ + /* note that a local variable init could refer to a global */ + + for (p = rdy; p; p = p->nxt) + { if (strcmp(n->sym->name, p->n->name) == 0) + { /* printf("proc %s safety: %d\n", p->n->name, p->unsafe); */ + return (p->unsafe != 0); + } } +/* non_fatal("bad call to proc_is_safe", (char *) 0); */ + /* cannot happen */ + return 0; +} + int has_global(Lextok *n) -{ Lextok *v; extern int runsafe; +{ Lextok *v; if (!n) return 0; if (AllGlobal) return 1; /* global provided clause */ @@ -1975,7 +2118,8 @@ return 0; return 1; - case RUN: return 1-runsafe; + case RUN: + return proc_is_safe(n); case C_CODE: case C_EXPR: return glob_inline(n->sym->name); @@ -2021,7 +2165,7 @@ else if (IsGuard) fprintf(fd, "%s%s", NextLab[Level], str); else - fprintf(fd, "Uerror(\"block in step seq\")%s", str); + fprintf(fd, "Uerror(\"block in d_step seq\")%s", str); } #define cat0(x) putstmnt(fd,now->lft,m); fprintf(fd, x); \ @@ -2070,12 +2214,14 @@ else fprintf(fd, "((trpt->tau)&1)"); if (GenCode) - printf("spin: line %3d, warning: 'timeout' in d_step sequence\n", - lineno); + printf("spin: warning, %s:%d, 'timeout' in d_step sequence\n", + Fname->name, lineno); /* is okay as a guard */ break; case RUN: + if (now->sym == NULL) + Fatal("internal error pangen2.c", (char *) 0); if (claimproc && strcmp(now->sym->name, claimproc) == 0) fatal("claim %s, (not runnable)", claimproc); @@ -2087,16 +2233,15 @@ fatal("'run' in d_step sequence (use atomic)", (char *)0); - fprintf(fd,"addproc(%d", fproc(now->sym->name)); + fprintf(fd,"addproc(II, %d", fproc(now->sym->name)); for (v = now->lft, i = 0; v; v = v->rgt, i++) { cat2(", ", v->lft); } check_param_count(i, now); if (i > Npars) - { printf("\t%d parameters used, max %d expected\n", i, Npars); - fatal("too many parameters in run %s(...)", - now->sym->name); + { /* printf("\t%d parameters used, max %d expected\n", i, Npars); */ + fatal("too many parameters in run %s(...)", now->sym->name); } for ( ; i < Npars; i++) fprintf(fd, ", 0"); @@ -2180,7 +2325,7 @@ case 's': if (Pid == eventmapnr) - { fprintf(fd, "if ((ot == EVENT_TRACE && _tp != 's') "); + { fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 's') "); putname(fd, "|| _qid+1 != ", now->lft, m, ""); for (v = now->rgt, i=0; v; v = v->rgt, i++) { if (v->lft->ntyp != CONST @@ -2208,10 +2353,16 @@ break; } if (has_xu) - { fprintf(fd, "\n#ifndef XUSAFE\n\t\t"); - putname(fd, "if (q_claim[", now->lft, m, "]&2) "); - putname(fd, "q_S_check(", now->lft, m, ", II);"); - fprintf(fd, "\n#endif\n\t\t"); + { fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t"); + putname(fd, "if (q_claim[", now->lft, m, "]&2)\n\t\t"); + putname(fd, "{ q_S_check(", now->lft, m, ", II);\n\t\t"); + fprintf(fd, "}\n"); + if (has_sorted && now->val == 1) + { putname(fd, "\t\tif (q_claim[", now->lft, m, "]&1)\n\t\t"); /* &1 iso &2 */ + fprintf(fd, "{ uerror(\"sorted send on xr channel violates po reduction\");\n\t\t"); + fprintf(fd, "}\n"); + } + fprintf(fd, "#endif\n\t\t"); } fprintf(fd, "if (q_%s", (u_sync > 0 && u_async == 0)?"len":"full"); @@ -2256,9 +2407,9 @@ printf(" %d msg parameters sent, %d expected\n", i, Mpars); fatal("too many pars in send", ""); } - for ( ; i < Mpars; i++) + for (j = i; i < Mpars; i++) fprintf(fd, ", 0"); - fprintf(fd, ")"); + fprintf(fd, ", %d)", j); if (u_sync) { fprintf(fd, ";\n\t\t"); if (u_async) @@ -2274,7 +2425,7 @@ case 'r': if (Pid == eventmapnr) - { fprintf(fd, "if ((ot == EVENT_TRACE && _tp != 'r') "); + { fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 'r') "); putname(fd, "|| _qid+1 != ", now->lft, m, ""); for (v = now->rgt, i=0; v; v = v->rgt, i++) { if (v->lft->ntyp != CONST @@ -2342,10 +2493,13 @@ break; } if (has_xu) - { fprintf(fd, "\n#ifndef XUSAFE\n\t\t"); - putname(fd, "if (q_claim[", now->lft, m, "]&1) "); - putname(fd, "q_R_check(", now->lft, m, ", II);"); - fprintf(fd, "\n#endif\n\t\t"); + { fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t"); + putname(fd, "if (q_claim[", now->lft, m, "]&1)\n\t\t"); + putname(fd, "{ q_R_check(", now->lft, m, ", II);\n\t\t"); + if (has_random && now->val != 0) + fprintf(fd, " uerror(\"rand receive on xr channel violates po reduction\");\n\t\t"); + fprintf(fd, "}\n"); + fprintf(fd, "#endif\n\t\t"); } if (u_sync) { if (now->val >= 2) @@ -2415,6 +2569,7 @@ fprintf(fd, ", 0, 0"); fprintf(fd, "))) "); Bailout(fd, ""); + if (!GenCode) { fprintf(fd, ";\n\t\t"); if (multi_oval) { check_needed(); @@ -2424,6 +2579,7 @@ } else fprintf(fd, "(trpt+1)->bup.oval = "); fprintf(fd, "XX"); + } } if (has_enabled) @@ -2485,7 +2641,7 @@ && v->lft->ntyp != EVAL && v->lft->sym && v->lft->sym->type != STRUCT /* not a struct */ - && v->lft->sym->nel == 1 /* not an array */ + && (v->lft->sym->nel == 1 && v->lft->sym->isarray == 0) /* not array */ && strcmp(v->lft->sym->name, "_") != 0) for (w = v->rgt; w; w = w->rgt) if (v->lft->sym == w->lft->sym) @@ -2501,6 +2657,7 @@ if (v->lft->ntyp != CONST && v->lft->ntyp != EVAL + && v->lft->sym != NULL && strcmp(v->lft->sym->name, "_") != 0) { nocast=1; _isok++; @@ -2515,6 +2672,7 @@ if (v->lft->ntyp != CONST && v->lft->ntyp != EVAL + && v->lft->sym != NULL && strcmp(v->lft->sym->name, "_") != 0 && (v->lft->ntyp != NAME || v->lft->sym->type != CHAN)) @@ -2748,14 +2906,16 @@ break; case C_CODE: - fprintf(fd, "/* %s */\n\t\t", now->sym->name); + if (now->sym) + fprintf(fd, "/* %s */\n\t\t", now->sym->name); if (has_enabled) fprintf(fd, "if (TstOnly) return 1;\n\t\t"); - if (!GenCode) /* not in d_step */ - { fprintf(fd, "sv_save();\n\t\t"); - /* store the old values for reverse moves */ - } - plunk_inline(fd, now->sym->name, 1); + + if (now->sym) + plunk_inline(fd, now->sym->name, 1, GenCode); + else + Fatal("internal error pangen2.c", (char *) 0); + if (!GenCode) { fprintf(fd, "\n"); /* state changed, capture it */ fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n"); @@ -2768,7 +2928,7 @@ if (has_enabled) fprintf(fd, "if (TstOnly) return 1;\n\t\t"); - cat3("assert(", now->lft, ", "); + cat3("spin_assert(", now->lft, ", "); terse = nocast = 1; cat3("\"", now->lft, "\", II, tt, t)"); terse = nocast = 0; @@ -2797,16 +2957,30 @@ break; default: - printf("spin: bad node type %d (.m) - line %d\n", - now->ntyp, now->ln); + printf("spin: error, %s:%d, bad node type %d (.m)\n", + now->fn->name, now->ln, now->ntyp); fflush(tm); alldone(1); } } +char * +simplify_name(char *s) +{ char *t = s; + + if (!old_scope_rules) + { while (*t == '_' || isdigit((int)*t)) + { t++; + } } + + return t; +} + void putname(FILE *fd, char *pre, Lextok *n, int m, char *suff) /* varref */ { Symbol *s = n->sym; + char *ptr; + lineno = n->ln; Fname = n->fn; if (!s) @@ -2824,7 +2998,7 @@ if (!s->type) { if (strcmp(pre, ".") != 0) - non_fatal("undeclared variable '%s'", s->name); + fatal("undeclared variable '%s'", s->name); s->type = INT; } @@ -2845,22 +3019,29 @@ fatal("attempt to read value of '_'", 0); } } - if (withprocname - && s->context - && strcmp(pre, ".")) - fprintf(fd, "%s:", s->context->name); + ptr = s->name; + + if (s->type != PREDEF) /* new 6.0.2 */ + { if (withprocname + && s->context + && strcmp(pre, ".")) + { fprintf(fd, "%s:", s->context->name); + ptr = simplify_name(ptr); + } else + { if (terse) + { ptr = simplify_name(ptr); + } } } if (evalindex != 1) - fprintf(fd, "%s", s->name); - - if (s->nel != 1) + fprintf(fd, "%s", ptr); + + if (s->nel > 1 || s->isarray == 1) { if (no_arrays) - { - non_fatal("ref to array element invalid in this context", - (char *)0); - printf("\thint: instead of, e.g., x[rs] qu[3], use\n"); - printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n"); - printf("\tand use nm_3 in sends/recvs instead of qu[3]\n"); + { non_fatal("ref to array element invalid in this context", + (char *)0); + printf("\thint: instead of, e.g., x[rs] qu[3], use\n"); + printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n"); + printf("\tand use nm_3 in sends/recvs instead of qu[3]\n"); } /* an xr or xs reference to an array element * becomes an exclusion tag on the array itself - @@ -2885,11 +3066,27 @@ || (!n->lft && s->nel > 0)) { cat3("[", n->lft, "]"); } else - { cat3("[ Index(", n->lft, ", "); + { /* attempt to catch arrays that are indexed with an array element in the same array + * this causes trouble in the verifier in the backtracking + * e.g., restoring a[?] in the assignment: a [a[1]] = x where a[1] == 1 + * but it is hard when the array is inside a structure, so the names dont match + */ +#if 0 + if (n->lft->ntyp == NAME) + { printf("%4d: Basename %s index %s\n", + n->lft->ln, s->name, n->lft->sym->name); + } +#endif + cat3("[ Index(", n->lft, ", "); fprintf(fd, "%d) ]", s->nel); - } - } - } + } } + } else + { if (n->lft /* effectively a scalar, but with an index */ + && (n->lft->ntyp != CONST + || n->lft->val != 0)) + { fatal("ref to scalar '%s' using array index", (char *) ptr); + } } + if (s->type == STRUCT && n->rgt && n->rgt->lft) { putname(fd, ".", n->rgt->lft, m, ""); } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen2.h --- a/sys/src/cmd/spin/pangen2.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen2.h Tue Mar 06 23:34:10 2012 +0100 @@ -1,6 +1,6 @@ /***** spin: pangen2.h *****/ -/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* Copyright (c) 1989-2007 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 */ @@ -8,20 +8,7 @@ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ - -static char *Nvr1[] = { /* allow separate compilation */ - "#ifdef VERI", - "void", - "check_claim(int st)", - "{", - " if (st == endclaim)", - " uerror(\"claim violated!\");", - " if (stopstate[VERI][st])", - " uerror(\"end state in claim reached\");", - "}", - "#endif", - 0, -}; +/* (c) 2007: small additions for V5.0 to support multi-core verifications */ static char *Pre0[] = { "#ifdef SC", @@ -38,11 +25,12 @@ "#include ", "#else", "#include ", - "#include ", /* new 4.3.0 */ + "#include ", "#endif", "#include ", /* defines off_t */ "#include ", "#include ", + "#define Offsetof(X, Y) ((unsigned long)(&(((X *)0)->Y)))", "#ifndef max", "#define max(a,b) (((a)<(b)) ? (b) : (a))", @@ -55,10 +43,13 @@ static char *Preamble[] = { + "#ifdef RANDOMIZE", + " #define T_RAND RANDOMIZE", + "#endif", "#ifdef CNTRSTACK", - "#define onstack_now() (LL[trpt->j6] && LL[trpt->j7])", - "#define onstack_put() LL[trpt->j6]++; LL[trpt->j7]++", - "#define onstack_zap() LL[trpt->j6]--; LL[trpt->j7]--", + " #define onstack_now() (LL[trpt->j6] && LL[trpt->j7])", + " #define onstack_put() LL[trpt->j6]++; LL[trpt->j7]++", + " #define onstack_zap() LL[trpt->j6]--; LL[trpt->j7]--", "#endif", "#if !defined(SAFETY) && !defined(NOCOMP)", @@ -68,13 +59,13 @@ * S_A remembers how many leading bytes in the sv * are used for these markers + fairness bits */ - "#define V_A (((now._a_t&1)?2:1) << (now._a_t&2))", - "#define A_V (((now._a_t&1)?1:2) << (now._a_t&2))", - "int S_A = 0;", + " #define V_A (((now._a_t&1)?2:1) << (now._a_t&2))", + " #define A_V (((now._a_t&1)?1:2) << (now._a_t&2))", + " int S_A = 0;", "#else", - "#define V_A 0", - "#define A_V 0", - "#define S_A 0", + " #define V_A 0", + " #define A_V 0", + " #define S_A 0", "#endif", "#ifdef MA", @@ -93,32 +84,62 @@ " }", "#endif", "#endif", + + "#ifndef NO_V_PROVISO", + "#define V_PROVISO", + "#endif", + "#if !defined(NO_RESIZE) && !defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(SPACE) && NCORE==1", + " #define AUTO_RESIZE", + "#endif", + "", "struct H_el {", " struct H_el *nxt;", "#ifdef FULLSTACK", " unsigned int tagged;", - "#if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)", + " #if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)", " unsigned int proviso;", /* uses just 1 bit 0/1 */ - "#endif", + " #endif", "#endif", "#if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))", " unsigned long st_id;", "#endif", - "#ifdef COLLAPSE", - "#if VECTORSZ<65536", - " unsigned short ln;", /* length of vector */ - "#else", - " unsigned long ln;", /* length of vector */ - "#endif", - "#endif", "#if !defined(SAFETY) || defined(REACH)", " unsigned int D;", "#endif", - " unsigned state;", + "#ifdef BCS", + " #ifndef CONSERVATIVE", + " #define CONSERVATIVE 1 /* good for up to 8 processes */", + " #endif", + " #ifdef CONSERVATIVE", + " #if CONSERVATIVE <= 0 || CONSERVATIVE>32", + " #error sensible values for CONSERVATIVE are 1..32 (256/8 = 32)", + " #endif", + " uchar ctx_pid[CONSERVATIVE];", /* pids setting lowest value */ + " #endif", + " uchar ctx_low;", /* lowest nr of context switches seen so far */ + "#endif", + "#if NCORE>1", + " /* could cost 1 extra word: 4 bytes if 32-bit and 8 bytes if 64-bit */", + " #ifdef V_PROVISO", + " uchar cpu_id; /* id of cpu that created the state */", + " #endif", + "#endif", + "#ifdef COLLAPSE", + " #if VECTORSZ<65536", + " unsigned short ln;", /* length of vector */ + " #else", + " unsigned long ln;", /* length of vector */ + " #endif", + "#endif", + "#if defined(AUTO_RESIZE) && !defined(BITSTATE)", + " unsigned long m_K1;", + "#endif", + " unsigned long state;", "} **H_tab, **S_Tab;\n", "typedef struct Trail {", " int st; /* current state */", + " int o_tt;", " uchar pr; /* process id */", " uchar tau; /* 8 bit-flags */", " uchar o_pm; /* 8 more bit-flags */", @@ -142,6 +163,9 @@ " o_pm&64 -> the current proc applied rule2", " o_pm&128 -> a fairness, dummy move - all procs blocked", "#endif", + "#ifdef NSUCC", + " uchar n_succ; /* nr of successor states */", + "#endif", "#if defined(FULLSTACK) && defined(MA) && !defined(BFS)", " uchar proviso;", "#endif", @@ -150,23 +174,22 @@ "#endif", " uchar o_m;", "#ifdef EVENT_TRACE", - "#if nstates_event<256", - " uchar o_event;", - "#else", - " unsigned short o_event;", - "#endif", + " #if nstates_event<256", + " uchar o_event;", + " #else", + " unsigned short o_event;", + " #endif", "#endif", - " int o_tt;", "#ifndef BFS", " short o_To;", - "#ifdef RANDOMIZE", - " short oo_i;", - "#endif", + " #ifdef T_RAND", + " short oo_i;", + " #endif", "#endif", "#if defined(HAS_UNLESS) && !defined(BFS)", " int e_state; /* if escape trans - state of origin */", "#endif", - "#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS)", + "#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS) || (NCORE>1)", " struct H_el *ostate; /* pointer to stored state */", "#endif", /* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY, uses LL[] */ @@ -174,6 +197,23 @@ " long j6, j7;", "#endif", " Trans *o_t;", /* transition fct, next state */ + + "#if !defined(BFS) && !defined(TRIX_ORIG)", + " char *p_bup;", + " char *q_bup;", + "#endif", + + "#ifdef BCS", + " unsigned short sched_limit;", + " unsigned char bcs; /* phase 1 or 2, or forced 4 */", + " unsigned char b_pno; /* preferred pid */", + "#endif", + + "#ifdef P_RAND", /* process scheduling randomization */ + " unsigned char p_left; /* nr of procs left to explore */", + " short p_skip; /* to find starting point in list */", + "#endif", + "#ifdef HAS_SORTED", " short ipt;", /* insertion slot in q */ "#endif", @@ -188,6 +228,22 @@ "uchar *this;", "long maxdepth=10000;", "long omaxdepth=10000;", + "#ifdef BCS", + " /* bitflags in trpt->bcs */", + " #define B_PHASE1 1", + " #define B_PHASE2 2", + " #define B_FORCED 4", + "int sched_max = 0;", + "#endif", + "#ifdef PERMUTED", + " uchar permuted = 1;", + "#else", + " uchar permuted = 0;", + "#endif", + "double quota; /* time limit */", + "#if NCORE>1", + "long z_handoff = -1;", + "#endif", "#ifdef SC", /* stack cycling */ "char *stackfile;", "#endif", @@ -195,7 +251,10 @@ "uchar HASH_NR = 0;", "", "double memcnt = (double) 0;", - "double memlim = (double) (1<<30);", + "double memlim = (double) (1<<30); /* 1 GB */", + "#if NCORE>1", + "double mem_reserved = (double) 0;", + "#endif", "", "/* for emalloc: */", "static char *have;", @@ -203,6 +262,62 @@ "static double fragment = (double) 0;", "static unsigned long grow;", "", +#if 1 + "unsigned int HASH_CONST[] = {", + " /* asuming 4 bytes per int */", + " 0x100d4e63, 0x0fc22f87,", + " 0x3ff0c3ff, 0x38e84cd7,", + " 0x02b148e9, 0x98b2e49d,", + " 0xb616d379, 0xa5247fd9,", + " 0xbae92a15, 0xb91c8bc5,", + " 0x8e5880f3, 0xacd7c069,", + " 0xb4c44bb3, 0x2ead1fb7,", + " 0x8e428171, 0xdbebd459,", + " 0x00400007, 0x04c11db7,", + " 0x828ae611, 0x6cb25933,", + " 0x86cdd651, 0x9e8f5f21,", + " 0xd5f8d8e7, 0x9c4e956f,", + " 0xb5cf2c71, 0x2e805a6d,", + " 0x33fc3a55, 0xaf203ed1,", + " 0xe31f5909, 0x5276db35,", + " 0x0c565ef7, 0x273d1aa5,", + " 0x8923b1dd, 0xa9acaac5,", + " 0xd1f69207, 0xedfd944b,", + " 0x9a68e46b, 0x5355e13f,", + " 0x7eeb44f9, 0x932beea9,", + " 0x330c4cd3, 0x87f34e5f,", + " 0x1b5851b7, 0xb9ca6447,", + " 0x58f96a8f, 0x1b3b5307,", + " 0x31c387b3, 0xf35f0f35,", + " 0xa0acc4df, 0xf3140303,", + " 0x2446245d, 0xe4b8f4ef,", + " 0x5c007383, 0x68e648af,", + " 0x1814fba7, 0xcdf731b5,", + " 0xd09ccb4b, 0xb92d0eff,", + " 0xcc3c6b67, 0xd3af6a57,", + " 0xf44fc3f5, 0x5bb67623,", + " 0xaeb9c953, 0x5e0ac739,", + " 0x3a7fda09, 0x5edf39eb,", + " 0x661eefd9, 0x6423f0d1,", + " 0x910fe413, 0x9ec92297,", + " 0x4bd8159d, 0xa7b16ee1,", + " 0x89d484e9, 0x7f305cb3,", + " 0xc5f303e7, 0x415deeef,", + " 0x09986f89, 0x7e9c4117,", + " 0x0b7cbedb, 0xf9ed7561,", + " 0x7a20ac99, 0xf05adef3,", + " 0x5893d75b, 0x44d73327,", + " 0xb583c873, 0x324d2145,", + " 0x7fa3829b, 0xe4b47a23,", + " 0xe256d94f, 0xb1fd8959,", + " 0xe561a321, 0x1435ac09,", + " 0xdd62408b, 0x02ec0bcb,", + " 0x5469b785, 0x2f4f50bb,", + " 0x20f19395, 0xf96ba085,", + " 0x2381f937, 0x768e2a11,", + " 0", + "};", +#else "unsigned int HASH_CONST[] = {", " /* asuming 4 bytes per int */", " 0x88888EEF, 0x00400007,", @@ -224,9 +339,23 @@ " 0x273d1aa5, 0x8923b1dd,", " 0", "};", - "int mreached=0, done=0, errors=0, Nrun=1;", +#endif + "#if NCORE>1", + "extern int core_id;", + "#endif", + "long mreached=0;", + "int done=0, errors=0, Nrun=1;", + "int c_init_done=0;", + "char *c_stack_start = (char *) 0;", "double nstates=0, nlinks=0, truncs=0, truncs2=0;", "double nlost=0, nShadow=0, hcmp=0, ngrabs=0;", + "#ifdef PUTPID", + "char *progname;", + "#endif", + "#if defined(ZAPH) && defined(BITSTATE)", + "double zstates = 0;", + "#endif", + "int c_init_run;", "#ifdef BFS", "double midrv=0, failedrv=0, revrv=0;", "#endif", @@ -236,9 +365,11 @@ "long Ccheck=0, Cholds=0;", "int a_cycles=0, upto=1, strict=0, verbose = 0, signoff = 0;", "#ifdef HAS_CODE", - "int gui = 0, coltrace = 0, readtrail = 0, whichtrail = 0, onlyproc = -1, silent = 0;", + "int gui = 0, coltrace = 0, readtrail = 0;", + "int whichtrail = 0, whichclaim = -1, onlyproc = -1, silent = 0;", + "char *claimname;", "#endif", - "int state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;", + "int state_tables=0, fairness=0, no_rck=0, Nr_Trails=0, dodot=0;", "char simvals[128];", "#ifndef INLINE", "int TstOnly=0;", @@ -251,7 +382,7 @@ "#endif", "int hmax=0, svmax=0, smax=0;", "int Maxbody=0, XX;", - "uchar *noptr; /* used by macro Pptr(x) */", + "uchar *noptr, *noqptr; /* used by Pptr(x) and Qptr(x) */", "#ifdef VAR_RANGES", "void logval(char *, int);", "void dumpranges(void);", @@ -264,8 +395,15 @@ "extern int dfa_store(uchar *);", "unsigned int maxgs = 0;", "#endif", - - "State comp_now; /* compressed state vector */", + "", + "#ifdef ALIGNED", + " State comp_now __attribute__ ((aligned (8)));", + " /* gcc 64-bit aligned for Itanium2 systems */", + " /* MAJOR runtime penalty if not used on those systems */", + "#else", + " State comp_now; /* compressed state vector */", + "#endif", + "", "State comp_msk;", "uchar *Mask = (uchar *) &comp_msk;", "#ifdef COLLAPSE", @@ -273,23 +411,30 @@ "static char *scratch = (char *) &comp_tmp;", "#endif", - "Stack *stack; /* for queues, processes */", + "_Stack *stack; /* for queues, processes */", "Svtack *svtack; /* for old state vectors */", "#ifdef BITSTATE", - "static unsigned hfns = 3; /* new default */", + "static unsigned int hfns = 3; /* new default */", "#endif", - "static unsigned long j1;", + "static unsigned long j1_spin; /* 5.2.1: avoid nameclash with math.h */", "static unsigned long K1, K2;", "static unsigned long j2, j3, j4;", "#ifdef BITSTATE", -#ifndef POWOW "static long udmem;", -#endif "#endif", "static long A_depth = 0;", - "long depth = 0;", /* not static to support -S2 option, but possible clash with embedded code */ - "static uchar warned = 0, iterative = 0, like_java = 0, every_error = 0;", + "long depth = 0;", + /* depth: not static to support -S2, but possible clash with embedded code */ + "#if NCORE>1", + "long nr_handoffs = 0;", + "#endif", + "static uchar warned = 0, iterative = 0, exclusive = 0, like_java = 0, every_error = 0;", "static uchar noasserts = 0, noends = 0, bounded = 0;", + + "#if defined(T_RAND) || defined(P_RAND) || defined(RANDSTOR)", + "unsigned int s_rand = 123; /* default seed */", + "#endif", + "#if SYNC>0 && ASYNC==0", "void set_recvs(void);", "int no_recvs(int);", @@ -304,15 +449,13 @@ "#ifdef BITSTATE", "int (*bstore)(char *, int);", "int bstore_reg(char *, int);", -#ifndef POWOW "int bstore_mod(char *, int);", -#endif "#endif", "void active_procs(void);", "void cleanup(void);", "void do_the_search(void);", "void find_shorter(int);", - "void iniglobals(void);", + "void iniglobals(int);", "void stopped(int);", "void wrapup(void);", "int *grab_ints(int);", @@ -425,9 +568,9 @@ "}", "#endif", "void", - "retrans(int n, int m, int is, short srcln[], uchar reach[])", + "retrans(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])", " /* process n, with m states, is=initial state */", - "{ Trans *T0, *T1, *T2, *T3;", + "{ Trans *T0, *T1, *T2, *T3, *T4, *T5;", " int i, k;", "#ifndef NOREDUCE", " int g, h, j, aa;", @@ -436,7 +579,7 @@ " int p;", "#endif", " if (state_tables >= 4)", - " { printf(\"STEP 1 proctype %%s\\n\", ", + " { printf(\"STEP 1 %%s\\n\", ", " procname[n]);", " for (i = 1; i < m; i++)", " for (T0 = trans[n][i]; T0; T0 = T0->nxt)", @@ -477,7 +620,7 @@ " } while (cnt);", " if (state_tables >= 3)", - " { printf(\"STEP 2 proctype %%s\\n\", ", + " { printf(\"STEP 2 %%s\\n\", ", " procname[n]);", " for (i = 1; i < m; i++)", " for (T0 = trans[n][i]; T0; T0 = T0->nxt)", @@ -490,7 +633,9 @@ "#if 0", " printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",", " T1->st, T1->forw, i);", - "#endif", + "#endif", /* pull linenumber ref as well: */ + " srcln[i] = srcln[T1->st]; /* Oyvind Teig, 5.2.0 */", + "", " if (!trans[n][T1->st]) continue;", " T0 = cpytr(trans[n][T1->st]);", " trans[n][i] = T0;", @@ -502,6 +647,7 @@ " printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",", " T1->st, T1->forw, i);", "#endif", + " /* srcln[i] = srcln[T1->st]; gh: not useful */", " if (!trans[n][T1->st]) continue;", " T0->nxt = cpytr(trans[n][T1->st]);", " T0 = T0->nxt;", @@ -509,7 +655,7 @@ " imed(T0, T1->st, n, i);", " } } }", " if (state_tables >= 2)", - " { printf(\"STEP 3 proctype %%s\\n\", ", + " { printf(\"STEP 3 %%s\\n\", ", " procname[n]);", " for (i = 1; i < m; i++)", " for (T0 = trans[n][i]; T0; T0 = T0->nxt)", @@ -525,8 +671,8 @@ " * and prepend them to the transition-", " * list of state i", " */", - " if (!like_java) /* the default */", - " { for (T0 = trans[n][i]; T0; T0 = T0->nxt)", + " if (!like_java) /* the default */", + " { for (T0 = trans[n][i]; T0; T0 = T0->nxt)", " for (k = HAS_UNLESS-1; k >= 0; k--)", " { if (p = T0->escp[k])", " for (T1 = trans[n][p]; T1; T1 = T1->nxt)", @@ -537,9 +683,8 @@ " T2->nxt = trans[n][i];", " trans[n][i] = T2;", " } }", - " } else /* outermost unless checked first */", - " { Trans *T4;", - " T4 = T3 = (Trans *) 0;", + " } else /* outermost unless checked first */", + " { T4 = T3 = (Trans *) 0;", " for (T0 = trans[n][i]; T0; T0 = T0->nxt)", " for (k = HAS_UNLESS-1; k >= 0; k--)", " { if (p = T0->escp[k])", @@ -557,22 +702,21 @@ " { T3->nxt = trans[n][i];", " trans[n][i] = T4;", " }", - " }", + " }", " }", "#endif", "#ifndef NOREDUCE", " for (i = 1; i < m; i++)", - " {", - " if (a_cycles)", + " { if (a_cycles)", " { /* moves through these states are visible */", - "#if PROG_LAB>0 && defined(HAS_NP)", + " #if PROG_LAB>0 && defined(HAS_NP)", " if (progstate[n][i])", " goto degrade;", " for (T1 = trans[n][i]; T1; T1 = T1->nxt)", " if (progstate[n][T1->st])", " goto degrade;", - "#endif", + " #endif", " if (accpstate[n][i] || visstate[n][i])", " goto degrade;", " for (T1 = trans[n][i]; T1; T1 = T1->nxt)", @@ -668,19 +812,43 @@ " continue;", " stopstate[n][T2->st] = 1;", " }", - " if (state_tables)", - " { printf(\"proctype \");", - " if (!strcmp(procname[n], \":init:\"))", - " printf(\"init\\n\");", - " else", - " printf(\"%%s\\n\", procname[n]);", + " if (state_tables && !verbose)", + " { if (dodot)", + " { char buf[256], *q = buf, *p = procname[n];", + " while (*p != '\\0')", + " { if (*p != ':')", + " { *q++ = *p;", + " }", + " p++;", + " }", + " *q = '\\0';", + " printf(\"digraph \");", + " switch (Btypes[n]) {", + " case I_PROC: printf(\"init {\\n\"); break;", + " case N_CLAIM: printf(\"claim_%%s {\\n\", buf); break;", + " case E_TRACE: printf(\"notrace {\\n\"); break;", + " case N_TRACE: printf(\"trace {\\n\"); break;", + " default: printf(\"p_%%s {\\n\", buf); break;", + " }", + " printf(\"size=\\\"8,10\\\";\\n\");", + " printf(\" GT [shape=box,style=dotted,label=\\\"%%s\\\"];\\n\", buf);", + " } else", + " { switch (Btypes[n]) {", + " case I_PROC: printf(\"init\\n\"); break;", + " case N_CLAIM: printf(\"claim %%s\\n\", procname[n]); break;", + " case E_TRACE: printf(\"notrace assertion\\n\"); break;", + " case N_TRACE: printf(\"trace assertion\\n\"); break;", + " default: printf(\"proctype %%s\\n\", procname[n]); break;", + " } }", " for (i = 1; i < m; i++)", - " reach[i] = 1;", + " { reach[i] = 1;", + " }", " tagtable(n, m, is, srcln, reach);", + " if (dodot) printf(\"}\\n\");", " } else", " for (i = 1; i < m; i++)", " { int nrelse;", - " if (strcmp(procname[n], \":never:\") != 0)", + " if (Btypes[n] != N_CLAIM)", " { for (T0 = trans[n][i]; T0; T0 = T0->nxt)", " { if (T0->st == i", " && strcmp(T0->tp, \"(1)\") == 0)", @@ -703,17 +871,75 @@ " printf(\" 'else' stmnts\\n\");", " pan_exit(1);", " } }", - " if (!state_tables && strcmp(procname[n], \":never:\") == 0)", - " { int h = 0;", + "#ifndef LOOPSTATE", + " if (state_tables)", + "#endif", + " do_dfs(n, m, is, srcln, reach, lstate);", + "#ifdef T_REVERSE", + " /* process n, with m states, is=initial state -- reverse list */", + " if (!state_tables && Btypes[n] != N_CLAIM)", + " { for (i = 1; i < m; i++)", /* for each state */ + " { Trans *Tx = (Trans *) 0; /* list of escapes */", + " Trans *Ty = (Trans *) 0; /* its tail element */", + " T1 = (Trans *) 0; /* reversed list */", + " T2 = (Trans *) 0; /* its tail */", + " T3 = (Trans *) 0; /* remembers possible 'else' */", + "", + " /* find unless-escapes, they should go first */", + " T4 = T5 = T0 = trans[n][i];", + "#ifdef HAS_UNLESS", + " while (T4 && T4->e_trans) /* escapes are first in orig list */", + " { T5 = T4; /* remember predecessor */", + " T4 = T4->nxt;", + " }", + "#endif", + " /* T4 points to first non-escape, T5 to its parent, T0 to original list */", + " if (T4 != T0) /* there was at least one escape */", + " { T3 = T5->nxt; /* start of non-escapes */", + " T5->nxt = (Trans *) 0; /* separate */", + " Tx = T0; /* start of the escapes */", + " Ty = T5; /* its tail */", + " T0 = T3; /* the rest, to be reversed */", + " }", + " /* T0 points to first non-escape, Tx to the list of escapes, Ty to its tail */", + "", + " /* first tail-add non-escape transitions, reversed */", + " T3 = (Trans *) 0;", /* remember a possible 'else' */ + " for (T5 = T0; T5; T5 = T4)", + " { T4 = T5->nxt;", + "#ifdef HAS_UNLESS", + " if (T5->e_trans)", + " { printf(\"error: cannot happen!\\n\");", + " continue;", + " }", + "#endif", + " if (strcmp(T5->tp, \"else\") == 0)", + " { T3 = T5;", + " T5->nxt = (Trans *) 0;", + " } else", + " { T5->nxt = T1;", + " if (!T1) { T2 = T5; }", + " T1 = T5;", + " } }", + " /* T3 points to a possible else, which is removed from the list */", + " /* T1 points to the reversed list so far (without escapes) */", + " /* T2 points to the tail element -- where the else should go */", + " if (T2 && T3) { T2->nxt = T3; } /* add else */", + "", + " /* add in the escapes, to that they appear at the front */", + " if (Tx && Ty) { Ty->nxt = T1; T1 = Tx; }", + "", + " trans[n][i] = T1;", + " /* reversed, with escapes first and else last */", + " } }", + " if (state_tables && verbose)", + " { printf(\"FINAL proctype %%s\\n\", ", + " procname[n]);", " for (i = 1; i < m; i++)", " for (T0 = trans[n][i]; T0; T0 = T0->nxt)", - " if (T0->forw > h) h = T0->forw;", - " h++;", - " frm_st0 = (short *) emalloc(h * sizeof(short));", - " for (i = 1; i < m; i++)", - " for (T0 = trans[n][i]; T0; T0 = T0->nxt)", - " frm_st0[T0->forw] = i;", + " crack(n, i, T0, srcln);", " }", + "#endif", "}", "void", "imed(Trans *T, int v, int n, int j) /* set intermediate state */", @@ -731,7 +957,12 @@ " reach[is] = 0;", " if (state_tables)", " for (z = trans[n][is]; z; z = z->nxt)", - " crack(n, is, z, srcln);", + " { if (dodot)", + " dot_crack(n, is, z);", + " else", + " crack(n, is, z, srcln);", + " }", + "", " for (z = trans[n][is]; z; z = z->nxt)", " {", "#ifdef HAS_UNLESS", @@ -748,6 +979,44 @@ " }", "}", "void", + "dfs_table(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])", + "{ Trans *z;\n", + " if (is >= m || is <= 0 || !trans[n][is])", + " return;", + " if ((reach[is] & (4|8|16)) != 0)", + " { if ((reach[is] & (8|16)) == 16) /* on stack, not yet recorded */", + " { lstate[is] = 1;", + " reach[is] |= 8; /* recorded */", + " if (state_tables && verbose)", + " { printf(\"state %%d line %%d is a loopstate\\n\", is, srcln[is]);", + " } }", + " return;", + " }", + " reach[is] |= (4|16); /* visited | onstack */", + " for (z = trans[n][is]; z; z = z->nxt)", + " {", + "#ifdef HAS_UNLESS", + " int i, j;", + "#endif", + " dfs_table(n, m, z->st, srcln, reach, lstate);", + "#ifdef HAS_UNLESS", + " for (i = 0; i < HAS_UNLESS; i++)", + " { j = trans[n][is]->escp[i];", + " if (!j) break;", + " dfs_table(n, m, j, srcln, reach, lstate);", + " }", + "#endif", + " }", + " reach[is] &= ~16; /* no longer on stack */", + "}", + "void", + "do_dfs(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])", + "{ int i;", + " dfs_table(n, m, is, srcln, reach, lstate);", + " for (i = 0; i < m; i++)", + " reach[i] &= ~(4|8|16);", + "}", + "void", "crack(int n, int j, Trans *z, short srcln[])", "{ int i;\n", " if (!z) return;", @@ -765,19 +1034,19 @@ " }", "#endif", " printf(\"]\");", - " printf(\" [%%s%%s%%s%%s%%s] line %%d => \",", + " printf(\" [%%s%%s%%s%%s%%s] %%s:%%d => \",", " z->atom&6?\"A\":z->atom&32?\"D\":\"-\",", " accpstate[n][j]?\"a\" :\"-\",", " stopstate[n][j]?\"e\" : \"-\",", " progstate[n][j]?\"p\" : \"-\",", " z->atom & 8 ?\"L\":\"G\",", - " srcln[j]);", + " PanSource, srcln[j]);", " for (i = 0; z->tp[i]; i++)", " if (z->tp[i] == \'\\n\')", " printf(\"\\\\n\");", " else", " putchar(z->tp[i]);", - " if (z->qu[0])", + " if (verbose && z->qu[0])", " { printf(\"\\t[\");", " for (i = 0; i < 6; i++)", " if (z->qu[i])", @@ -788,6 +1057,32 @@ " printf(\"\\n\");", " fflush(stdout);", "}", + "/* spin -a m.pml; cc -o pan pan.c; ./pan -D | dot -Tps > foo.ps; ps2pdf foo.ps */", + "void", + "dot_crack(int n, int j, Trans *z)", + "{ int i;\n", + " if (!z) return;", + " printf(\"\tS%%d -> S%%d [color=black\", j, z->st);", + "", + " if (z->atom&6) printf(\",style=dashed\");", /* A */ + " else if (z->atom&32) printf(\",style=dotted\");", /* D */ + " else if (z->atom&8) printf(\",style=solid\");", /* L */ + " else printf(\",style=bold\");", /* G */ + /* other styles: filled dotted */ + "", + " printf(\",label=\\\"\");", + " for (i = 0; z->tp[i]; i++)", + " { if (z->tp[i] == \'\\\\\'", + " && z->tp[i+1] == \'n\')", + " { i++; printf(\" \");", + " } else", + " { putchar(z->tp[i]);", + " } }", + " printf(\"\\\"];\\n\");", + " if (accpstate[n][j]) printf(\" S%%d [color=red,style=bold];\\n\", j);", + " else if (progstate[n][j]) printf(\" S%%d [color=green,style=bold];\\n\", j);", + " if (stopstate[n][j]) printf(\" S%%d [color=blue,style=bold,shape=box];\\n\", j);", + "}", "", "#ifdef VAR_RANGES", "#define BYTESIZE 32 /* 2^8 : 2^3 = 256:8 = 32 */", diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen3.c --- a/sys/src/cmd/spin/pangen3.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen3.c Tue Mar 06 23:34:10 2012 +0100 @@ -13,10 +13,10 @@ #include "y.tab.h" extern FILE *th; -extern int claimnr, eventmapnr; +extern int eventmapnr; typedef struct SRC { - short ln, st; /* linenr, statenr */ + int ln, st; /* linenr, statenr */ Symbol *fn; /* filename */ struct SRC *nxt; } SRC; @@ -28,6 +28,8 @@ static SRC *frst = (SRC *) 0; static SRC *skip = (SRC *) 0; +extern int ltl_mode; + extern void sr_mesg(FILE *, int, int); static void @@ -47,7 +49,7 @@ return; if (lastfnm) - fprintf(th, "{ %s, %d, %d },\n\t", + fprintf(th, "{ \"%s\", %d, %d },\n\t", lastfnm->name, lastfrom, j-1); @@ -59,7 +61,7 @@ putfnm_flush(int j) { if (lastfnm) - fprintf(th, "{ %s, %d, %d }\n", + fprintf(th, "{ \"%s\", %d, %d }\n", lastfnm->name, lastfrom, j); } @@ -72,7 +74,7 @@ if (tmp->st == m) return; tmp = (SRC *) emalloc(sizeof(SRC)); - tmp->st = (short) m; + tmp->st = m; tmp->nxt = skip; skip = tmp; } @@ -85,7 +87,7 @@ if (tmp->st == m) { if (tmp == skip) skip = skip->nxt; - else + else if (lst) /* always true, but helps coverity */ lst->nxt = tmp->nxt; break; } @@ -104,13 +106,13 @@ for (tmp = frst; tmp; tmp = tmp->nxt) if (tmp->st == m) { if (tmp->ln != n || tmp->fn != e->n->fn) - printf("putsrc mismatch %d - %d, file %s\n", n, + printf("putsrc mismatch seqno %d, line %d - %d, file %s\n", m, n, tmp->ln, tmp->fn->name); return; } tmp = (SRC *) emalloc(sizeof(SRC)); - tmp->ln = (short) n; - tmp->st = (short) m; + tmp->ln = n; + tmp->st = m; tmp->fn = e->n->fn; tmp->nxt = frst; frst = tmp; @@ -137,8 +139,9 @@ putnr(0); } fprintf(th, "};\n"); - if (m == claimnr) - fprintf(th, "#define reached_claim reached%d\n", m); + + fprintf(th, "uchar *loopstate%d;\n", m); + if (m == eventmapnr) fprintf(th, "#define reached_event reached%d\n", m); @@ -149,6 +152,7 @@ dumpsrc(int n, int m) { SRC *tmp, *lst; int j; + static int did_claim = 0; fprintf(th, "short src_ln%d [] = {\n\t", m); for (j = 0, col = 0; j <= n; j++) @@ -164,7 +168,7 @@ fprintf(th, "};\n"); lastfnm = (Symbol *) 0; - lastdef.name = "\"-\""; + lastdef.name = "-"; fprintf(th, "S_F_MAP src_file%d [] = {\n\t", m); for (j = 0, col = 0; j <= n; j++) { lst = (SRC *) 0; @@ -183,8 +187,10 @@ putfnm_flush(j); fprintf(th, "};\n"); - if (m == claimnr) - fprintf(th, "#define src_claim src_ln%d\n", m); + if (pid_is_claim(m) && !did_claim) + { fprintf(th, "short *src_claim;\n"); + did_claim++; + } if (m == eventmapnr) fprintf(th, "#define src_event src_ln%d\n", m); @@ -237,7 +243,27 @@ case GT: Cat1(">"); break; case LT: Cat1("<"); break; case NE: Cat1("!="); break; - case EQ: Cat1("=="); break; + case EQ: + if (ltl_mode + && now->lft->ntyp == 'p' + && now->rgt->ntyp == 'q') /* remote ref */ + { Lextok *p = now->lft->lft; + + fprintf(fd, "("); + fprintf(fd, "%s", p->sym->name); + if (p->lft) + { fprintf(fd, "["); + putstmnt(fd, p->lft, 0); /* pid */ + fprintf(fd, "]"); + } + fprintf(fd, "@"); + fprintf(fd, "%s", now->rgt->sym->name); + fprintf(fd, ")"); + break; + } + Cat1("=="); + break; + case OR: Cat1("||"); break; case AND: Cat1("&&"); break; case LSHIFT: Cat1("<<"); break; @@ -349,9 +375,22 @@ comwork(fd, now->lft, m); fprintf(fd, ")"); break; - case NAME: putname(fd, "", now, m, ""); + case NAME: + putname(fd, "", now, m, ""); break; - case 'p': putremote(fd, now, m); + + case 'p': if (ltl_mode) + { fprintf(fd, "%s", now->lft->sym->name); /* proctype */ + if (now->lft->lft) + { fprintf(fd, "["); + putstmnt(fd, now->lft->lft, 0); /* pid */ + fprintf(fd, "]"); + } + fprintf(fd, ":"); /* remote varref */ + fprintf(fd, "%s", now->sym->name); /* varname */ + break; + } + putremote(fd, now, m); break; case 'q': fprintf(fd, "%s", now->sym->name); break; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen3.h --- a/sys/src/cmd/spin/pangen3.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen3.h Tue Mar 06 23:34:10 2012 +0100 @@ -8,15 +8,16 @@ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ +/* (c) 2007: small additions for V5.0 to support multi-core verifications */ static char *Head0[] = { "#if defined(BFS) && defined(REACH)", - "#undef REACH", /* redundant with bfs */ + " #undef REACH", /* redundant with bfs */ "#endif", "#ifdef VERI", - "#define BASE 1", + " #define BASE 1", "#else", - "#define BASE 0", + " #define BASE 0", "#endif", "typedef struct Trans {", " short atom; /* if &2 = atomic trans; if &8 local */", @@ -37,108 +38,140 @@ " int back; /* index return transition */", " struct Trans *nxt;", "} Trans;\n", - "#define qptr(x) (((uchar *)&now)+(int)q_offset[x])", - "#define pptr(x) (((uchar *)&now)+(int)proc_offset[x])", -/* "#define Pptr(x) ((proc_offset[x])?pptr(x):noptr)", */ + + "#ifdef TRIX", + " #define qptr(x) (channels[x]->body)", + " #define pptr(x) (processes[x]->body)", + "#else", + " #define qptr(x) (((uchar *)&now)+(int)q_offset[x])", + " #define pptr(x) (((uchar *)&now)+(int)proc_offset[x])", +/* " #define Pptr(x) ((proc_offset[x])?pptr(x):noptr)", */ + "#endif", "extern uchar *Pptr(int);", + "extern uchar *Qptr(int);", - "#define q_sz(x) (((Q0 *)qptr(x))->Qlen)\n", - "#ifndef VECTORSZ", - "#define VECTORSZ 1024 /* sv size in bytes */", + "#define q_sz(x) (((Q0 *)qptr(x))->Qlen)", + "", + "#ifdef TRIX", + " #ifdef VECTORSZ", + " #undef VECTORSZ", /* backward compatibility */ + " #endif", + " #if WS==4", + " #define VECTORSZ 2056 /* ((MAXPROC+MAXQ+4)*sizeof(uchar *)) */", + " #else", + " #define VECTORSZ 4112 /* the formula causes probs in preprocessing */", + " #endif", + "#else", + " #ifndef VECTORSZ", + " #define VECTORSZ 1024 /* sv size in bytes */", + " #endif", "#endif\n", 0, }; static char *Header[] = { "#ifdef VERBOSE", - "#ifndef CHECK", - "#define CHECK", - "#endif", - "#ifndef DEBUG", - "#define DEBUG", - "#endif", + " #ifndef CHECK", + " #define CHECK", + " #endif", + " #ifndef DEBUG", + " #define DEBUG", + " #endif", "#endif", "#ifdef SAFETY", - "#ifndef NOFAIR", - "#define NOFAIR", - "#endif", + " #ifndef NOFAIR", + " #define NOFAIR", + " #endif", "#endif", "#ifdef NOREDUCE", - "#ifndef XUSAFE", - "#define XUSAFE", - "#endif", - "#if !defined(SAFETY) && !defined(MA)", - "#define FULLSTACK", - "#endif", + " #ifndef XUSAFE", + " #define XUSAFE", + " #endif", + " #if !defined(SAFETY) && !defined(MA)", + " #define FULLSTACK", + " #endif", "#else", - "#ifdef BITSTATE", - "#ifdef SAFETY && !defined(HASH64)", - "#define CNTRSTACK", - "#else", - "#define FULLSTACK", - "#endif", - "#else", - "#define FULLSTACK", - "#endif", + " #ifdef BITSTATE", + " #if defined(SAFETY) && !defined(HASH64)", + " #define CNTRSTACK", + " #else", + " #define FULLSTACK", + " #endif", + " #else", + " #define FULLSTACK", + " #endif", "#endif", "#ifdef BITSTATE", - "#ifndef NOCOMP", - "#define NOCOMP", - "#endif", - "#if !defined(LC) && defined(SC)", - "#define LC", - "#endif", + " #ifndef NOCOMP", + " #define NOCOMP", + " #endif", + " #if !defined(LC) && defined(SC)", + " #define LC", + " #endif", "#endif", "#if defined(COLLAPSE2) || defined(COLLAPSE3) || defined(COLLAPSE4)", - "/* accept the above for backward compatibility */", - "#define COLLAPSE", + " /* accept the above for backward compatibility */", + " #define COLLAPSE", "#endif", "#ifdef HC", - "#undef HC", - "#define HC4", + " #undef HC", + " #define HC4", "#endif", "#ifdef HC0", /* 32 bits */ - "#define HC 0", + " #define HC 0", "#endif", "#ifdef HC1", /* 32+8 bits */ - "#define HC 1", + " #define HC 1", "#endif", "#ifdef HC2", /* 32+16 bits */ - "#define HC 2", + " #define HC 2", "#endif", "#ifdef HC3", /* 32+24 bits */ - "#define HC 3", + " #define HC 3", "#endif", "#ifdef HC4", /* 32+32 bits - combine with -DMA=8 */ - "#define HC 4", + " #define HC 4", "#endif", "#ifdef COLLAPSE", - "unsigned long ncomps[256+2];", + " #if NCORE>1 && !defined(SEP_STATE)", + " unsigned long *ncomps; /* in shared memory */", + " #else", + " unsigned long ncomps[256+2];", + " #endif", "#endif", "#define MAXQ 255", "#define MAXPROC 255", - "#define WS sizeof(long) /* word size in bytes */", - "typedef struct Stack { /* for queues and processes */", + "", + "typedef struct _Stack { /* for queues and processes */", "#if VECTORSZ>32000", " int o_delta;", - " int o_offset;", - " int o_skip;", + " #ifndef TRIX", + " int o_offset;", + " int o_skip;", + " #endif", " int o_delqs;", "#else", " short o_delta;", - " short o_offset;", - " short o_skip;", + " #ifndef TRIX", + " short o_offset;", + " short o_skip;", + " #endif", " short o_delqs;", "#endif", " short o_boq;", + "#ifdef TRIX", + " short parent;", + " char *b_ptr;", /* used in delq/q_restor and delproc/p_restor */ + "#else", + " char *body;", /* full copy of state vector in non-trix mode */ + "#endif", "#ifndef XUSAFE", " char *o_name;", "#endif", - " char *body;", - " struct Stack *nxt;", - " struct Stack *lst;", - "} Stack;\n", + " struct _Stack *nxt;", + " struct _Stack *lst;", + "} _Stack;\n", "typedef struct Svtack { /* for complete state vector */", "#if VECTORSZ>32000", " int o_delta;", @@ -159,22 +192,24 @@ " struct Svtack *lst;", "} Svtack;\n", "Trans ***trans; /* 1 ptr per state per proctype */\n", - "#if defined(FULLSTACK) || defined(BFS)", "struct H_el *Lstate;", + "int depthfound = -1; /* loop detection */", + + "#ifndef TRIX", + " #if VECTORSZ>32000", + " int proc_offset[MAXPROC];", + " int q_offset[MAXQ];", + " #else", + " short proc_offset[MAXPROC];", + " short q_offset[MAXQ];", + " #endif", + " uchar proc_skip[MAXPROC];", + " uchar q_skip[MAXQ];", "#endif", - "int depthfound = -1; /* loop detection */", - "#if VECTORSZ>32000", - "int proc_offset[MAXPROC];", - "int q_offset[MAXQ];", - "#else", - "short proc_offset[MAXPROC];", - "short q_offset[MAXQ];", - "#endif", - "uchar proc_skip[MAXPROC];", - "uchar q_skip[MAXQ];", + "unsigned long vsize; /* vector size in bytes */", "#ifdef SVDUMP", - "int vprefix=0, svfd; /* runtime option -pN */", + " int vprefix=0, svfd; /* runtime option -pN */", "#endif", "char *tprefix = \"trail\"; /* runtime option -tsuffix */", "short boq = -1; /* blocked_on_queue status */", @@ -214,12 +249,17 @@ "#ifdef HAS_LAST", /* cannot go before _cnt - see hstore() */ " uchar _last; /* pid executed in last step */", "#endif", + + "#if defined(BITSTATE) && defined(BCS) && defined(STORE_CTX)", + " uchar _ctx; /* nr of context switches so far */", + "#endif", + "#ifdef EVENT_TRACE", - "#if nstates_event<256", - " uchar _event;", - "#else", - " unsigned short _event;", - "#endif", + " #if nstates_event<256", + " uchar _event;", + " #else", + " unsigned short _event;", + " #endif", "#endif", 0, }; @@ -235,12 +275,15 @@ " if (TstOnly) return (h < MAXPROC);", "#endif", "#ifndef NOBOUNDCHECK", - "/* redefine Index only within this procedure */", - "#undef Index", - "#define Index(x, y) Boundcheck(x, y, 0, 0, 0)", + " /* redefine Index only within this procedure */", + " #undef Index", + " #define Index(x, y) Boundcheck(x, y, 0, 0, 0)", "#endif", " if (h >= MAXPROC)", " Uerror(\"too many processes\");", + "#ifdef V_TRIX", + " printf(\"%%4d: add process %%d\\n\", depth, h);", + "#endif", " switch (n) {", " case 0: j = sizeof(P0); break;", 0, @@ -249,31 +292,46 @@ static char *Addp1[] = { " default: Uerror(\"bad proc - addproc\");", " }", + + "#ifdef TRIX", + " vsize += sizeof(struct H_el *);", + "#else", " if (vsize%%WS)", " proc_skip[h] = WS-(vsize%%WS);", " else", " proc_skip[h] = 0;", - "#ifndef NOCOMP", - " for (k = vsize + (int) proc_skip[h]; k > vsize; k--)", - " Mask[k-1] = 1; /* align */", - "#endif", + " #ifndef NOCOMP", + " for (k = vsize + (int) proc_skip[h]; k > vsize; k--)", + " Mask[k-1] = 1; /* align */", + " #endif", " vsize += (int) proc_skip[h];", " proc_offset[h] = vsize;", - "#ifdef SVDUMP", + " vsize += j;", + " #if defined(SVDUMP) && defined(VERBOSE)", " if (vprefix > 0)", " { int dummy = 0;", " write(svfd, (uchar *) &dummy, sizeof(int)); /* mark */", " write(svfd, (uchar *) &h, sizeof(int));", " write(svfd, (uchar *) &n, sizeof(int));", - "#if VECTORSZ>32000", + " #if VECTORSZ>32000", " write(svfd, (uchar *) &proc_offset[h], sizeof(int));", - "#else", + " write(svfd, (uchar *) &now, vprefix-4*sizeof(int)); /* padd */", + " #else", " write(svfd, (uchar *) &proc_offset[h], sizeof(short));", + " write(svfd, (uchar *) &now, vprefix-3*sizeof(int)-sizeof(short)); /* padd */", + " #endif", + " }", + " #endif", "#endif", - " write(svfd, (uchar *) &now, vprefix-4*sizeof(int)); /* padd */", + + " now._nr_pr += 1;", + "#if defined(BCS) && defined(CONSERVATIVE)", + " if (now._nr_pr >= CONSERVATIVE*8)", + " { printf(\"pan: error: too many processes -- recompile with \");", + " printf(\"-DCONSERVATIVE=%%d\\n\", CONSERVATIVE+1);", + " pan_exit(1);", " }", "#endif", - " now._nr_pr += 1;", " if (fairness && ((int) now._nr_pr + 1 >= (8*NFAIR)/2))", " { printf(\"pan: error: too many processes -- current\");", " printf(\" max is %%d procs (-DNFAIR=%%d)\\n\",", @@ -282,22 +340,38 @@ " NFAIR+1);", " pan_exit(1);", " }", - - " vsize += j;", "#ifndef NOVSZ", " now._vsz = vsize;", "#endif", - "#ifndef NOCOMP", - " for (k = 1; k <= Air[n]; k++)", - " Mask[vsize - k] = 1; /* pad */", - " Mask[vsize-j] = 1; /* _pid */", - "#endif", " hmax = max(hmax, vsize);", + + "#ifdef TRIX", + " #ifndef BFS", + " if (freebodies)", + " { processes[h] = freebodies;", + " freebodies = freebodies->nxt;", + " } else", + " { processes[h] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));", + " processes[h]->body = (uchar *) emalloc(Maxbody * sizeof(char));", + " }", + " processes[h]->modified = 1; /* addproc */", + " #endif", + " processes[h]->psize = j;", + " processes[h]->parent_pid = calling_pid;", + " processes[h]->nxt = (TRIX_v6 *) 0;", + "#else", + " #ifndef NOCOMP", + " for (k = 1; k <= Air[n]; k++)", + " Mask[vsize - k] = 1; /* pad */", + " Mask[vsize-j] = 1; /* _pid */", + " #endif", " if (vsize >= VECTORSZ)", " { printf(\"pan: error, VECTORSZ too small, recompile pan.c\");", - " printf(\" with -DVECTORSZ=N with N>%%d\\n\", vsize);", + " printf(\" with -DVECTORSZ=N with N>%%d\\n\", (int) vsize);", " Uerror(\"aborting\");", " }", + "#endif", + " memset((char *)pptr(h), 0, j);", " this = pptr(h);", " if (BASE > 0 && h > 0)", @@ -310,13 +384,16 @@ static char *Addq0[] = { "int", - "addqueue(int n, int is_rv)", + "addqueue(int calling_pid, int n, int is_rv)", "{ int j=0, i = now._nr_qs;", - "#ifndef NOCOMP", + "#if !defined(NOCOMP) && !defined(TRIX)", " int k;", "#endif", " if (i >= MAXQ)", " Uerror(\"too many queues\");", + "#ifdef V_TRIX", + " printf(\"%%4d: add queue %%d\\n\", depth, i);", + "#endif", " switch (n) {", 0, }; @@ -324,29 +401,55 @@ static char *Addq1[] = { " default: Uerror(\"bad queue - addqueue\");", " }", + + "#ifdef TRIX", + " vsize += sizeof(struct H_el *);", + "#else", " if (vsize%%WS)", " q_skip[i] = WS-(vsize%%WS);", " else", " q_skip[i] = 0;", - "#ifndef NOCOMP", - " k = vsize;", - "#ifndef BFS", - " if (is_rv) k += j;", - "#endif", - " for (k += (int) q_skip[i]; k > vsize; k--)", - " Mask[k-1] = 1;", - "#endif", + " #ifndef NOCOMP", + " k = vsize;", + " #ifndef BFS", + " if (is_rv) k += j;", + " #endif", + " for (k += (int) q_skip[i]; k > vsize; k--)", + " Mask[k-1] = 1;", + " #endif", " vsize += (int) q_skip[i];", " q_offset[i] = vsize;", + " vsize += j;", + "#endif", + " now._nr_qs += 1;", - " vsize += j;", "#ifndef NOVSZ", " now._vsz = vsize;", "#endif", " hmax = max(hmax, vsize);", + + "#ifdef TRIX", + " #ifndef BFS", + " if (freebodies)", + " { channels[i] = freebodies;", + " freebodies = freebodies->nxt;", + " } else", + " { channels[i] = (TRIX_v6 *) emalloc(sizeof(TRIX_v6));", + " channels[i]->body = (uchar *) emalloc(Maxbody * sizeof(char));", + " }", + " channels[i]->modified = 1; /* addq */", + " #endif", + " channels[i]->psize = j;", + " channels[i]->parent_pid = calling_pid;", + " channels[i]->nxt = (TRIX_v6 *) 0;", + "#else", " if (vsize >= VECTORSZ)", " Uerror(\"VECTORSZ is too small, edit pan.h\");", - " memset((char *)qptr(i), 0, j);", + "#endif", + + " if (j > 0)", /* zero if there are no queues */ + " { memset((char *)qptr(i), 0, j);", + " }", " ((Q0 *)qptr(i))->_t = n;", " return i+1;", "}\n", @@ -362,6 +465,19 @@ " uerror(\"ref to uninitialized chan name (sending)\");", " if (into >= (int) now._nr_qs || into < 0)", " Uerror(\"qsend bad queue#\");", + "#if defined(TRIX) && !defined(BFS)", + " #ifndef TRIX_ORIG", + " (trpt+1)->q_bup = now._ids_[now._nr_pr+into];", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d s save %%p from %%d\\n\",", + " depth, into, (trpt+1)->q_bup, now._nr_pr+into);", + " #endif", + " #endif", + " channels[into]->modified = 1; /* qsend */", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d modified\\n\", depth, into);", + " #endif", + "#endif", " z = qptr(into);", " j = ((Q0 *)qptr(into))->Qlen;", " switch (((Q0 *)qptr(into))->_t) {", @@ -509,6 +625,19 @@ " int j, k, r=0;\n", " if (!from--)", " uerror(\"ref to uninitialized chan name (receiving)\");", + "#if defined(TRIX) && !defined(BFS)", + " #ifndef TRIX_ORIG", + " (trpt+1)->q_bup = now._ids_[now._nr_pr+from];", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d r save %%p from %%d\\n\",", + " depth, from, (trpt+1)->q_bup, now._nr_pr+from);", + " #endif", + " #endif", + " channels[from]->modified = 1; /* qrecv */", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d modified\\n\", depth, from);", + " #endif", + "#endif", " if (from >= (int) now._nr_qs || from < 0)", " Uerror(\"qrecv bad queue#\");", " z = qptr(from);", @@ -547,6 +676,13 @@ "#ifndef NOVSZ", " now._vsz = vsize;", "#endif", + "#ifdef TRIX", + " if (VECTORSZ != sizeof(now._ids_))", + " { printf(\"VECTORSZ is %%d, but should be %%d in this mode\\n\",", + " VECTORSZ, sizeof(now._ids_));", + " Uerror(\"VECTORSZ set incorrectly, recompile Spin (not pan.c)\");", + " }", + "#endif", "/* optional provisioning statements, e.g. to */", "/* set hidden variables, used as constants */", "#ifdef PROV", @@ -557,10 +693,11 @@ }; static char *R0[] = { - " Maxbody = max(Maxbody, sizeof(P%d));", + " Maxbody = max(Maxbody, ((int) sizeof(P%d)));", " reached[%d] = reached%d;", " accpstate[%d] = (uchar *) emalloc(nstates%d);", " progstate[%d] = (uchar *) emalloc(nstates%d);", + " loopstate%d = loopstate[%d] = (uchar *) emalloc(nstates%d);", " stopstate[%d] = (uchar *) emalloc(nstates%d);", " visstate[%d] = (uchar *) emalloc(nstates%d);", " mapstate[%d] = (short *) emalloc(nstates%d * sizeof(short));", @@ -572,30 +709,42 @@ }; static char *R0a[] = { - " retrans(%d, nstates%d, start%d, src_ln%d, reached%d);", - 0, -}; -static char *R0b[] = { - " if (state_tables)", - " { printf(\"\\nTransition Type: \");", - " printf(\"A=atomic; D=d_step; L=local; G=global\\n\");", - " printf(\"Source-State Labels: \");", - " printf(\"p=progress; e=end; a=accept;\\n\");", - "#ifdef MERGED", - " printf(\"Note: statement merging was used. Only the first\\n\");", - " printf(\" stmnt executed in each merge sequence is shown\\n\");", - " printf(\" (use spin -a -o3 to disable statement merging)\\n\");", - "#endif", - " pan_exit(0);", - " }", + " retrans(%d, nstates%d, start%d, src_ln%d, reached%d, loopstate%d);", 0, }; static char *Code1[] = { "#ifdef NP", - "#define ACCEPT_LAB 1 /* at least 1 in np_ */", + " #define ACCEPT_LAB 1 /* at least 1 in np_ */", "#else", - "#define ACCEPT_LAB %d /* user-defined accept labels */", + " #define ACCEPT_LAB %d /* user-defined accept labels */", + "#endif", + "#ifdef MEMCNT", + " #ifdef MEMLIM", + " #warning -DMEMLIM takes precedence over -DMEMCNT", + " #undef MEMCNT", + " #else", + " #if MEMCNT<20", + " #warning using minimal value -DMEMCNT=20 (=1MB)", + " #define MEMLIM (1)", + " #undef MEMCNT", + " #else", + " #if MEMCNT==20", + " #define MEMLIM (1)", + " #undef MEMCNT", + " #else", + " #if MEMCNT>=50", + " #error excessive value for MEMCNT", + " #else", + " #define MEMLIM (1<<(MEMCNT-20))", + " #endif", + " #endif", + " #endif", + " #endif", + "#endif", + + "#if NCORE>1 && !defined(MEMLIM)", + " #define MEMLIM (2048) /* need a default, using 2 GB */", "#endif", 0, }; @@ -608,17 +757,18 @@ static char *R2[] = { "uchar *accpstate[%d];", "uchar *progstate[%d];", + "uchar *loopstate[%d];", "uchar *reached[%d];", "uchar *stopstate[%d];", "uchar *visstate[%d];", "short *mapstate[%d];", "#ifdef HAS_CODE", - "int NrStates[%d];", + " int NrStates[%d];", "#endif", 0, }; static char *R3[] = { - " Maxbody = max(Maxbody, sizeof(Q%d));", + " Maxbody = max(Maxbody, ((int) sizeof(Q%d)));", 0, }; static char *R4[] = { @@ -632,19 +782,22 @@ static char *R6[] = { " }", " this = o_this;", + "#ifdef TRIX", + " re_mark_all(1); /* addproc */", + "#endif", " return h-BASE;", "#ifndef NOBOUNDCHECK", - "#undef Index", - "#define Index(x, y) Boundcheck(x, y, II, tt, t)", + " #undef Index", + " #define Index(x, y) Boundcheck(x, y, II, tt, t)", "#endif", "}\n", "#if defined(BITSTATE) && defined(COLLAPSE)", - "/* just to allow compilation, to generate the error */", - "long col_p(int i, char *z) { return 0; }", - "long col_q(int i, char *z) { return 0; }", + " /* just to allow compilation, to generate the error */", + " long col_p(int i, char *z) { return 0; }", + " long col_q(int i, char *z) { return 0; }", "#endif", "#ifndef BITSTATE", - "#ifdef COLLAPSE", + " #ifdef COLLAPSE", "long", "col_p(int i, char *z)", "{ int j, k; unsigned long ordinal(char *, long, short);", @@ -669,7 +822,7 @@ " if (z) return (long) (x - z);", " return ordinal(scratch, x-scratch, (short) (2+ptr->_t));", "}", - "#endif", + " #endif", "#endif", 0, }; @@ -691,7 +844,7 @@ " if (z) return (long) (x - z);", " return ordinal(scratch, x-scratch, 1); /* chan */", "}", - "#endif", + " #endif", "#endif", 0, }; @@ -709,6 +862,20 @@ "#endif", " if (!into--)", " uerror(\"ref to uninitialized chan (unsend)\");", + "#if defined(TRIX) && !defined(BFS)", + " #ifndef TRIX_ORIG", + " now._ids_[now._nr_pr+into] = trpt->q_bup;", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d s restore %%p into %%d\\n\",", + " depth, into, trpt->q_bup, now._nr_pr+into);", + " #endif", + " #else", + " channels[into]->modified = 1; /* unsend */", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d unmodify\\n\", depth, into);", + " #endif", + " #endif", + "#endif", " z = qptr(into);", " j = ((Q0 *)z)->Qlen;", " ((Q0 *)z)->Qlen = --j;", @@ -725,6 +892,20 @@ "{ int j; uchar *z;\n", " if (!from--)", " uerror(\"ref to uninitialized chan (unrecv)\");", + "#if defined(TRIX) && !defined(BFS)", + " #ifndef TRIX_ORIG", + " now._ids_[now._nr_pr+from] = trpt->q_bup;", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d r restore %%p into %%d\\n\",", + " depth, from, trpt->q_bup, now._nr_pr+from);", + " #endif", + " #else", + " channels[from]->modified = 1; /* unrecv */", + " #ifdef V_TRIX", + " printf(\"%%4d: channel %%d unmodify\\n\", depth, from);", + " #endif", + " #endif", + "#endif", " z = qptr(from);", " j = ((Q0 *)z)->Qlen;", " if (strt) ((Q0 *)z)->Qlen = j+1;", @@ -743,14 +924,14 @@ "char *emalloc(unsigned long);", "char *Malloc(unsigned long);", "int Boundcheck(int, int, int, int, Trans *);", - "int addqueue(int, int);", + "int addqueue(int, int, int);", "/* int atoi(char *); */", "/* int abort(void); */", "int close(int);", /* should probably remove this */ #if 0 "#ifndef SC", - "int creat(char *, unsigned short);", - "int write(int, void *, unsigned);", + " int creat(char *, unsigned short);", + " int write(int, void *, unsigned);", "#endif", #endif "int delproc(int, int);", @@ -767,16 +948,19 @@ "int unsend(int);", "/* void *sbrk(int); */", "void Uerror(char *);", - "void assert(int, char *, int, int, Trans *);", + "void spin_assert(int, char *, int, int, Trans *);", "void c_chandump(int);", "void c_globals(void);", "void c_locals(int, int);", "void checkcycles(void);", "void crack(int, int, Trans *, short *);", + "void d_sfh(const char *, int);", + "void sfh(const char *, int);", "void d_hash(uchar *, int);", "void s_hash(uchar *, int);", "void r_hash(uchar *, int);", "void delq(int);", + "void dot_crack(int, int, Trans *);", "void do_reach(void);", "void pan_exit(int);", "void exit(int);", @@ -787,28 +971,29 @@ "void putpeg(int, int);", "void putrail(void);", "void q_restor(void);", - "void retrans(int, int, int, short *, uchar *);", + "void retrans(int, int, int, short *, uchar *, uchar *);", "void settable(void);", "void setq_claim(int, int, char *, int, char *);", "void sv_restor(void);", "void sv_save(void);", "void tagtable(int, int, int, short *, uchar *);", + "void do_dfs(int, int, int, short *, uchar *, uchar *);", "void uerror(char *);", "void unrecv(int, int, int, int, int);", "void usage(FILE *);", "void wrap_stats(void);", "#if defined(FULLSTACK) && defined(BITSTATE)", - "int onstack_now(void);", - "void onstack_init(void);", - "void onstack_put(void);", - "void onstack_zap(void);", + " int onstack_now(void);", + " void onstack_init(void);", + " void onstack_put(void);", + " void onstack_zap(void);", "#endif", "#ifndef XUSAFE", - "int q_S_check(int, int);", - "int q_R_check(int, int);", - "uchar q_claim[MAXQ+1];", - "char *q_name[MAXQ+1];", - "char *p_name[MAXPROC+1];", + " int q_S_check(int, int);", + " int q_R_check(int, int);", + " uchar q_claim[MAXQ+1];", + " char *q_name[MAXQ+1];", + " char *p_name[MAXPROC+1];", "#endif", 0, }; @@ -825,6 +1010,35 @@ "#ifdef NOVSZ", " strcat(ctd, \"-DNOVSZ \");", "#endif", + "#ifdef REVERSE", + " strcat(ctd, \"-DREVERSE \");", + "#endif", + "#ifdef T_REVERSE", + " strcat(ctd, \"-DT_REVERSE \");", + "#endif", + "#ifdef T_RAND", + " #if T_RAND>0", + " sprintf(carg, \"-DT_RAND=%%d \", T_RAND);", + " strcat(ctd, carg);", + " #else", + " strcat(ctd, \"-DT_RAND \");", + " #endif", + "#endif", + "#ifdef P_RAND", + " #if P_RAND>0", + " sprintf(carg, \"-DP_RAND=%%d \", P_RAND);", + " strcat(ctd, carg);", + " #else", + " strcat(ctd, \"-DP_RAND \");", + " #endif", + "#endif", + "#ifdef BCS", + " sprintf(carg, \"-DBCS=%%d \", BCS);", + " strcat(ctd, carg);", + "#endif", + "#ifdef BFS", + " strcat(ctd, \"-DBFS \");", + "#endif", "#ifdef MEMLIM", " sprintf(carg, \"-DMEMLIM=%%d \", MEMLIM);", " strcat(ctd, carg);", @@ -888,6 +1102,9 @@ "#ifdef CTL", " strcat(ctd, \"-DCTL \");", "#endif", + "#ifdef TRIX", + " strcat(ctd, \"-DTRIX \");", + "#endif", "#ifdef NIBIS", " strcat(ctd, \"-DNIBIS \");", "#endif", @@ -916,7 +1133,7 @@ "#ifdef SVDUMP", " strcat(ctd, \"-DSVDUMP \");", "#endif", - "#ifdef VECTORSZ", + "#if defined(VECTORSZ) && !defined(TRIX)", " if (VECTORSZ != 1024)", " { sprintf(carg, \"-DVECTORSZ=%%d \", VECTORSZ);", " strcat(ctd, carg);", @@ -931,8 +1148,35 @@ "#ifdef SDUMP", " strcat(ctd, \"-DSDUMP \");", "#endif", - "#ifdef COVEST", - " strcat(ctd, \"-DCOVEST \");", + "#if NCORE>1", + " sprintf(carg, \"-DNCORE=%%d \", NCORE);", + " strcat(ctd, carg);", + "#endif", + "#ifdef SFH", + " sprintf(carg, \"-DSFH \");", + " strcat(ctd, carg);", + "#endif", + "#ifdef VMAX", + " if (VMAX != 256)", + " { sprintf(carg, \"-DVMAX=%%d \", VMAX);", + " strcat(ctd, carg);", + " }", + "#endif", + "#ifdef PMAX", + " if (PMAX != 16)", + " { sprintf(carg, \"-DPMAX=%%d \", PMAX);", + " strcat(ctd, carg);", + " }", + "#endif", + "#ifdef QMAX", + " if (QMAX != 16)", + " { sprintf(carg, \"-DQMAX=%%d \", QMAX);", + " strcat(ctd, carg);", + " }", + "#endif", + "#ifdef SET_WQ_SIZE", + " sprintf(carg, \"-DSET_WQ_SIZE=%%d \", SET_WQ_SIZE);", + " strcat(ctd, carg);", "#endif", " printf(\"Compiled as: cc -o pan %%span.c\\n\", ctd);", "}", diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen4.c --- a/sys/src/cmd/spin/pangen4.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen4.c Tue Mar 06 23:34:10 2012 +0100 @@ -307,6 +307,8 @@ ntimes(tc, 0, 1, R15); } +extern void explain(int); + int proper_enabler(Lextok *n) { @@ -321,7 +323,9 @@ return 1; return (!(n->sym->context)); - case CONST: case TIMEOUT: + case C_EXPR: + case CONST: + case TIMEOUT: has_provided = 1; return 1; @@ -340,5 +344,8 @@ default: break; } + printf("spin: saw "); + explain(n->ntyp); + printf("\n"); return 0; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen5.c --- a/sys/src/cmd/spin/pangen5.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen5.c Tue Mar 06 23:34:10 2012 +0100 @@ -211,13 +211,18 @@ static int build_step(FSM_trans *v) { FSM_state *f; - Element *el = v->step; + Element *el; #if 0 Lextok *lt = ZN; #endif - int st = v->to; + int st; int r; + if (!v) return -1; + + el = v->step; + st = v->to; + if (!el) return -1; if (v->step->merge) @@ -234,9 +239,7 @@ lt = v->step->n; if (verbose&32) { if (++howdeep == 1) - printf("spin: %s, line %3d, merge:\n", - lt->fn->name, - lt->ln); + printf("spin: %s:%d, merge:\n", lt->fn->name, lt->ln); printf("\t[%d] \t", howdeep, el->seqno); comment(stdout, lt, 0); printf(";\n"); @@ -257,7 +260,7 @@ } static void -FSM_MERGER(char *pname_unused) /* find candidates for safely merging steps */ +FSM_MERGER(/* char *pname */ void) /* find candidates for safely merging steps */ { FSM_state *f, *g; FSM_trans *t; Lextok *lt; @@ -281,14 +284,14 @@ continue; g = fsm_tbl[t->to]; - if (!eligible(g->t)) + if (!g || !eligible(g->t)) { #define SINGLES #ifdef SINGLES t->step->merge_single = t->to; #if 0 if ((verbose&32)) - { printf("spin: %s, line %3d, merge_single:\n\t\t", + { printf("spin: %s:%d, merge_single:\n\t\t", t->step->n->fn->name, t->step->n->ln, t->step->seqno); @@ -346,9 +349,8 @@ #if 0 if ((verbose&32) && t->step->merge_start) - { printf("spin: %s, line %3d, merge_START:\n\t\t", - lt->fn->name, - lt->ln, + { printf("spin: %s:%d, merge_START:\n\t\t", + lt->fn->name, lt->ln, t->step->seqno); comment(stdout, lt, 0); printf(";\n"); @@ -679,7 +681,8 @@ break; default: - printf("spin: bad node type %d line %d (ana_stmnt)\n", now->ntyp, now->ln); + printf("spin: %s:%d, bad node type %d (ana_stmnt)\n", + now->fn->name, now->ln, now->ntyp); fatal("aborting", (char *) 0); } } @@ -692,10 +695,7 @@ int counter = 1; #endif for (p = rdy; p; p = p->nxt) - { if (p->tn == eventmapnr - || p->tn == claimnr) - continue; - + { ana_seq(p->s); fsm_table(); @@ -711,7 +711,7 @@ { FSM_ANA(); } if (merger) - { FSM_MERGER(p->n->name); + { FSM_MERGER(/* p->n->name */); huntele(e, e->status, -1)->merge_in = 1; /* start-state */ #if 0 printf("\n"); @@ -726,8 +726,7 @@ { if (!(e->status&DONE) && (verbose&32)) { printf("unreachable code: "); - printf("%s, line %3d: ", - e->n->fn->name, e->n->ln); + printf("%s:%3d ", e->n->fn->name, e->n->ln); comment(stdout, e->n, 0); printf("\n"); } @@ -735,7 +734,7 @@ } if (export_ast) { AST_slice(); - exit(0); + alldone(0); /* changed in 5.3.0: was exit(0) */ } } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen5.h --- a/sys/src/cmd/spin/pangen5.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen5.h Tue Mar 06 23:34:10 2012 +0100 @@ -80,7 +80,7 @@ " int i, j; uchar c;", " static uchar xwarned = 0;", "", - " sprintf(nm, \"%%s.xpt\", Source);", + " sprintf(nm, \"%%s.xpt\", PanSource);", " if ((fd = creat(nm, 0666)) <= 0)", " if (!xwarned)", " { xwarned = 1;", @@ -372,7 +372,7 @@ " int i, j;", "", " wcnt = 0;", - " sprintf(nm, \"%%s.xpt\", Source);", + " sprintf(nm, \"%%s.xpt\", PanSource);", " if ((fd = open(nm, 0)) < 0) /* O_RDONLY */", " Uerror(\"cannot open checkpoint file\");", "", diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen6.c --- a/sys/src/cmd/spin/pangen6.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pangen6.c Tue Mar 06 23:34:10 2012 +0100 @@ -90,7 +90,6 @@ static Slicer *rel_vars; /* all relevant variables */ static int AST_Changes; static int AST_Round; -static FSM_state no_state; static RPN *rpn; static int in_recv = 0; @@ -145,7 +144,7 @@ { if (!n || !n->sym) return; - if (n->sym->nel != 1) + if (n->sym->nel > 1 || n->sym->isarray) def_use(n->lft, code); /* process the index */ if (n->sym->type == STRUCT /* and possible deeper ones */ @@ -503,7 +502,7 @@ if (strcmp(as->name, bs->name) != 0) return 0; - if (as->type == STRUCT && a->rgt && b->rgt) + if (as->type == STRUCT && a->rgt && b->rgt) /* we know that a and b are not null */ return AST_mutual(a->rgt->lft, b->rgt->lft, 0); return 1; @@ -545,14 +544,14 @@ case 'r': /* guess sends where name may originate */ for (cl = chanlist; cl; cl = cl->nxt) /* all sends */ - { int a = AST_nrpar(cl->s); - int b = AST_nrpar(t->step->n); - if (a != b) /* matching nrs of params */ + { int aa = AST_nrpar(cl->s); + int bb = AST_nrpar(t->step->n); + if (aa != bb) /* matching nrs of params */ continue; - a = AST_ord(cl->s, cl->n); - b = AST_ord(t->step->n, u->n); - if (a != b) /* same position in parlist */ + aa = AST_ord(cl->s, cl->n); + bb = AST_ord(t->step->n, u->n); + if (aa != bb) /* same position in parlist */ continue; AST_add_alias(cl->n, 4); /* RCV assume possible match */ @@ -692,9 +691,7 @@ } for (a = ast; a; a = a->nxt) /* all other stmnts */ - { if (strcmp(a->p->n->name, ":never:") != 0 - && strcmp(a->p->n->name, ":trace:") != 0 - && strcmp(a->p->n->name, ":notrace:") != 0) + { if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE) for (f = a->fsm; f; f = f->nxt) for (t = f->t; t; t = t->nxt) { if (!(t->relevant&1)) @@ -786,10 +783,8 @@ */ for (a = ast; a; a = a->nxt) - { if (strcmp(a->p->n->name, ":never:") == 0 - || strcmp(a->p->n->name, ":trace:") == 0 - || strcmp(a->p->n->name, ":notrace:") == 0 - || strcmp(a->p->n->name, ":init:") == 0) + { if (a->p->b == N_CLAIM || a->p->b == I_PROC + || a->p->b == E_TRACE || a->p->b == N_TRACE) { a->relevant |= 1; /* the proctype is relevant */ continue; } @@ -823,9 +818,9 @@ printf("spin: redundant in proctype %s (for given property):\n", a->p->n->name); } - printf(" line %3d %s (state %d)", + printf(" %s:%d (state %d)", + e->n?e->n->fn->name:"-", e->n?e->n->ln:-1, - e->n?e->n->fn->name:"-", e->seqno); printf(" ["); comment(stdout, e->n, 0); @@ -1075,7 +1070,7 @@ case NAME: name_AST_track(now, code); - if (now->sym->nel != 1) + if (now->sym->nel > 1 || now->sym->isarray) AST_track(now->lft, USE|code); /* index */ break; @@ -1569,7 +1564,8 @@ { t->relevant &= ~2; /* clear mark */ if (verbose&32) { printf("\t\tnomark "); - comment(stdout, t->step->n, 0); + if (t->step && t->step->n) + comment(stdout, t->step->n, 0); printf("\n"); } } } @@ -1601,7 +1597,8 @@ t->relevant |= 2; /* lift */ if (verbose&32) { printf("\t\t\tliftmark "); - comment(stdout, t->step->n, 0); + if (t->step && t->step->n) + comment(stdout, t->step->n, 0); printf("\n"); } AST_spread(a, t->to); /* and spread to all guards */ @@ -1621,10 +1618,9 @@ { AST *a; for (a = ast; a; a = a->nxt) - if (strcmp(a->p->n->name, ":never:") != 0 - && strcmp(a->p->n->name, ":trace:") != 0 - && strcmp(a->p->n->name, ":notrace:") != 0) - AST_ctrl(a); + { if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE) + { AST_ctrl(a); + } } } static void @@ -1634,9 +1630,7 @@ FSM_trans *t; for (a = ast; a; a = a->nxt) - { if (strcmp(a->p->n->name, ":never:") != 0 - && strcmp(a->p->n->name, ":trace:") != 0 - && strcmp(a->p->n->name, ":notrace:") != 0) + { if (a->p->b != N_CLAIM && a->p->b != E_TRACE && a->p->b != N_TRACE) for (f = a->fsm; f; f = f->nxt) for (t = f->t; t; t = t->nxt) { if (t->step @@ -1692,8 +1686,7 @@ int spurious = 0; if (!slicer) - { non_fatal("no slice criteria (or no claim) specified", - (char *) 0); + { printf("spin: warning: no slice criteria found (no assertions and no claim)\n"); spurious = 1; } AST_dorelevant(); /* mark procs refered to in remote refs */ @@ -1730,9 +1723,7 @@ AST_store(ProcList *p, int start_state) { AST *n_ast; - if (strcmp(p->n->name, ":never:") != 0 - && strcmp(p->n->name, ":trace:") != 0 - && strcmp(p->n->name, ":notrace:") != 0) + if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE) { n_ast = (AST *) emalloc(sizeof(AST)); n_ast->p = p; n_ast->i_st = start_state; @@ -1809,12 +1800,10 @@ int cnt; for (a = ast; a; a = a->nxt) - { if (strcmp(a->p->n->name, ":never:") == 0 - || strcmp(a->p->n->name, ":trace:") == 0 - || strcmp(a->p->n->name, ":notrace:") == 0 - || strcmp(a->p->n->name, ":init:") == 0) - continue; /* have no params */ - + { if (a->p->b == N_CLAIM || a->p->b == I_PROC + || a->p->b == E_TRACE || a->p->b == N_TRACE) + { continue; /* has no params */ + } cnt = 0; for (f = a->p->p; f; f = f->rgt) /* types */ for (t = f->lft; t; t = t->rgt) /* formals */ @@ -1845,9 +1834,8 @@ } } for (a = ast; a; a = a->nxt) - { if (strcmp(a->p->n->name, ":never:") != 0 - && strcmp(a->p->n->name, ":trace:") != 0 - && strcmp(a->p->n->name, ":notrace:") != 0) /* claim has no locals */ + { if (a->p->b != N_CLAIM + && a->p->b != E_TRACE && a->p->b != N_TRACE) /* has no locals */ for (walk = all_names; walk; walk = walk->next) { sp = walk->entry; if (sp @@ -2261,6 +2249,7 @@ FSM_trans *t; AST *a; int oi; + static FSM_state no_state; #if 0 find dominators Aho, Sethi, & Ullman, Compilers - principles, techniques, and tools diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen6.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/spin/pangen6.h Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,2840 @@ +/***** spin: pangen6.h *****/ + +/* Copyright (c) 2006-2007 by the California Institute of Technology. */ +/* ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged */ +/* Supporting routines for a multi-core extension of the SPIN software */ +/* Developed as part of Reliable Software Engineering Project ESAS/6G */ +/* Like all SPIN Software 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. */ +/* Any commercial use must be negotiated with the Office of Technology */ +/* Transfer at the California Institute of Technology. */ +/* Software written by Gerard J. Holzmann. For tool documentation see: */ +/* http://spinroot.com/ */ +/* Bug-reports and/or questions can be send to: bugs@spinroot.com */ + +static char *Code2c[] = { /* multi-core option - Spin 5.0 and later */ + "#if NCORE>1", + "#if defined(WIN32) || defined(WIN64)", + " #ifndef _CONSOLE", + " #define _CONSOLE", + " #endif", + " #ifdef WIN64", + " #undef long", + " #endif", + " #include ", + " #ifdef WIN64", + " #define long long long", + " #endif", + "#else", + " #include ", + " #include ", + " #include ", + "#endif", + "", + "/* code common to cygwin/linux and win32/win64: */", + "", + "#ifdef VERBOSE", + " #define VVERBOSE (1)", + "#else", + " #define VVERBOSE (0)", + "#endif", + "", + "/* the following values must be larger than 256 and must fit in an int */", + "#define QUIT 1024 /* terminate now command */", + "#define QUERY 512 /* termination status query message */", + "#define QUERY_F 513 /* query failed, cannot quit */", + "", + "#define GN_FRAMES (int) (GWQ_SIZE / (double) sizeof(SM_frame))", + "#define LN_FRAMES (int) (LWQ_SIZE / (double) sizeof(SM_frame))", + "", + "#ifndef VMAX", + " #define VMAX VECTORSZ", + "#endif", + "#ifndef PMAX", + " #define PMAX 64", + "#endif", + "#ifndef QMAX", + " #define QMAX 64", + "#endif", + "", + "#if VECTORSZ>32000", + " #define OFFT int", + "#else", + " #define OFFT short", + "#endif", + "", + "#ifdef SET_SEG_SIZE", + " /* no longer usefule -- being recomputed for local heap size anyway */", + " double SEG_SIZE = (((double) SET_SEG_SIZE) * 1048576.);", + "#else", + " double SEG_SIZE = (1048576.*1024.); /* 1GB default shared memory pool segments */", + "#endif", + "", + "double LWQ_SIZE = 0.; /* initialized in main */", + "", + "#ifdef SET_WQ_SIZE", + " #ifdef NGQ", + " #warning SET_WQ_SIZE applies to global queue -- ignored", + " double GWQ_SIZE = 0.;", + " #else", + " double GWQ_SIZE = (((double) SET_WQ_SIZE) * 1048576.);", + " /* must match the value in pan_proxy.c, if used */", + " #endif", + "#else", + " #ifdef NGQ", + " double GWQ_SIZE = 0.;", + " #else", + " double GWQ_SIZE = (128.*1048576.); /* 128 MB default queue sizes */", + " #endif", + "#endif", + "", + "/* Crash Detection Parameters */", + "#ifndef ONESECOND", + " #define ONESECOND (1<<25)", /* name is somewhat of a misnomer */ + "#endif", + "#ifndef SHORT_T", + " #define SHORT_T (0.1)", + "#endif", + "#ifndef LONG_T", + " #define LONG_T (600)", + "#endif", + "", + "double OneSecond = (double) (ONESECOND); /* waiting for a free slot -- checks crash */", + "double TenSeconds = 10. * (ONESECOND); /* waiting for a lock -- check for a crash */", + "", + "/* Termination Detection Params -- waiting for new state input in Get_Full_Frame */", + "double Delay = ((double) SHORT_T) * (ONESECOND); /* termination detection trigger */", + "double OneHour = ((double) LONG_T) * (ONESECOND); /* timeout termination detection */", + "", + "typedef struct SM_frame SM_frame;", + "typedef struct SM_results SM_results;", + "typedef struct sh_Allocater sh_Allocater;", + "", + "struct SM_frame { /* about 6K per slot */", + " volatile int m_vsize; /* 0 means free slot */", + " volatile int m_boq; /* >500 is a control message */", + "#ifdef FULL_TRAIL", + " volatile struct Stack_Tree *m_stack; /* ptr to previous state */", + "#endif", + " volatile uchar m_tau;", + " volatile uchar m_o_pm;", + " volatile int nr_handoffs; /* to compute real_depth */", + " volatile char m_now [VMAX];", + " volatile char m_Mask [(VMAX + 7)/8];", + " volatile OFFT m_p_offset[PMAX];", + " volatile OFFT m_q_offset[QMAX];", + " volatile uchar m_p_skip [PMAX];", + " volatile uchar m_q_skip [QMAX];", + "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)", + " volatile uchar m_c_stack [StackSize];", + /* captures contents of c_stack[] for unmatched objects */ + "#endif", + "};", + "", + "int proxy_pid; /* id of proxy if nonzero -- receive half */", + "int store_proxy_pid;", + "short remote_party;", + "int proxy_pid_snd; /* id of proxy if nonzero -- send half */", + "char o_cmdline[512]; /* to pass options to children */", + "", + "int iamin[CS_NR+NCORE]; /* non-shared */", + "", +"#if defined(WIN32) || defined(WIN64)", + "int tas(volatile LONG *);", + "", + "HANDLE proxy_handle_snd; /* for Windows Create and Terminate */", + "", + "struct sh_Allocater { /* shared memory for states */", + " volatile char *dc_arena; /* to allocate states from */", + " volatile long pattern; /* to detect overruns */", + " volatile long dc_size; /* nr of bytes left */", + " volatile void *dc_start; /* where memory segment starts */", + " volatile void *dc_id; /* to attach, detach, remove shared memory segments */", + " volatile sh_Allocater *nxt; /* linked list of pools */", + "};", + "DWORD worker_pids[NCORE]; /* root mem of pids of all workers created */", + "HANDLE worker_handles[NCORE]; /* for windows Create and Terminate */", + "void * shmid [NR_QS]; /* return value from CreateFileMapping */", + "void * shmid_M; /* shared mem for state allocation in hashtable */", + "", + "#ifdef SEP_STATE", + " void *shmid_X;", + "#else", + " void *shmid_S; /* shared bitstate arena or hashtable */", + "#endif", +"#else", + "int tas(volatile int *);", + "", + "struct sh_Allocater { /* shared memory for states */", + " volatile char *dc_arena; /* to allocate states from */", + " volatile long pattern; /* to detect overruns */", + " volatile long dc_size; /* nr of bytes left */", + " volatile char *dc_start; /* where memory segment starts */", + " volatile int dc_id; /* to attach, detach, remove shared memory segments */", + " volatile sh_Allocater *nxt; /* linked list of pools */", + "};", + "", + "int worker_pids[NCORE]; /* root mem of pids of all workers created */", + "int shmid [NR_QS]; /* return value from shmget */", + "int nibis = 0; /* set after shared mem has been released */", + "int shmid_M; /* shared mem for state allocation in hashtable */", + "#ifdef SEP_STATE", + " long shmid_X;", + "#else", + " int shmid_S; /* shared bitstate arena or hashtable */", + " volatile sh_Allocater *first_pool; /* of shared state memory */", + " volatile sh_Allocater *last_pool;", + "#endif", /* SEP_STATE */ +"#endif", /* WIN32 || WIN64 */ + "", + "struct SM_results { /* for shuttling back final stats */", + " volatile int m_vsize; /* avoid conflicts with frames */", + " volatile int m_boq; /* these 2 fields are not written in record_info */", + " /* probably not all fields really need to be volatile */", + " volatile double m_memcnt;", + " volatile double m_nstates;", + " volatile double m_truncs;", + " volatile double m_truncs2;", + " volatile double m_nShadow;", + " volatile double m_nlinks;", + " volatile double m_ngrabs;", + " volatile double m_nlost;", + " volatile double m_hcmp;", + " volatile double m_frame_wait;", + " volatile int m_hmax;", + " volatile int m_svmax;", + " volatile int m_smax;", + " volatile int m_mreached;", + " volatile int m_errors;", + " volatile int m_VMAX;", + " volatile short m_PMAX;", + " volatile short m_QMAX;", + " volatile uchar m_R; /* reached info for all proctypes */", + "};", + "", + "int core_id = 0; /* internal process nr, to know which q to use */", + "unsigned long nstates_put = 0; /* statistics */", + "unsigned long nstates_get = 0;", + "int query_in_progress = 0; /* termination detection */", + "", + "double free_wait = 0.; /* waiting for a free frame */", + "double frame_wait = 0.; /* waiting for a full frame */", + "double lock_wait = 0.; /* waiting for access to cs */", + "double glock_wait[3]; /* waiting for access to global lock */", + "", + "char *sprefix = \"rst\";", + "uchar was_interrupted, issued_kill, writing_trail;", + "", + "static SM_frame cur_Root; /* current root, to be safe with error trails */", + "", + "SM_frame *m_workq [NR_QS]; /* per cpu work queues + global q */", + "char *shared_mem[NR_QS]; /* return value from shmat */", + "#ifdef SEP_HEAP", + "char *my_heap;", + "long my_size;", + "#endif", + "volatile sh_Allocater *dc_shared; /* assigned at initialization */", + "", + "static int vmax_seen, pmax_seen, qmax_seen;", + "static double gq_tries, gq_hasroom, gq_hasnoroom;", + "", + "volatile int *prfree;", /* [NCORE] */ + "volatile int *prfull;", /* [NCORE] */ + "volatile int *prcnt;", /* [NCORE] */ + "volatile int *prmax;", /* [NCORE] */ + "", + "volatile int *sh_lock; /* mutual exclusion locks - in shared memory */", + "volatile double *is_alive; /* to detect when processes crash */", + "volatile int *grfree, *grfull, *grcnt, *grmax; /* access to shared global q */", + "volatile double *gr_readmiss, *gr_writemiss;", + "static int lrfree; /* used for temporary recording of slot */", + "static int dfs_phase2;", + "", + "void mem_put(int); /* handoff state to other cpu */", + "void mem_put_acc(void); /* liveness mode */", + "void mem_get(void); /* get state from work queue */", + "void sudden_stop(char *);", + "#if 0", + "void enter_critical(int);", + "void leave_critical(int);", + "#endif", + "", + "void", + "record_info(SM_results *r)", + "{ int i;", + " uchar *ptr;", + "", + "#ifdef SEP_STATE", + " if (0)", + " { cpu_printf(\"nstates %%g nshadow %%g -- memory %%-6.3f Mb\\n\",", + " nstates, nShadow, memcnt/(1048576.));", + " }", + " r->m_memcnt = 0;", + "#else", + " #ifdef BITSTATE", + " r->m_memcnt = 0; /* it's shared */", + " #endif", + " r->m_memcnt = memcnt;", + "#endif", + " if (a_cycles && core_id == 1)", + " { r->m_nstates = nstates;", + " r->m_nShadow = nstates;", + " } else", + " { r->m_nstates = nstates;", + " r->m_nShadow = nShadow;", + " }", + " r->m_truncs = truncs;", + " r->m_truncs2 = truncs2;", + " r->m_nlinks = nlinks;", + " r->m_ngrabs = ngrabs;", + " r->m_nlost = nlost;", + " r->m_hcmp = hcmp;", + " r->m_frame_wait = frame_wait;", + " r->m_hmax = hmax;", + " r->m_svmax = svmax;", + " r->m_smax = smax;", + " r->m_mreached = mreached;", + " r->m_errors = errors;", + " r->m_VMAX = vmax_seen;", + " r->m_PMAX = (short) pmax_seen;", + " r->m_QMAX = (short) qmax_seen;", + " ptr = (uchar *) &(r->m_R);", + " for (i = 0; i <= _NP_; i++) /* all proctypes */", + " { memcpy(ptr, reached[i], NrStates[i]*sizeof(uchar));", + " ptr += NrStates[i]*sizeof(uchar);", + " }", + " if (verbose>1)", + " { cpu_printf(\"Put Results nstates %%g (sz %%d)\\n\", nstates, ptr - &(r->m_R));", + " }", + "}", + "", + "void snapshot(void);", + "", + "void", + "retrieve_info(SM_results *r)", + "{ int i, j;", + " volatile uchar *ptr;", + "", + " snapshot(); /* for a final report */", + "", + " enter_critical(GLOBAL_LOCK);", + "#ifdef SEP_HEAP", + " if (verbose)", + " { printf(\"cpu%%d: local heap-left %%ld KB (%%d MB)\\n\",", + " core_id, (long) (my_size/1024), (int) (my_size/1048576));", + " }", + "#endif", + " if (verbose && core_id == 0)", + " { printf(\"qmax: \");", + " for (i = 0; i < NCORE; i++)", + " { printf(\"%%d \", prmax[i]);", + " }", + "#ifndef NGQ", + " printf(\"G: %%d\", *grmax);", + "#endif", + " printf(\"\\n\");", + " }", + " leave_critical(GLOBAL_LOCK);", + "", + " memcnt += r->m_memcnt;", + " nstates += r->m_nstates;", + " nShadow += r->m_nShadow;", + " truncs += r->m_truncs;", + " truncs2 += r->m_truncs2;", + " nlinks += r->m_nlinks;", + " ngrabs += r->m_ngrabs;", + " nlost += r->m_nlost;", + " hcmp += r->m_hcmp;", + " /* frame_wait += r->m_frame_wait; */", + " errors += r->m_errors;", + "", + " if (hmax < r->m_hmax) hmax = r->m_hmax;", + " if (svmax < r->m_svmax) svmax = r->m_svmax;", + " if (smax < r->m_smax) smax = r->m_smax;", + " if (mreached < r->m_mreached) mreached = r->m_mreached;", + "", + " if (vmax_seen < r->m_VMAX) vmax_seen = r->m_VMAX;", + " if (pmax_seen < (int) r->m_PMAX) pmax_seen = (int) r->m_PMAX;", + " if (qmax_seen < (int) r->m_QMAX) qmax_seen = (int) r->m_QMAX;", + "", + " ptr = &(r->m_R);", + " for (i = 0; i <= _NP_; i++) /* all proctypes */", + " { for (j = 0; j < NrStates[i]; j++)", + " { if (*(ptr + j) != 0)", + " { reached[i][j] = 1;", + " } }", + " ptr += NrStates[i]*sizeof(uchar);", + " }", + " if (verbose>1)", + " { cpu_printf(\"Got Results (%%d)\\n\", (int) (ptr - &(r->m_R)));", + " snapshot();", + " }", + "}", + "", + "#if !defined(WIN32) && !defined(WIN64)", + "static void", + "rm_shared_segments(void)", + "{ int m;", + " volatile sh_Allocater *nxt_pool;", + " /*", + " * mark all shared memory segments for removal ", + " * the actual removes wont happen intil last process dies or detaches", + " * the shmctl calls can return -1 if not all procs have detached yet", + " */", + " for (m = 0; m < NR_QS; m++) /* +1 for global q */", + " { if (shmid[m] != -1)", + " { (void) shmctl(shmid[m], IPC_RMID, NULL);", + " } }", + "#ifdef SEP_STATE", + " if (shmid_M != -1)", + " { (void) shmctl(shmid_M, IPC_RMID, NULL);", + " }", + "#else", + " if (shmid_S != -1)", + " { (void) shmctl(shmid_S, IPC_RMID, NULL);", + " }", + " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)", + " { shmid_M = (int) (last_pool->dc_id);", + " nxt_pool = last_pool->nxt; /* as a pre-caution only */", + " if (shmid_M != -1)", + " { (void) shmctl(shmid_M, IPC_RMID, NULL);", + " } }", + "#endif", + "}", + "#endif", + "", + "void", + "sudden_stop(char *s)", + "{ char b[64];", + " int i;", + "", + " printf(\"cpu%%d: stop - %%s\\n\", core_id, s);", + "#if !defined(WIN32) && !defined(WIN64)", + " if (proxy_pid != 0)", + " { rm_shared_segments();", + " }", + "#endif", + " if (search_terminated != NULL)", + " { if (*search_terminated != 0)", + " { if (verbose)", + " { printf(\"cpu%%d: termination initiated (%%d)\\n\",", + " core_id, *search_terminated);", + " }", + " } else", + " { if (verbose)", + " { printf(\"cpu%%d: initiated termination\\n\", core_id);", + " }", + " *search_terminated |= 8; /* sudden_stop */", + " }", + " if (core_id == 0)", + " { if (((*search_terminated) & 4) /* uerror in one of the cpus */", + " && !((*search_terminated) & (8|32|128|256))) /* abnormal stop */", + " { if (errors == 0) errors++; /* we know there is at least 1 */", + " }", + " wrapup(); /* incomplete stats, but at least something */", + " }", + " return;", + " } /* else: should rarely happen, take more drastic measures */", + "", + " if (core_id == 0) /* local root process */", + " { for (i = 1; i < NCORE; i++) /* not for 0 of course */", + " {", + "#if defined(WIN32) || defined(WIN64)", + " DWORD dwExitCode = 0;", + " GetExitCodeProcess(worker_handles[i], &dwExitCode);", + " if (dwExitCode == STILL_ACTIVE)", + " { TerminateProcess(worker_handles[i], 0);", + " }", + " printf(\"cpu0: terminate %%d %%d\\n\",", + " worker_pids[i], (dwExitCode == STILL_ACTIVE));", + "#else", + " sprintf(b, \"kill -%%d %%d\", SIGKILL, worker_pids[i]);", + " system(b); /* if this is a proxy: receive half */", + " printf(\"cpu0: %%s\\n\", b);", + "#endif", + " }", + " issued_kill++;", + " } else", + " { /* on WIN32/WIN64 -- these merely kills the root process... */", + " if (was_interrupted == 0)", /* 2=SIGINT to root to trigger stop */ + " { sprintf(b, \"kill -%%d %%d\", SIGINT, worker_pids[0]);", + " system(b); /* warn the root process */", + " printf(\"cpu%%d: %%s\\n\", core_id, b);", + " issued_kill++;", + " } }", + "}", + "", + "#define iam_alive() is_alive[core_id]++", /* for crash detection */ + "", + "extern int crash_test(double);", + "extern void crash_reset(void);", + "", + "int", + "someone_crashed(int wait_type)", + "{ static double last_value = 0.0;", + " static int count = 0;", + "", + " if (search_terminated == NULL", + " || *search_terminated != 0)", + " {", + " if (!(*search_terminated & (8|32|128|256)))", + " { if (count++ < 100*NCORE)", + " { return 0;", + " } }", + " return 1;", + " }", + " /* check left neighbor only */", + " if (last_value == is_alive[(core_id + NCORE - 1) %% NCORE])", + " { if (count++ >= 100) /* to avoid unnecessary checks */", + " { return 1;", + " }", + " return 0;", + " }", + " last_value = is_alive[(core_id + NCORE - 1) %% NCORE];", + " count = 0;", + " crash_reset();", + " return 0;", + "}", + "", + "void", + "sleep_report(void)", + "{", + " enter_critical(GLOBAL_LOCK);", + " if (verbose)", + " {", + "#ifdef NGQ", + " printf(\"cpu%%d: locks: global %%g\\tother %%g\\t\",", + " core_id, glock_wait[0], lock_wait - glock_wait[0]);", + "#else", + " printf(\"cpu%%d: locks: GL %%g, RQ %%g, WQ %%g, HT %%g\\t\",", + " core_id, glock_wait[0], glock_wait[1], glock_wait[2],", + " lock_wait - glock_wait[0] - glock_wait[1] - glock_wait[2]);", + "#endif", + " printf(\"waits: states %%g slots %%g\\n\", frame_wait, free_wait);", + "#ifndef NGQ", + " printf(\"cpu%%d: gq [tries %%g, room %%g, noroom %%g]\\n\", core_id, gq_tries, gq_hasroom, gq_hasnoroom);", + " if (core_id == 0 && (*gr_readmiss >= 1.0 || *gr_readmiss >= 1.0 || *grcnt != 0))", + " printf(\"cpu0: gq [readmiss: %%g, writemiss: %%g cnt %%d]\\n\", *gr_readmiss, *gr_writemiss, *grcnt);", + "#endif", + " }", + " if (free_wait > 1000000.)", + " #ifndef NGQ", + " if (!a_cycles)", + " { printf(\"hint: this search may be faster with a larger work-queue\\n\");", + " printf(\" (-DSET_WQ_SIZE=N with N>%%g), and/or with -DUSE_DISK\\n\",", + " GWQ_SIZE/sizeof(SM_frame));", + " printf(\" or with a larger value for -zN (N>%%ld)\\n\", z_handoff);", + " #else", + " { printf(\"hint: this search may be faster if compiled without -DNGQ, with -DUSE_DISK, \");", + " printf(\"or with a larger -zN (N>%%d)\\n\", z_handoff);", + " #endif", + " }", + " leave_critical(GLOBAL_LOCK);", + "}", + "", + "#ifndef MAX_DSK_FILE", + " #define MAX_DSK_FILE 1000000 /* default is max 1M states per file */", + "#endif", + "", + "void", + "multi_usage(FILE *fd)", + "{ static int warned = 0;", + " if (warned > 0) { return; } else { warned++; }", + " fprintf(fd, \"\\n\");", + " fprintf(fd, \"Defining multi-core mode:\\n\\n\");", + " fprintf(fd, \" -DDUAL_CORE --> same as -DNCORE=2\\n\");", + " fprintf(fd, \" -DQUAD_CORE --> same as -DNCORE=4\\n\");", + " fprintf(fd, \" -DNCORE=N --> enables multi_core verification if N>1\\n\");", + " fprintf(fd, \"\\n\");", + " fprintf(fd, \"Additional directives supported in multi-core mode:\\n\\n\");", + " fprintf(fd, \" -DSEP_STATE --> forces separate statespaces instead of a single shared state space\\n\");", + " fprintf(fd, \" -DNUSE_DISK --> use disk for storing states when a work queue overflows\\n\");", + " fprintf(fd, \" -DMAX_DSK_FILE --> max nr of states per diskfile (%%d)\\n\", MAX_DSK_FILE);", + " fprintf(fd, \" -DFULL_TRAIL --> support full error trails (increases memory use)\\n\");", + " fprintf(fd, \"\\n\");", + " fprintf(fd, \"More advanced use (should rarely need changing):\\n\\n\");", + " fprintf(fd, \" To change the nr of states that can be stored in the global queue\\n\");", + " fprintf(fd, \" (lower numbers allow for more states to be stored, prefer multiples of 8):\\n\");", + " fprintf(fd, \" -DVMAX=N --> upperbound on statevector for handoffs (N=%%d)\\n\", VMAX);", + " fprintf(fd, \" -DPMAX=N --> upperbound on nr of procs (default: N=%%d)\\n\", PMAX);", + " fprintf(fd, \" -DQMAX=N --> upperbound on nr of channels (default: N=%%d)\\n\", QMAX);", + " fprintf(fd, \"\\n\");", +#if 0 + "#if !defined(WIN32) && !defined(WIN64)", + " fprintf(fd, \" To change the size of spin's individual shared memory segments for cygwin/linux:\\n\");", + " fprintf(fd, \" -DSET_SEG_SIZE=N --> default %%g (Mbytes)\\n\", SEG_SIZE/(1048576.));", + " fprintf(fd, \"\\n\");", + "#endif", +#endif + " fprintf(fd, \" To set the total amount of memory reserved for the global workqueue:\\n\");", + " fprintf(fd, \" -DSET_WQ_SIZE=N --> default: N=128 (defined in MBytes)\\n\\n\");", +#if 0 + " fprintf(fd, \" To omit the global workqueue completely (bad idea):\\n\");", + " fprintf(fd, \" -DNGQ\\n\\n\");", +#endif + " fprintf(fd, \" To force the use of a single global heap, instead of separate heaps:\\n\");", + " fprintf(fd, \" -DGLOB_HEAP\\n\");", + " fprintf(fd, \"\\n\");", + " fprintf(fd, \" To define a fct to initialize data before spawning processes (use quotes):\\n\");", + " fprintf(fd, \" \\\"-DC_INIT=fct()\\\"\\n\");", + " fprintf(fd, \"\\n\");", + " fprintf(fd, \" Timer settings for termination and crash detection:\\n\");", + " fprintf(fd, \" -DSHORT_T=N --> timeout for termination detection trigger (N=%%g)\\n\", (double) SHORT_T);", + " fprintf(fd, \" -DLONG_T=N --> timeout for giving up on termination detection (N=%%g)\\n\", (double) LONG_T);", + " fprintf(fd, \" -DONESECOND --> (1<<29) --> timeout waiting for a free slot -- to check for crash\\n\");", + " fprintf(fd, \" -DT_ALERT --> collect stats on crash alert timeouts\\n\\n\");", + " fprintf(fd, \"Help with Linux/Windows/Cygwin configuration for multi-core:\\n\");", + " fprintf(fd, \" http://spinroot.com/spin/multicore/V5_Readme.html\\n\");", + " fprintf(fd, \"\\n\");", + "}", + "#if NCORE>1 && defined(FULL_TRAIL)", + "typedef struct Stack_Tree {", + " uchar pr; /* process that made transition */", + " T_ID t_id; /* id of transition */", + " volatile struct Stack_Tree *prv; /* backward link towards root */", + "} Stack_Tree;", + "", + "struct H_el *grab_shared(int);", + "volatile Stack_Tree **stack_last; /* in shared memory */", + "char *stack_cache = NULL; /* local */", + "int nr_cached = 0; /* local */", + "", + "#ifndef CACHE_NR", + " #define CACHE_NR 1024", + "#endif", + "", + "volatile Stack_Tree *", + "stack_prefetch(void)", + "{ volatile Stack_Tree *st;", + "", + " if (nr_cached == 0)", + " { stack_cache = (char *) grab_shared(CACHE_NR * sizeof(Stack_Tree));", + " nr_cached = CACHE_NR;", + " }", + " st = (volatile Stack_Tree *) stack_cache;", + " stack_cache += sizeof(Stack_Tree);", + " nr_cached--;", + " return st;", + "}", + "", + "void", + "Push_Stack_Tree(short II, T_ID t_id)", + "{ volatile Stack_Tree *st;", + "", + " st = (volatile Stack_Tree *) stack_prefetch();", + " st->pr = II;", + " st->t_id = t_id;", + " st->prv = (Stack_Tree *) stack_last[core_id];", + " stack_last[core_id] = st;", + "}", + "", + "void", + "Pop_Stack_Tree(void)", + "{ volatile Stack_Tree *cf = stack_last[core_id];", + "", + " if (cf)", + " { stack_last[core_id] = cf->prv;", + " } else if (nr_handoffs * z_handoff + depth > 0)", + " { printf(\"cpu%%d: error pop_stack_tree (depth %%d)\\n\",", + " core_id, depth);", + " }", + "}", + "#endif", /* NCORE>1 && FULL_TRAIL */ + "", + "void", + "e_critical(int which)", + "{ double cnt_start;", + "", + " if (readtrail || iamin[which] > 0)", + " { if (!readtrail && verbose)", + " { printf(\"cpu%%d: Double Lock on %%d (now %%d)\\n\",", + " core_id, which, iamin[which]+1);", + " fflush(stdout);", + " }", + " iamin[which]++; /* local variable */", + " return;", + " }", + "", + " cnt_start = lock_wait;", + "", + " while (sh_lock != NULL) /* as long as we have shared memory */", + " { int r = tas(&sh_lock[which]);", + " if (r == 0)", + " { iamin[which] = 1;", + " return; /* locked */", + " }", + "", + " lock_wait++;", + "#ifndef NGQ", + " if (which < 3) { glock_wait[which]++; }", + "#else", + " if (which == 0) { glock_wait[which]++; }", + "#endif", + " iam_alive();", + "", + " if (lock_wait - cnt_start > TenSeconds)", + " { printf(\"cpu%%d: lock timeout on %%d\\n\", core_id, which);", + " cnt_start = lock_wait;", + " if (someone_crashed(1))", + " { sudden_stop(\"lock timeout\");", + " pan_exit(1);", + " } } }", + "}", + "", + "void", + "x_critical(int which)", + "{", + " if (iamin[which] != 1)", + " { if (iamin[which] > 1)", + " { iamin[which]--; /* this is thread-local - no races on this one */", + " if (!readtrail && verbose)", + " { printf(\"cpu%%d: Partial Unlock on %%d (%%d more needed)\\n\",", + " core_id, which, iamin[which]);", + " fflush(stdout);", + " }", + " return;", + " } else /* iamin[which] <= 0 */", + " { if (!readtrail)", + " { printf(\"cpu%%d: Invalid Unlock iamin[%%d] = %%d\\n\",", + " core_id, which, iamin[which]);", + " fflush(stdout);", + " }", + " return;", + " } }", + "", + " if (sh_lock != NULL)", + " { iamin[which] = 0;", + " sh_lock[which] = 0; /* unlock */", + " }", + "}", + "", + "void", + "#if defined(WIN32) || defined(WIN64)", + "start_proxy(char *s, DWORD r_pid)", + "#else", + "start_proxy(char *s, int r_pid)", + "#endif", + "{ char Q_arg[16], Z_arg[16], Y_arg[16];", + " char *args[32], *ptr;", + " int argcnt = 0;", + "", + " sprintf(Q_arg, \"-Q%%d\", getpid());", + " sprintf(Y_arg, \"-Y%%d\", r_pid);", + " sprintf(Z_arg, \"-Z%%d\", proxy_pid /* core_id */);", + "", + " args[argcnt++] = \"proxy\";", + " args[argcnt++] = s; /* -r or -s */", + " args[argcnt++] = Q_arg;", + " args[argcnt++] = Z_arg;", + " args[argcnt++] = Y_arg;", + "", + " if (strlen(o_cmdline) > 0)", + " { ptr = o_cmdline; /* assume args separated by spaces */", + " do { args[argcnt++] = ptr++;", + " if ((ptr = strchr(ptr, ' ')) != NULL)", + " { while (*ptr == ' ')", + " { *ptr++ = '\\0';", + " }", + " } else", + " { break;", + " }", + " } while (argcnt < 31);", + " }", + " args[argcnt] = NULL;", + "#if defined(WIN32) || defined(WIN64)", + " execvp(\"pan_proxy\", args); /* no return */", + "#else", + " execvp(\"./pan_proxy\", args); /* no return */", + "#endif", + " Uerror(\"pan_proxy exec failed\");", + "}", + "/*** end of common code fragment ***/", + "", + "#if !defined(WIN32) && !defined(WIN64)", + "void", + "init_shm(void) /* initialize shared work-queues - linux/cygwin */", + "{ key_t key[NR_QS];", + " int n, m;", + " int must_exit = 0;", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 3: allocate shared workqueues %%g MB\\n\",", + " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.) );", + " }", + " for (m = 0; m < NR_QS; m++) /* last q is the global q */", + " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;", + " key[m] = ftok(PanSource, m+1);", /* m must be nonzero, 1..NCORE */ + " if (key[m] == -1)", + " { perror(\"ftok shared queues\"); must_exit = 1; break;", + " }", + "", + " if (core_id == 0) /* root creates */", + " { /* check for stale copy */", + " shmid[m] = shmget(key[m], (size_t) qsize, 0600);", + " if (shmid[m] != -1) /* yes there is one; remove it */", + " { printf(\"cpu0: removing stale q%%d, status: %%d\\n\",", + " m, shmctl(shmid[m], IPC_RMID, NULL));", + " }", + " shmid[m] = shmget(key[m], (size_t) qsize, 0600|IPC_CREAT|IPC_EXCL);", + " memcnt += qsize;", + " } else /* workers attach */", + " { shmid[m] = shmget(key[m], (size_t) qsize, 0600);", + " /* never called, since we create shm *before* we fork */", + " }", + " if (shmid[m] == -1)", + " { perror(\"shmget shared queues\"); must_exit = 1; break;", + " }", + "", + " shared_mem[m] = (char *) shmat(shmid[m], (void *) 0, 0); /* attach */", + " if (shared_mem[m] == (char *) -1)", + " { fprintf(stderr, \"error: cannot attach shared wq %%d (%%d Mb)\\n\",", + " m+1, (int) (qsize/(1048576.)));", + " perror(\"shmat shared queues\"); must_exit = 1; break;", + " }", + "", + " m_workq[m] = (SM_frame *) shared_mem[m];", + " if (core_id == 0)", + " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;", + " for (n = 0; n < nframes; n++)", + " { m_workq[m][n].m_vsize = 0;", + " m_workq[m][n].m_boq = 0;", + " } } }", + "", + " if (must_exit)", + " { rm_shared_segments();", + " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1); /* calls cleanup_shm */", + " }", + "}", + "", + "static uchar *", + "prep_shmid_S(size_t n) /* either sets SS or H_tab, linux/cygwin */", + "{ char *rval;", + "#ifndef SEP_STATE", + " key_t key;", + "", + " if (verbose && core_id == 0)", + " {", + " #ifdef BITSTATE", + " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",", + " (double) n / (1048576.));", + " #else", + " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",", + " (double) n / (1048576.));", + " #endif", + " }", + " #ifdef MEMLIM", /* memlim has a value */ + " if (memcnt + (double) n > memlim)", + " { printf(\"cpu0: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",", + " memcnt/1024., (int) (n/1024), memlim/(1048576.));", + " printf(\"cpu0: insufficient memory -- aborting\\n\");", + " exit(1);", + " }", + " #endif", + "", + " key = ftok(PanSource, NCORE+2); /* different from queues */", + " if (key == -1)", + " { perror(\"ftok shared bitstate or hashtable\");", + " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1);", + " }", + "", + " if (core_id == 0) /* root */", + " { shmid_S = shmget(key, n, 0600);", + " if (shmid_S != -1)", + " { printf(\"cpu0: removing stale segment, status: %%d\\n\",", + " (int) shmctl(shmid_S, IPC_RMID, NULL));", + " }", + " shmid_S = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);", + " memcnt += (double) n;", + " } else /* worker */", + " { shmid_S = shmget(key, n, 0600);", + " }", + " if (shmid_S == -1)", + " { perror(\"shmget shared bitstate or hashtable too large?\");", + " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1);", + " }", + "", + " rval = (char *) shmat(shmid_S, (void *) 0, 0); /* attach */", + " if ((char *) rval == (char *) -1)", + " { perror(\"shmat shared bitstate or hashtable\");", + " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1);", + " }", + "#else", + " rval = (char *) emalloc(n);", + "#endif", + " return (uchar *) rval;", + "}", + "", + "#define TRY_AGAIN 1", + "#define NOT_AGAIN 0", + "", + "static char shm_prep_result;", + "", + "static uchar *", + "prep_state_mem(size_t n) /* sets memory arena for states linux/cygwin */", + "{ char *rval;", + " key_t key;", + " static int cnt = 3; /* start larger than earlier ftok calls */", + "", + " shm_prep_result = NOT_AGAIN; /* default */", + " if (verbose && core_id == 0)", + " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%6.2g Mb\\n\",", + " cnt-3, (double) n / (1048576.));", + " }", + " #ifdef MEMLIM", + " if (memcnt + (double) n > memlim)", + " { printf(\"cpu0: error: M %%.0f + %%.0f Kb exceeds memory limit of %%.0f Mb\\n\",", + " memcnt/1024.0, (double) n/1024.0, memlim/(1048576.));", + " return NULL;", + " }", + " #endif", + "", + " key = ftok(PanSource, NCORE+cnt); cnt++;", /* starts at NCORE+3 */ + " if (key == -1)", + " { perror(\"ftok T\");", + " printf(\"pan: check './pan --' for usage details\\n\");", + " pan_exit(1);", + " }", + "", + " if (core_id == 0)", + " { shmid_M = shmget(key, n, 0600);", + " if (shmid_M != -1)", + " { printf(\"cpu0: removing stale memory segment %%d, status: %%d\\n\",", + " cnt-3, shmctl(shmid_M, IPC_RMID, NULL));", + " }", + " shmid_M = shmget(key, n, 0600 | IPC_CREAT | IPC_EXCL);", + " /* memcnt += (double) n; -- only amount actually used is counted */", + " } else", + " { shmid_M = shmget(key, n, 0600);", + " ", + " }", + " if (shmid_M == -1)", + " { if (verbose)", + " { printf(\"error: failed to get pool of shared memory %%d of %%.0f Mb\\n\",", + " cnt-3, ((double)n)/(1048576.));", + " perror(\"state mem\");", + " printf(\"pan: check './pan --' for usage details\\n\");", + " }", + " shm_prep_result = TRY_AGAIN;", + " return NULL;", + " }", + " rval = (char *) shmat(shmid_M, (void *) 0, 0); /* attach */", + "", + " if ((char *) rval == (char *) -1)", + " { printf(\"cpu%%d error: failed to attach pool of shared memory %%d of %%.0f Mb\\n\",", + " core_id, cnt-3, ((double)n)/(1048576.));", + " perror(\"state mem\");", + " return NULL;", + " }", + " return (uchar *) rval;", + "}", + "", + "void", + "init_HT(unsigned long n) /* cygwin/linux version */", + "{ volatile char *x;", + " double get_mem;", + "#ifndef SEP_STATE", + " volatile char *dc_mem_start;", + " double need_mem, got_mem = 0.;", + "#endif", + "", +"#ifdef SEP_STATE", + " #ifndef MEMLIM", + " if (verbose)", + " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", /* cannot happen */ + " }", + " #else", + " if (verbose)", + " { printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",", + " MEMLIM, ((double)n/(1048576.)), (((double) NCORE * LWQ_SIZE) + GWQ_SIZE) /(1048576.) );", + " }", + " #endif", + " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *) + 4*sizeof(void *) + 2*sizeof(double);", + " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */", + " get_mem += 4 * NCORE * sizeof(void *); /* prfree, prfull, prcnt, prmax */", + " #ifdef FULL_TRAIL", + " get_mem += (NCORE) * sizeof(Stack_Tree *); /* NCORE * stack_last */", + " #endif", + " x = (volatile char *) prep_state_mem((size_t) get_mem); /* work queues and basic structs */", + " shmid_X = (long) x;", + " if (x == NULL)", /* do not repeat for smaller sizes */ + " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");", + " exit(1);", + " }", + " search_terminated = (volatile unsigned int *) x; /* comes first */", + " x += sizeof(void *); /* maintain alignment */", + "", + " is_alive = (volatile double *) x;", + " x += NCORE * sizeof(double);", + "", + " sh_lock = (volatile int *) x;", + " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */ + "", + " grfree = (volatile int *) x;", + " x += sizeof(void *);", + " grfull = (volatile int *) x;", + " x += sizeof(void *);", + " grcnt = (volatile int *) x;", + " x += sizeof(void *);", + " grmax = (volatile int *) x;", + " x += sizeof(void *);", + " prfree = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prfull = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prcnt = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prmax = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " gr_readmiss = (volatile double *) x;", + " x += sizeof(double);", + " gr_writemiss = (volatile double *) x;", + " x += sizeof(double);", + "", + " #ifdef FULL_TRAIL", + " stack_last = (volatile Stack_Tree **) x;", + " x += NCORE * sizeof(Stack_Tree *);", + " #endif", + "", + " #ifndef BITSTATE", + " H_tab = (struct H_el **) emalloc(n);", + " #endif", +"#else", + " #ifndef MEMLIM", + " #warning MEMLIM not set", /* cannot happen */ + " #define MEMLIM (2048)", + " #endif", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 0: -DMEMLIM=%%d Mb minus hashtable+workqs (%%g + %%g Mb) leaves %%g Mb\\n\",", + " MEMLIM, ((double)n/(1048576.)), (NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),", + " (memlim - memcnt - (double) n - (NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));", + " }", + " #ifndef BITSTATE", + " H_tab = (struct H_el **) prep_shmid_S((size_t) n); /* hash_table */", + " #endif", + " need_mem = memlim - memcnt - ((double) NCORE * LWQ_SIZE) - GWQ_SIZE;", + " if (need_mem <= 0.)", + " { Uerror(\"internal error -- shared state memory\");", + " }", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 2: pre-allocate shared state memory %%g Mb\\n\",", + " need_mem/(1048576.));", + " }", + "#ifdef SEP_HEAP", + " SEG_SIZE = need_mem / NCORE;", + " if (verbose && core_id == 0)", + " { printf(\"cpu0: setting segsize to %%6g MB\\n\",", + " SEG_SIZE/(1048576.));", + " }", + " #if defined(CYGWIN) || defined(__CYGWIN__)", + " if (SEG_SIZE > 512.*1024.*1024.)", + " { printf(\"warning: reducing SEG_SIZE of %%g MB to 512MB (exceeds max for Cygwin)\\n\",", + " SEG_SIZE/(1024.*1024.));", + " SEG_SIZE = 512.*1024.*1024.;", + " }", + " #endif", + "#endif", + " mem_reserved = need_mem;", + " while (need_mem > 1024.)", + " { get_mem = need_mem;", + "shm_more:", + " if (get_mem > (double) SEG_SIZE)", + " { get_mem = (double) SEG_SIZE;", + " }", + " if (get_mem <= 0.0) break;", + "", + " /* for allocating states: */", + " x = dc_mem_start = (volatile char *) prep_state_mem((size_t) get_mem);", + " if (x == NULL)", + " { if (shm_prep_result == NOT_AGAIN", + " || first_pool != NULL", + " || SEG_SIZE < (16. * 1048576.))", + " { break;", + " }", + " SEG_SIZE /= 2.;", + " if (verbose)", + " { printf(\"pan: lowered segsize to %f\\n\", SEG_SIZE);", + " }", + " if (SEG_SIZE >= 1024.)", + " { goto shm_more;", /* always terminates */ + " }", + " break;", + " }", + "", + " need_mem -= get_mem;", + " got_mem += get_mem;", + " if (first_pool == NULL)", + " { search_terminated = (volatile unsigned int *) x; /* comes first */", + " x += sizeof(void *); /* maintain alignment */", + "", + " is_alive = (volatile double *) x;", + " x += NCORE * sizeof(double);", + "", + " sh_lock = (volatile int *) x;", + " x += CS_NR * sizeof(void *);", /* allow 1 word per entry */ + "", + " grfree = (volatile int *) x;", + " x += sizeof(void *);", + " grfull = (volatile int *) x;", + " x += sizeof(void *);", + " grcnt = (volatile int *) x;", + " x += sizeof(void *);", + " grmax = (volatile int *) x;", + " x += sizeof(void *);", + " prfree = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prfull = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prcnt = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prmax = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " gr_readmiss = (volatile double *) x;", + " x += sizeof(double);", + " gr_writemiss = (volatile double *) x;", + " x += sizeof(double);", + " #ifdef FULL_TRAIL", + " stack_last = (volatile Stack_Tree **) x;", + " x += NCORE * sizeof(Stack_Tree *);", + " #endif", + " if (((long)x)&(sizeof(void *)-1)) /* 64-bit word alignment */", + " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1));", + " }", + "", + " #ifdef COLLAPSE", + " ncomps = (unsigned long *) x;", + " x += (256+2) * sizeof(unsigned long);", + " #endif", + " }", + "", + " dc_shared = (sh_Allocater *) x; /* must be in shared memory */", + " x += sizeof(sh_Allocater);", + "", + " if (core_id == 0) /* root only */", + " { dc_shared->dc_id = shmid_M;", + " dc_shared->dc_start = dc_mem_start;", + " dc_shared->dc_arena = x;", + " dc_shared->pattern = 1234567; /* protection */", + " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);", + " dc_shared->nxt = (long) 0;", + "", + " if (last_pool == NULL)", + " { first_pool = last_pool = dc_shared;", + " } else", + " { last_pool->nxt = dc_shared;", + " last_pool = dc_shared;", + " }", + " } else if (first_pool == NULL)", + " { first_pool = dc_shared;", + " } }", + "", + " if (need_mem > 1024.)", + " { printf(\"cpu0: could allocate only %%g Mb of shared memory (wanted %%g more)\\n\",", + " got_mem/(1048576.), need_mem/(1048576.));", + " }", + "", + " if (!first_pool)", + " { printf(\"cpu0: insufficient memory -- aborting.\\n\");", + " exit(1);", + " }", + " /* we are still single-threaded at this point, with core_id 0 */", + " dc_shared = first_pool;", + "", +"#endif", /* !SEP_STATE */ + "}", + "", + " /* Test and Set assembly code */", + "", + " #if defined(i386) || defined(__i386__) || defined(__x86_64__)", + " int", + " tas(volatile int *s) /* tested */", + " { int r;", + " __asm__ __volatile__(", + " \"xchgl %%0, %%1 \\n\\t\"", + " : \"=r\"(r), \"=m\"(*s)", + " : \"0\"(1), \"m\"(*s)", + " : \"memory\");", + " ", + " return r;", + " }", + " #elif defined(__arm__)", + " int", + " tas(volatile int *s) /* not tested */", + " { int r = 1;", + " __asm__ __volatile__(", + " \"swpb %%0, %%0, [%%3] \\n\"", + " : \"=r\"(r), \"=m\"(*s)", + " : \"0\"(r), \"r\"(s));", + "", + " return r;", + " }", + " #elif defined(sparc) || defined(__sparc__)", + " int", + " tas(volatile int *s) /* not tested */", + " { int r = 1;", + " __asm__ __volatile__(", + " \" ldstub [%%2], %%0 \\n\"", + " : \"=r\"(r), \"=m\"(*s)", + " : \"r\"(s));", + "", + " return r;", + " }", + " #elif defined(ia64) || defined(__ia64__)", + " /* Intel Itanium */", + " int", + " tas(volatile int *s) /* tested */", + " { long int r;", + " __asm__ __volatile__(", + " \" xchg4 %%0=%%1,%%2 \\n\"", + " : \"=r\"(r), \"+m\"(*s)", + " : \"r\"(1)", + " : \"memory\");", + " return (int) r;", + " }", + " #else", + " #error missing definition of test and set operation for this platform", + " #endif", + "", + "void", + "cleanup_shm(int val)", + "{ volatile sh_Allocater *nxt_pool;", + " unsigned long cnt = 0;", + " int m;", + "", + " if (nibis != 0)", + " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);", + " return;", + " } else", + " { nibis = 1;", + " }", + " if (search_terminated != NULL)", + " { *search_terminated |= 16; /* cleanup_shm */", + " }", + "", + " for (m = 0; m < NR_QS; m++)", + " { if (shmdt((void *) shared_mem[m]) > 0)", + " { perror(\"shmdt detaching from shared queues\");", + " } }", + "", + "#ifdef SEP_STATE", + " if (shmdt((void *) shmid_X) != 0)", + " { perror(\"shmdt detaching from shared state memory\");", + " }", + "#else", + " #ifdef BITSTATE", + " if (SS > 0 && shmdt((void *) SS) != 0)", + " { if (verbose)", + " { perror(\"shmdt detaching from shared bitstate arena\");", + " } }", + " #else", + " if (core_id == 0)", + " { /* before detaching: */", + " for (nxt_pool = dc_shared; nxt_pool != NULL; nxt_pool = nxt_pool->nxt)", + " { cnt += nxt_pool->dc_size;", + " }", + " if (verbose)", + " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",", + " cnt / (long)(1048576));", + " } }", + "", + " if (shmdt((void *) H_tab) != 0)", + " { perror(\"shmdt detaching from shared hashtable\");", + " }", + "", + " for (last_pool = first_pool; last_pool != NULL; last_pool = nxt_pool)", + " { nxt_pool = last_pool->nxt;", + " if (shmdt((void *) last_pool->dc_start) != 0)", + " { perror(\"shmdt detaching from shared state memory\");", + " } }", + " first_pool = last_pool = NULL; /* precaution */", + " #endif", + "#endif", + " /* detached from shared memory - so cannot use cpu_printf */", + " if (verbose)", + " { printf(\"cpu%%d: done -- got %%ld states from queue\\n\",", + " core_id, nstates_get);", + " }", + "}", + "", + "extern void give_up(int);", + "extern void Read_Queue(int);", + "", + "void", + "mem_get(void)", + "{ SM_frame *f;", + " int is_parent;", + "", + "#if defined(MA) && !defined(SEP_STATE)", + " #error MA without SEP_STATE is not supported with multi-core", + "#endif", + "#ifdef BFS", + " #error BFS is not supported with multi-core", + "#endif", + "#ifdef SC", + " #error SC is not supported with multi-core", + "#endif", + " init_shm(); /* we are single threaded when this starts */", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 4: calling fork()\\n\");", + " }", + " fflush(stdout);", + "", + "/* if NCORE > 1 the child or the parent should fork N-1 more times", + " * the parent is the only process with core_id == 0 and is_parent > 0", + " * the workers have is_parent = 0 and core_id = 1..NCORE-1", + " */", + " if (core_id == 0)", + " { worker_pids[0] = getpid(); /* for completeness */", + " while (++core_id < NCORE) /* first worker sees core_id = 1 */", + " { is_parent = fork();", + " if (is_parent == -1)", + " { Uerror(\"fork failed\");", + " }", + " if (is_parent == 0) /* this is a worker process */", + " { if (proxy_pid == core_id) /* always non-zero */", + " { start_proxy(\"-r\", 0); /* no return */", + " }", + " goto adapt; /* root process continues spawning */", + " }", + " worker_pids[core_id] = is_parent;", + " }", + " /* note that core_id is now NCORE */", + " if (proxy_pid > 0 && proxy_pid < NCORE)", /* add send-half of proxy */ + " { proxy_pid_snd = fork();", + " if (proxy_pid_snd == -1)", + " { Uerror(\"proxy fork failed\");", + " }", + " if (proxy_pid_snd == 0)", + " { start_proxy(\"-s\", worker_pids[proxy_pid]); /* no return */", + " } } /* else continue */", + + " if (is_parent > 0)", + " { core_id = 0; /* reset core_id for root process */", + " }", + " } else /* worker */", + " { static char db0[16]; /* good for up to 10^6 cores */", + " static char db1[16];", + "adapt: tprefix = db0; sprefix = db1;", + " sprintf(tprefix, \"cpu%%d_trail\", core_id);", + " sprintf(sprefix, \"cpu%%d_rst\", core_id);", + " memcnt = 0; /* count only additionally allocated memory */", + " }", + " signal(SIGINT, give_up);", + "", + " if (proxy_pid == 0) /* not in a cluster setup, pan_proxy must attach */", + " { rm_shared_segments(); /* mark all shared segments for removal on exit */", + " }", /* doing it early means less chance of being unable to do this */ + " if (verbose)", + " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());", + " }", + + "#if defined(SEP_HEAP) && !defined(SEP_STATE)", /* set my_heap and adjust dc_shared */ + " { int i;", + " volatile sh_Allocater *ptr;", + " ptr = first_pool;", + " for (i = 0; i < NCORE && ptr != NULL; i++)", + " { if (i == core_id)", + " { my_heap = (char *) ptr->dc_arena;", + " my_size = (long) ptr->dc_size;", + " if (verbose)", + " cpu_printf(\"local heap %%ld MB\\n\", my_size/(1048576));", + " break;", + " }", + " ptr = ptr->nxt; /* local */", + " }", + " if (my_heap == NULL)", + " { printf(\"cpu%%d: no local heap\\n\", core_id);", + " pan_exit(1);", + " } /* else */", + " #if defined(CYGWIN) || defined(__CYGWIN__)", + " ptr = first_pool;", + " for (i = 0; i < NCORE && ptr != NULL; i++)", + " { ptr = ptr->nxt; /* local */", + " }", + " dc_shared = ptr; /* any remainder */", + " #else", + " dc_shared = NULL; /* used all mem for local heaps */", + " #endif", + " }", + "#endif", + + " if (core_id == 0 && !remote_party)", + " { new_state(); /* cpu0 explores root */", + " if (verbose)", + " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), read q\\n\",", + " nstates, nstates_put);", + " dfs_phase2 = 1;", + " }", + " Read_Queue(core_id); /* all cores */", + "", + " if (verbose)", + " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",", + " nstates_put, nstates_get);", + " }", + " if (proxy_pid != 0)", + " { rm_shared_segments();", + " }", + " done = 1;", + " wrapup();", + " exit(0);", + "}", + "", + "#else", + "int unpack_state(SM_frame *, int);", + "#endif", + "", + "struct H_el *", + "grab_shared(int n)", + "{", + "#ifndef SEP_STATE", + " char *rval = (char *) 0;", + "", + " if (n == 0)", + " { printf(\"cpu%%d: grab shared zero\\n\", core_id); fflush(stdout);", + " return (struct H_el *) rval;", + " } else if (n&(sizeof(void *)-1))", + " { n += sizeof(void *)-(n&(sizeof(void *)-1)); /* alignment */", + " }", + "", + "#ifdef SEP_HEAP", + " /* no locking */", + " if (my_heap != NULL && my_size > n)", + " { rval = my_heap;", + " my_heap += n;", + " my_size -= n;", + " goto done;", + " }", + "#endif", + "", + " if (!dc_shared)", + " { sudden_stop(\"pan: out of memory\");", + " }", + "", + " /* another lock is always already in effect when this is called */", + " /* but not always the same lock -- i.e., on different parts of the hashtable */", + " enter_critical(GLOBAL_LOCK); /* this must be independently mutex */", + "#if defined(SEP_HEAP) && !defined(WIN32) && !defined(WIN64)", + " { static int noted = 0;", + " if (!noted)", + " { noted = 1;", + " printf(\"cpu%%d: global heap has %%ld bytes left, needed %%d\\n\",", + " core_id, dc_shared?dc_shared->dc_size:0, n);", + " } }", + "#endif", + "#if 0", /* for debugging */ + " if (dc_shared->pattern != 1234567)", + " { leave_critical(GLOBAL_LOCK);", + " Uerror(\"overrun -- memory corruption\");", + " }", + "#endif", + " if (dc_shared->dc_size < n)", + " { if (verbose)", + " { printf(\"Next Pool %%g Mb + %%d\\n\", memcnt/(1048576.), n);", + " }", + " if (dc_shared->nxt == NULL", + " || dc_shared->nxt->dc_arena == NULL", + " || dc_shared->nxt->dc_size < n)", + " { printf(\"cpu%%d: memcnt %%g Mb + wanted %%d bytes more\\n\",", + " core_id, memcnt / (1048576.), n);", + " leave_critical(GLOBAL_LOCK);", + " sudden_stop(\"out of memory -- aborting\");", + " wrapup(); /* exits */", + " } else", + " { dc_shared = (sh_Allocater *) dc_shared->nxt;", + " } }", + "", + " rval = (char *) dc_shared->dc_arena;", + " dc_shared->dc_arena += n;", + " dc_shared->dc_size -= (long) n;", + "#if 0", + " if (VVERBOSE)", + " printf(\"cpu%%d grab shared (%%d bytes) -- %%ld left\\n\",", + " core_id, n, dc_shared->dc_size);", + "#endif", + " leave_critical(GLOBAL_LOCK);", + "done:", + " memset(rval, 0, n);", + " memcnt += (double) n;", + "", + " return (struct H_el *) rval;", + "#else", + " return (struct H_el *) emalloc(n);", + "#endif", + "}", + "", + "SM_frame *", + "Get_Full_Frame(int n)", + "{ SM_frame *f;", + " double cnt_start = frame_wait;", + "", + " f = &m_workq[n][prfull[n]];", + " while (f->m_vsize == 0) /* await full slot LOCK : full frame */", + " { iam_alive();", + "#ifndef NGQ", + " #ifndef SAFETY", + " if (!a_cycles || core_id != 0)", + " #endif", + " if (*grcnt > 0) /* accessed outside lock, but safe even if wrong */", + " { enter_critical(GQ_RD); /* gq - read access */", + " if (*grcnt > 0) /* could have changed */", + " { f = &m_workq[NCORE][*grfull]; /* global q */", + " if (f->m_vsize == 0)", + " { /* writer is still filling the slot */", + " *gr_writemiss++;", + " f = &m_workq[n][prfull[n]]; /* reset */", + " } else", + " { *grfull = (*grfull+1) %% (GN_FRAMES);", + " enter_critical(GQ_WR);", + " *grcnt = *grcnt - 1;", + " leave_critical(GQ_WR);", + " leave_critical(GQ_RD);", + " return f;", + " } }", + " leave_critical(GQ_RD);", + " }", + "#endif", + " if (frame_wait++ - cnt_start > Delay)", + " { if (0)", /* too frequent to enable this one */ + " { cpu_printf(\"timeout on q%%d -- %%u -- query %%d\\n\",", + " n, f, query_in_progress);", + " }", + " return (SM_frame *) 0; /* timeout */", + " } }", + " iam_alive();", + " if (VVERBOSE) cpu_printf(\"got frame from q%%d\\n\", n);", + " prfull[n] = (prfull[n] + 1) %% (LN_FRAMES);", + " enter_critical(QLOCK(n));", + " prcnt[n]--; /* lock out increments */", + " leave_critical(QLOCK(n));", + " return f;", + "}", + "", + "SM_frame *", + "Get_Free_Frame(int n)", + "{ SM_frame *f;", + " double cnt_start = free_wait;", + "", + " if (VVERBOSE) { cpu_printf(\"get free frame from q%%d\\n\", n); }", + "", + " if (n == NCORE) /* global q */", + " { f = &(m_workq[n][lrfree]);", + " } else", + " { f = &(m_workq[n][prfree[n]]);", + " }", + " while (f->m_vsize != 0) /* await free slot LOCK : free slot */", + " { iam_alive();", + " if (free_wait++ - cnt_start > OneSecond)", + " { if (verbose)", + " { cpu_printf(\"timeout waiting for free slot q%%d\\n\", n);", + " }", + " cnt_start = free_wait;", + " if (someone_crashed(1))", + " { printf(\"cpu%%d: search terminated\\n\", core_id);", + " sudden_stop(\"get free frame\");", + " pan_exit(1);", + " } } }", + " if (n != NCORE)", + " { prfree[n] = (prfree[n] + 1) %% (LN_FRAMES);", + " enter_critical(QLOCK(n));", + " prcnt[n]++; /* lock out decrements */", + " if (prmax[n] < prcnt[n])", + " { prmax[n] = prcnt[n];", + " }", + " leave_critical(QLOCK(n));", + " }", + " return f;", + "}", + "", + "#ifndef NGQ", + "int", + "GlobalQ_HasRoom(void)", + "{ int rval = 0;", + "", + " gq_tries++;", + " if (*grcnt < GN_FRAMES) /* there seems to be room */", + " { enter_critical(GQ_WR); /* gq write access */", + " if (*grcnt < GN_FRAMES)", + " { if (m_workq[NCORE][*grfree].m_vsize != 0)", + " { /* can happen if reader is slow emptying slot */", + " *gr_readmiss++;", + " goto out; /* dont wait: release lock and return */", + " }", + " lrfree = *grfree; /* Get_Free_Frame use lrfree in this mode */", + " *grfree = (*grfree + 1) %% GN_FRAMES;", /* next process looks at next slot */ + " *grcnt = *grcnt + 1; /* count nr of slots filled -- no additional lock needed */", + " if (*grmax < *grcnt) *grmax = *grcnt;", + " leave_critical(GQ_WR); /* for short lock duration */", + " gq_hasroom++;", + " mem_put(NCORE); /* copy state into reserved slot */", + " rval = 1; /* successfull handoff */", + " } else", + " { gq_hasnoroom++;", + "out: leave_critical(GQ_WR);", /* should be rare */ + " } }", + " return rval;", + "}", + "#endif", + "", + "int", + "unpack_state(SM_frame *f, int from_q)", + "{ int i, j;", + " static struct H_el D_State;", + "", + " if (f->m_vsize > 0)", + " { boq = f->m_boq;", + " if (boq > 256)", + " { cpu_printf(\"saw control %%d, expected state\\n\", boq);", + " return 0;", + " }", + " vsize = f->m_vsize;", + "correct:", + " memcpy((uchar *) &now, (uchar *) f->m_now, vsize);", + " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)", + " { Mask[i] = (f->m_Mask[i/8] & (1< 0)", + " { memcpy((uchar *) proc_offset, (uchar *) f->m_p_offset, now._nr_pr * sizeof(OFFT));", + " memcpy((uchar *) proc_skip, (uchar *) f->m_p_skip, now._nr_pr * sizeof(uchar));", + " }", + " if (now._nr_qs > 0)", + " { memcpy((uchar *) q_offset, (uchar *) f->m_q_offset, now._nr_qs * sizeof(OFFT));", + " memcpy((uchar *) q_skip, (uchar *) f->m_q_skip, now._nr_qs * sizeof(uchar));", + " }", + "#ifndef NOVSZ", + " if (vsize != now._vsz)", + " { cpu_printf(\"vsize %%d != now._vsz %%d (type %%d) %%d\\n\",", + " vsize, now._vsz, f->m_boq, f->m_vsize);", + " vsize = now._vsz;", + " goto correct; /* rare event: a race */", + " }", + "#endif", + " hmax = max(hmax, vsize);", + "", + " if (f != &cur_Root)", + " { memcpy((uchar *) &cur_Root, (uchar *) f, sizeof(SM_frame));", + " }", + "", + " if (((now._a_t) & 1) == 1) /* i.e., when starting nested DFS */", + " { A_depth = depthfound = 0;", + " memcpy((uchar *)&A_Root, (uchar *)&now, vsize);", + " }", + " nr_handoffs = f->nr_handoffs;", + " } else", + " { cpu_printf(\"pan: state empty\\n\");", + " }", + "", + " depth = 0;", + " trpt = &trail[1];", + " trpt->tau = f->m_tau;", + " trpt->o_pm = f->m_o_pm;", + "", + " (trpt-1)->ostate = &D_State; /* stub */", + " trpt->ostate = &D_State;", + "", + "#ifdef FULL_TRAIL", + " if (upto > 0)", + " { stack_last[core_id] = (Stack_Tree *) f->m_stack;", + " }", + " #if defined(VERBOSE)", + " if (stack_last[core_id])", + " { cpu_printf(\"%%d: UNPACK -- SET m_stack %%u (%%d,%%d)\\n\",", + " depth, stack_last[core_id], stack_last[core_id]->pr,", + " stack_last[core_id]->t_id);", + " }", + " #endif", + "#endif", + "", + " if (!trpt->o_t)", + " { static Trans D_Trans;", + " trpt->o_t = &D_Trans;", + " }", + "", + " #ifdef VERI", + " if ((trpt->tau & 4) != 4)", + " { trpt->tau |= 4; /* the claim moves first */", + " cpu_printf(\"warning: trpt was not up to date\\n\");", + " }", + " #endif", + "", + " for (i = 0; i < (int) now._nr_pr; i++)", + " { P0 *ptr = (P0 *) pptr(i);", + " #ifndef NP", + " if (accpstate[ptr->_t][ptr->_p])", + " { trpt->o_pm |= 2;", + " }", + " #else", + " if (progstate[ptr->_t][ptr->_p])", + " { trpt->o_pm |= 4;", + " }", + " #endif", + " }", + "", + " #ifdef EVENT_TRACE", + " #ifndef NP", + " if (accpstate[EVENT_TRACE][now._event])", + " { trpt->o_pm |= 2;", + " }", + " #else", + " if (progstate[EVENT_TRACE][now._event])", + " { trpt->o_pm |= 4;", + " }", + " #endif", + " #endif", + "", + " #if defined(C_States) && (HAS_TRACK==1)", + " /* restore state of tracked C objects */", + " c_revert((uchar *) &(now.c_state[0]));", + " #if (HAS_STACK==1)", + " c_unstack((uchar *) f->m_c_stack); /* unmatched tracked data */", + " #endif", + " #endif", + " return 1;", + "}", + "", + "void", + "write_root(void) /* for trail file */", + "{ int fd;", + "", + " if (iterative == 0 && Nr_Trails > 1)", + " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);", + " else", + " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);", + "", + " if (cur_Root.m_vsize == 0)", + " { (void) unlink(fnm); /* remove possible old copy */", + " return; /* its the default initial state */", + " }", + "", + " if ((fd = creat(fnm, TMODE)) < 0)", + " { char *q;", + " if ((q = strchr(TrailFile, \'.\')))", + " { *q = \'\\0\'; /* strip .pml */", + " if (iterative == 0 && Nr_Trails-1 > 0)", + " sprintf(fnm, \"%%s%%d.%%s\", TrailFile, Nr_Trails-1, sprefix);", + " else", + " sprintf(fnm, \"%%s.%%s\", TrailFile, sprefix);", + " *q = \'.\';", + " fd = creat(fnm, TMODE);", + " }", + " if (fd < 0)", + " { cpu_printf(\"pan: cannot create %%s\\n\", fnm);", + " perror(\"cause\");", + " return;", + " } }", + "", + " if (write(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))", + " { cpu_printf(\"pan: error writing %%s\\n\", fnm);", + " } else", + " { cpu_printf(\"pan: wrote %%s\\n\", fnm);", + " }", + " close(fd);", + "}", + "", + "void", + "set_root(void)", + "{ int fd;", + " char *q;", + " char MyFile[512];", /* enough to hold a reasonable pathname */ + " char MySuffix[16];", + " char *ssuffix = \"rst\";", + " int try_core = 1;", + "", + " strcpy(MyFile, TrailFile);", + "try_again:", + " if (whichtrail > 0)", + " { sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);", + " fd = open(fnm, O_RDONLY, 0);", + " if (fd < 0 && (q = strchr(MyFile, \'.\')))", + " { *q = \'\\0\'; /* strip .pml */", + " sprintf(fnm, \"%%s%%d.%%s\", MyFile, whichtrail, ssuffix);", + " *q = \'.\';", + " fd = open(fnm, O_RDONLY, 0);", + " }", + " } else", + " { sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);", + " fd = open(fnm, O_RDONLY, 0);", + " if (fd < 0 && (q = strchr(MyFile, \'.\')))", + " { *q = \'\\0\'; /* strip .pml */", + " sprintf(fnm, \"%%s.%%s\", MyFile, ssuffix);", + " *q = \'.\';", + " fd = open(fnm, O_RDONLY, 0);", + " } }", + "", + " if (fd < 0)", + " { if (try_core < NCORE)", + " { ssuffix = MySuffix;", + " sprintf(ssuffix, \"cpu%%d_rst\", try_core++);", + " goto try_again;", + " }", + " cpu_printf(\"no file '%%s.rst' or '%%s' (not an error)\\n\", MyFile, fnm);", + " } else", + " { if (read(fd, &cur_Root, sizeof(SM_frame)) != sizeof(SM_frame))", + " { cpu_printf(\"read error %%s\\n\", fnm);", + " close(fd);", + " pan_exit(1);", + " }", + " close(fd);", + " (void) unpack_state(&cur_Root, -2);", + "#ifdef SEP_STATE", + " cpu_printf(\"partial trail -- last few steps only\\n\");", + "#endif", + " cpu_printf(\"restored root from '%%s'\\n\", fnm);", + " printf(\"=====State:=====\\n\");", + " { int i, j; P0 *z;", + " for (i = 0; i < now._nr_pr; i++)", + " { z = (P0 *)pptr(i);", + " printf(\"proc %%2d (%%s) \", i, procname[z->_t]);", + + " for (j = 0; src_all[j].src; j++)", + " if (src_all[j].tp == (int) z->_t)", + " { printf(\" %%s:%%d \",", + " PanSource, src_all[j].src[z->_p]);", + " break;", + " }", + " printf(\"(state %%d)\\n\", z->_p);", + " c_locals(i, z->_t);", + " }", + " c_globals();", + " }", + " printf(\"================\\n\");", + " }", + "}", + "", + "#ifdef USE_DISK", + "unsigned long dsk_written, dsk_drained;", + "void mem_drain(void);", + "#endif", + "", + "void", + "m_clear_frame(SM_frame *f)", /* clear room for stats */ + "{ int i, clr_sz = sizeof(SM_results);", + "", + " for (i = 0; i <= _NP_; i++) /* all proctypes */", + " { clr_sz += NrStates[i]*sizeof(uchar);", + " }", + " memset(f, 0, clr_sz);", + " /* caution if sizeof(SM_results) > sizeof(SM_frame) */", + "}", + "", + "#define TargetQ_Full(n) (m_workq[n][prfree[n]].m_vsize != 0)", /* no free slot */ + "#define TargetQ_NotFull(n) (m_workq[n][prfree[n]].m_vsize == 0)", /* avoiding prcnt */ + "", + "int", + "AllQueuesEmpty(void)", + "{ int q;", + "#ifndef NGQ", + " if (*grcnt != 0)", + " { return 0;", + " }", + "#endif", + " for (q = 0; q < NCORE; q++)", + " { if (prcnt[q] != 0)", /* not locked, ok if race */ + " { return 0;", + " } }", + " return 1;", + "}", + "", + "void", + "Read_Queue(int q)", + "{ SM_frame *f, *of;", + " int remember, target_q;", + " SM_results *r;", + " double patience = 0.0;", + "", + " target_q = (q + 1) %% NCORE;", + "", + " for (;;)", + " { f = Get_Full_Frame(q);", + " if (!f) /* 1 second timeout -- and trigger for Query */", + " { if (someone_crashed(2))", + " { printf(\"cpu%%d: search terminated [code %%d]\\n\",", + " core_id, search_terminated?*search_terminated:-1);", + " sudden_stop(\"\");", + " pan_exit(1);", + " }", + "#ifdef TESTING", + " /* to profile with cc -pg and gprof pan.exe -- set handoff depth beyond maxdepth */", + " exit(0);", + "#endif", + " remember = *grfree;", + " if (core_id == 0 /* root can initiate termination */", + " && remote_party == 0 /* and only the original root */", + " && query_in_progress == 0 /* unless its already in progress */", + " && AllQueuesEmpty())", + " { f = Get_Free_Frame(target_q);", + " query_in_progress = 1; /* only root process can do this */", + " if (!f) { Uerror(\"Fatal1: no free slot\"); }", + " f->m_boq = QUERY; /* initiate Query */", + " if (verbose)", + " { cpu_printf(\"snd QUERY to q%%d (%%d) into slot %%d\\n\",", + " target_q, nstates_get + 1, prfree[target_q]-1);", + " }", + " f->m_vsize = remember + 1;", + " /* number will not change unless we receive more states */", + " } else if (patience++ > OneHour) /* one hour watchdog timer */", + " { cpu_printf(\"timeout -- giving up\\n\");", + " sudden_stop(\"queue timeout\");", + " pan_exit(1);", + " }", + " if (0) cpu_printf(\"timed out -- try again\\n\");", + " continue; ", + " }", + " patience = 0.0; /* reset watchdog */", + "", + " if (f->m_boq == QUERY)", + " { if (verbose)", + " { cpu_printf(\"got QUERY on q%%d (%%d <> %%d) from slot %%d\\n\",", + " q, f->m_vsize, nstates_put + 1, prfull[q]-1);", + " snapshot();", + " }", + " remember = f->m_vsize;", + " f->m_vsize = 0; /* release slot */", + "", + " if (core_id == 0 && remote_party == 0) /* original root cpu0 */", + " { if (query_in_progress == 1 /* didn't send more states in the interim */", + " && *grfree + 1 == remember) /* no action on global queue meanwhile */", + " { if (verbose) cpu_printf(\"Termination detected\\n\");", + " if (TargetQ_Full(target_q))", + " { if (verbose)", + " cpu_printf(\"warning: target q is full\\n\");", + " }", + " f = Get_Free_Frame(target_q);", + " if (!f) { Uerror(\"Fatal2: no free slot\"); }", + " m_clear_frame(f);", + " f->m_boq = QUIT; /* send final Quit, collect stats */", + " f->m_vsize = 111; /* anything non-zero will do */", + " if (verbose)", + " cpu_printf(\"put QUIT on q%%d\\n\", target_q);", + " } else", + " { if (verbose) cpu_printf(\"Stale Query\\n\");", + "#ifdef USE_DISK", + " mem_drain();", + "#endif", + " }", + " query_in_progress = 0;", + " } else", + " { if (TargetQ_Full(target_q))", + " { if (verbose)", + " cpu_printf(\"warning: forward query - target q full\\n\");", + " }", + " f = Get_Free_Frame(target_q);", + " if (verbose)", + " cpu_printf(\"snd QUERY response to q%%d (%%d <> %%d) in slot %%d\\n\",", + " target_q, remember, *grfree + 1, prfree[target_q]-1);", + " if (!f) { Uerror(\"Fatal4: no free slot\"); }", + "", + " if (*grfree + 1 == remember) /* no action on global queue */", + " { f->m_boq = QUERY; /* forward query, to root */", + " f->m_vsize = remember;", + " } else", + " { f->m_boq = QUERY_F; /* no match -- busy */", + " f->m_vsize = 112; /* anything non-zero */", + "#ifdef USE_DISK", + " if (dsk_written != dsk_drained)", + " { mem_drain();", + " }", + "#endif", + " } }", + " continue;", + " }", + "", + " if (f->m_boq == QUERY_F)", + " { if (verbose)", + " { cpu_printf(\"got QUERY_F on q%%d from slot %%d\\n\", q, prfull[q]-1);", + " }", + " f->m_vsize = 0; /* release slot */", + "", + " if (core_id == 0 && remote_party == 0) /* original root cpu0 */", + " { if (verbose) cpu_printf(\"No Match on Query\\n\");", + " query_in_progress = 0;", + " } else", + " { if (TargetQ_Full(target_q))", + " { if (verbose) cpu_printf(\"warning: forwarding query_f, target queue full\\n\");", + " }", + " f = Get_Free_Frame(target_q);", + " if (verbose) cpu_printf(\"forward QUERY_F to q%%d into slot %%d\\n\",", + " target_q, prfree[target_q]-1);", + " if (!f) { Uerror(\"Fatal5: no free slot\"); }", + " f->m_boq = QUERY_F; /* cannot terminate yet */", + " f->m_vsize = 113; /* anything non-zero */", + " }", + "#ifdef USE_DISK", + " if (dsk_written != dsk_drained)", + " { mem_drain();", + " }", + "#endif", + " continue;", + " }", + "", + " if (f->m_boq == QUIT)", + " { if (0) cpu_printf(\"done -- local memcnt %%g Mb\\n\", memcnt/(1048576.));", + " retrieve_info((SM_results *) f); /* collect and combine stats */", + " if (verbose)", + " { cpu_printf(\"received Quit\\n\");", + " snapshot();", + " }", + " f->m_vsize = 0; /* release incoming slot */", + " if (core_id != 0)", + " { f = Get_Free_Frame(target_q); /* new outgoing slot */", + " if (!f) { Uerror(\"Fatal6: no free slot\"); }", + " m_clear_frame(f); /* start with zeroed stats */", + " record_info((SM_results *) f);", + " f->m_boq = QUIT; /* forward combined results */", + " f->m_vsize = 114; /* anything non-zero */", + " if (verbose>1)", + " cpu_printf(\"fwd Results to q%%d\\n\", target_q);", + " }", + " break; /* successful termination */", + " }", + "", + " /* else: 0<= boq <= 255, means STATE transfer */", + " if (unpack_state(f, q) != 0)", + " { nstates_get++;", + " f->m_vsize = 0; /* release slot */", + " if (VVERBOSE) cpu_printf(\"Got state\\n\");", + "", + " if (search_terminated != NULL", + " && *search_terminated == 0)", + " { new_state(); /* explore successors */", + " memset((uchar *) &cur_Root, 0, sizeof(SM_frame)); /* avoid confusion */", + " } else", + " { pan_exit(0);", + " }", + " } else", + " { pan_exit(0);", + " } }", + " if (verbose) cpu_printf(\"done got %%d put %%d\\n\", nstates_get, nstates_put);", + " sleep_report();", + "}", + "", + "void", + "give_up(int unused_x)", + "{", + " if (search_terminated != NULL)", + " { *search_terminated |= 32; /* give_up */", + " }", + " if (!writing_trail)", + " { was_interrupted = 1;", + " snapshot();", + " cpu_printf(\"Give Up\\n\");", + " sleep_report();", + " pan_exit(1);", + " } else /* we are already terminating */", + " { cpu_printf(\"SIGINT\\n\");", + " }", + "}", + "", + "void", + "check_overkill(void)", + "{", + " vmax_seen = (vmax_seen + 7)/ 8;", + " vmax_seen *= 8; /* round up to a multiple of 8 */", + "", + " if (core_id == 0", + " && !remote_party", + " && nstates_put > 0", + " && VMAX - vmax_seen > 8)", + " {", + "#ifdef BITSTATE", + " printf(\"cpu0: max VMAX value seen in this run: \");", + "#else", + " printf(\"cpu0: recommend recompiling with \");", + "#endif", + " printf(\"-DVMAX=%%d\\n\", vmax_seen);", + " }", + "}", + "", + "void", + "mem_put(int q) /* handoff state to other cpu, workq q */", + "{ SM_frame *f;", + " int i, j;", + "", + " if (vsize > VMAX)", + " { vsize = (vsize + 7)/8; vsize *= 8; /* round up */", + " printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", (int) vsize);", + " Uerror(\"aborting\");", + " }", + " if (now._nr_pr > PMAX)", + " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);", + " Uerror(\"aborting\");", + " }", + " if (now._nr_qs > QMAX)", + " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);", + " Uerror(\"aborting\");", + " }", + " if (vsize > vmax_seen) vmax_seen = vsize;", + " if (now._nr_pr > pmax_seen) pmax_seen = now._nr_pr;", + " if (now._nr_qs > qmax_seen) qmax_seen = now._nr_qs;", + "", + " f = Get_Free_Frame(q); /* not called in likely deadlock states */", + " if (!f) { Uerror(\"Fatal3: no free slot\"); }", + "", + " if (VVERBOSE) cpu_printf(\"putting state into q%%d\\n\", q);", + "", + " memcpy((uchar *) f->m_now, (uchar *) &now, vsize);", + " memset((uchar *) f->m_Mask, 0, (VMAX+7)/8 * sizeof(char));", + " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)", + " { if (Mask[i])", + " { f->m_Mask[i/8] |= (1< 0)", + " { memcpy((uchar *) f->m_p_offset, (uchar *) proc_offset, now._nr_pr * sizeof(OFFT));", + " memcpy((uchar *) f->m_p_skip, (uchar *) proc_skip, now._nr_pr * sizeof(uchar));", + " }", + " if (now._nr_qs > 0)", + " { memcpy((uchar *) f->m_q_offset, (uchar *) q_offset, now._nr_qs * sizeof(OFFT));", + " memcpy((uchar *) f->m_q_skip, (uchar *) q_skip, now._nr_qs * sizeof(uchar));", + " }", + "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)", + " c_stack((uchar *) f->m_c_stack); /* save unmatched tracked data */", + "#endif", + "#ifdef FULL_TRAIL", + " f->m_stack = stack_last[core_id];", + "#endif", + " f->nr_handoffs = nr_handoffs+1;", + " f->m_tau = trpt->tau;", + " f->m_o_pm = trpt->o_pm;", + " f->m_boq = boq;", + " f->m_vsize = vsize; /* must come last - now the other cpu can see it */", + "", + " if (query_in_progress == 1)", + " query_in_progress = 2; /* make sure we know, if a query makes the rounds */", + " nstates_put++;", + "}", + "", + "#ifdef USE_DISK", + "int Dsk_W_Nr, Dsk_R_Nr;", + "int dsk_file = -1, dsk_read = -1;", + "unsigned long dsk_written, dsk_drained;", + "char dsk_name[512];", + "", + "#ifndef BFS_DISK", + "#if defined(WIN32) || defined(WIN64)", + " #define RFLAGS (O_RDONLY|O_BINARY)", + " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC|O_BINARY)", + "#else", + " #define RFLAGS (O_RDONLY)", + " #define WFLAGS (O_CREAT|O_WRONLY|O_TRUNC)", + "#endif", + "#endif", + "", + "void", + "dsk_stats(void)", + "{ int i;", + "", + " if (dsk_written > 0)", + " { cpu_printf(\"dsk_written %%d states in %%d files\\ncpu%%d: dsk_drained %%6d states\\n\",", + " dsk_written, Dsk_W_Nr, core_id, dsk_drained);", + " close(dsk_read);", + " close(dsk_file);", + " for (i = 0; i < Dsk_W_Nr; i++)", + " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", i, core_id);", + " unlink(dsk_name);", + " } }", + "}", + "", + "void", + "mem_drain(void)", + "{ SM_frame *f, g;", + " int q = (core_id + 1) %% NCORE; /* target q */", + " int sz;", + "", + " if (dsk_read < 0", + " || dsk_written <= dsk_drained)", + " { return;", + " }", + "", + " while (dsk_written > dsk_drained", + " && TargetQ_NotFull(q))", + " { f = Get_Free_Frame(q);", + " if (!f) { Uerror(\"Fatal: unhandled condition\"); }", + "", + " if ((dsk_drained+1)%%MAX_DSK_FILE == 0) /* 100K states max per file */", + " { (void) close(dsk_read); /* close current read handle */", + " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr++, core_id);", + " (void) unlink(dsk_name); /* remove current file */", + " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_R_Nr, core_id);", + " cpu_printf(\"reading %%s\\n\", dsk_name);", + " dsk_read = open(dsk_name, RFLAGS); /* open next file */", + " if (dsk_read < 0)", + " { Uerror(\"could not open dsk file\");", + " } }", + " if (read(dsk_read, &g, sizeof(SM_frame)) != sizeof(SM_frame))", + " { Uerror(\"bad dsk file read\");", + " }", + " sz = g.m_vsize;", + " g.m_vsize = 0;", + " memcpy(f, &g, sizeof(SM_frame));", + " f->m_vsize = sz; /* last */", + "", + " dsk_drained++;", + " }", + "}", + "", + "void", + "mem_file(void)", + "{ SM_frame f;", + " int i, j, q = (core_id + 1) %% NCORE; /* target q */", + "", + " if (vsize > VMAX)", + " { printf(\"pan: recompile with -DVMAX=N with N >= %%d\\n\", vsize);", + " Uerror(\"aborting\");", + " }", + " if (now._nr_pr > PMAX)", + " { printf(\"pan: recompile with -DPMAX=N with N >= %%d\\n\", now._nr_pr);", + " Uerror(\"aborting\");", + " }", + " if (now._nr_qs > QMAX)", + " { printf(\"pan: recompile with -DQMAX=N with N >= %%d\\n\", now._nr_qs);", + " Uerror(\"aborting\");", + " }", + "", + " if (VVERBOSE) cpu_printf(\"filing state for q%%d\\n\", q);", + "", + " memcpy((uchar *) f.m_now, (uchar *) &now, vsize);", + " memset((uchar *) f.m_Mask, 0, (VMAX+7)/8 * sizeof(char));", + " for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)", + " { if (Mask[i])", + " { f.m_Mask[i/8] |= (1< 0)", + " { memcpy((uchar *)f.m_p_offset, (uchar *)proc_offset, now._nr_pr*sizeof(OFFT));", + " memcpy((uchar *)f.m_p_skip, (uchar *)proc_skip, now._nr_pr*sizeof(uchar));", + " }", + " if (now._nr_qs > 0)", + " { memcpy((uchar *) f.m_q_offset, (uchar *) q_offset, now._nr_qs*sizeof(OFFT));", + " memcpy((uchar *) f.m_q_skip, (uchar *) q_skip, now._nr_qs*sizeof(uchar));", + " }", + "#if defined(C_States) && (HAS_TRACK==1) && (HAS_STACK==1)", + " c_stack((uchar *) f.m_c_stack); /* save unmatched tracked data */", + "#endif", + "#ifdef FULL_TRAIL", + " f.m_stack = stack_last[core_id];", + "#endif", + " f.nr_handoffs = nr_handoffs+1;", + " f.m_tau = trpt->tau;", + " f.m_o_pm = trpt->o_pm;", + " f.m_boq = boq;", + " f.m_vsize = vsize;", + "", + " if (query_in_progress == 1)", + " { query_in_progress = 2;", + " }", + " if (dsk_file < 0)", + " { sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr, core_id);", + " dsk_file = open(dsk_name, WFLAGS, 0644);", + " dsk_read = open(dsk_name, RFLAGS);", + " if (dsk_file < 0 || dsk_read < 0)", + " { cpu_printf(\"File: <%%s>\\n\", dsk_name);", + " Uerror(\"cannot open diskfile\");", + " }", + " Dsk_W_Nr++; /* nr of next file to open */", + " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);", + " } else if ((dsk_written+1)%%MAX_DSK_FILE == 0)", + " { close(dsk_file); /* close write handle */", + " sprintf(dsk_name, \"Q%%.3d_%%.3d.tmp\", Dsk_W_Nr++, core_id);", + " dsk_file = open(dsk_name, WFLAGS, 0644);", + " if (dsk_file < 0)", + " { cpu_printf(\"File: <%%s>\\n\", dsk_name);", + " Uerror(\"aborting: cannot open new diskfile\");", + " }", + " cpu_printf(\"created temporary diskfile %%s\\n\", dsk_name);", + " }", + " if (write(dsk_file, &f, sizeof(SM_frame)) != sizeof(SM_frame))", + " { Uerror(\"aborting -- disk write failed (disk full?)\");", + " }", + " nstates_put++;", + " dsk_written++;", + "}", + "#endif", + "", + "int", + "mem_hand_off(void)", + "{", + " if (search_terminated == NULL", + " || *search_terminated != 0) /* not a full crash check */", + " { pan_exit(0);", + " }", + " iam_alive(); /* on every transition of Down */", + "#ifdef USE_DISK", + " mem_drain(); /* maybe call this also on every Up */", + "#endif", + " if (depth > z_handoff /* above handoff limit */", + "#ifndef SAFETY", + " && !a_cycles /* not in liveness mode */", + "#endif", + "#if SYNC", + " && boq == -1 /* not mid-rv */", + "#endif", + "#ifdef VERI", + " && (trpt->tau&4) /* claim moves first */", + " && !((trpt-1)->tau&128) /* not a stutter move */", + "#endif", + " && !(trpt->tau&8)) /* not an atomic move */", + " { int q = (core_id + 1) %% NCORE; /* circular handoff */", + " #ifdef GENEROUS", + " if (prcnt[q] < LN_FRAMES)", /* not the best strategy */ + " #else", + " if (TargetQ_NotFull(q)", + " && (dfs_phase2 == 0 || prcnt[core_id] > 0))", /* not locked, ok if race */ + " #endif", + " { mem_put(q);", /* only 1 writer: lock-free */ + " return 1;", + " }", + " { int rval;", + " #ifndef NGQ", + " rval = GlobalQ_HasRoom();", + " #else", + " rval = 0;", + " #endif", + " #ifdef USE_DISK", + " if (rval == 0)", + " { void mem_file(void);", + " mem_file();", + " rval = 1;", + " }", + " #endif", + " return rval;", + " }", + " }", + " return 0; /* i.e., no handoff */", + "}", + "", + "void", + "mem_put_acc(void) /* liveness mode */", + "{ int q = (core_id + 1) %% NCORE;", + "", + " if (search_terminated == NULL", + " || *search_terminated != 0)", + " { pan_exit(0);", + " }", + "#ifdef USE_DISK", + " mem_drain();", + "#endif", + " /* some tortured use of preprocessing: */", + "#if !defined(NGQ) || defined(USE_DISK)", + " if (TargetQ_Full(q))", + " {", + "#endif", + "#ifndef NGQ", + " if (GlobalQ_HasRoom())", + " { return;", + " }", + "#endif", + "#ifdef USE_DISK", + " mem_file();", + " } else", + "#else", + " #if !defined(NGQ) || defined(USE_DISK)", + " }", + " #endif", + "#endif", + " { mem_put(q);", + " }", + "}", + "", + "#if defined(WIN32) || defined(WIN64)", /* visual studio */ + "void", + "init_shm(void) /* initialize shared work-queues */", + "{ char key[512];", + " int n, m;", + " int must_exit = 0;", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 3: allocate shared work-queues %%g Mb\\n\",", + " ((double) NCORE * LWQ_SIZE + GWQ_SIZE) / (1048576.));", + " }", + " for (m = 0; m < NR_QS; m++) /* last q is global 1 */", + " { double qsize = (m == NCORE) ? GWQ_SIZE : LWQ_SIZE;", + " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, m);", + " if (core_id == 0)", /* root process creates shared memory segments */ + " { shmid[m] = CreateFileMapping(", + " INVALID_HANDLE_VALUE, /* use paging file */", + " NULL, /* default security */", + " PAGE_READWRITE, /* access permissions */", + " 0, /* high-order 4 bytes */", + " qsize, /* low-order bytes, size in bytes */", + " key); /* name */", + " } else /* worker nodes just open these segments */", + " { shmid[m] = OpenFileMapping(", + " FILE_MAP_ALL_ACCESS, /* read/write access */", + " FALSE, /* children do not inherit handle */", + " key);", + " }", + " if (shmid[m] == NULL)", + " { fprintf(stderr, \"cpu%%d: could not create or open shared queues\\n\",", + " core_id);", + " must_exit = 1;", + " break;", + " }", + " /* attach: */", + " shared_mem[m] = (char *) MapViewOfFile(shmid[m], FILE_MAP_ALL_ACCESS, 0, 0, 0);", + " if (shared_mem[m] == NULL)", + " { fprintf(stderr, \"cpu%%d: cannot attach shared q%%d (%%d Mb)\\n\",", + " core_id, m+1, (int) (qsize/(1048576.)));", + " must_exit = 1;", + " break;", + " }", + "", + " memcnt += qsize;", + "", + " m_workq[m] = (SM_frame *) shared_mem[m];", + " if (core_id == 0)", + " { int nframes = (m == NCORE) ? GN_FRAMES : LN_FRAMES;", + " for (n = 0; n < nframes; n++)", + " { m_workq[m][n].m_vsize = 0;", + " m_workq[m][n].m_boq = 0;", + " } } }", + "", + " if (must_exit)", + " { fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1); /* calls cleanup_shm */", + " }", + "}", + "", + "static uchar *", + "prep_shmid_S(size_t n) /* either sets SS or H_tab, WIN32/WIN64 */", + "{ char *rval;", + "#ifndef SEP_STATE", + " char key[512];", + "", + " if (verbose && core_id == 0)", + " {", + " #ifdef BITSTATE", + " printf(\"cpu0: step 1: allocate shared bitstate %%g Mb\\n\",", + " (double) n / (1048576.));", + " #else", + " printf(\"cpu0: step 1: allocate shared hastable %%g Mb\\n\",", + " (double) n / (1048576.));", + " #endif", + " }", + " #ifdef MEMLIM", + " if (memcnt + (double) n > memlim)", + " { printf(\"cpu%%d: S %%8g + %%d Kb exceeds memory limit of %%8g Mb\\n\",", + " core_id, memcnt/1024., n/1024, memlim/(1048576.));", + " printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);", + " exit(1);", + " }", + " #endif", + "", + " /* make key different from queues: */", + " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+2); /* different from qs */", + "", + " if (core_id == 0) /* root */", + " { shmid_S = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,", + "#ifdef WIN64", + " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);", + "#else", + " PAGE_READWRITE, 0, n, key);", + "#endif", + " memcnt += (double) n;", + " } else /* worker */", + " { shmid_S = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);", + " }", + + " if (shmid_S == NULL)", + " {", + " #ifdef BITSTATE", + " fprintf(stderr, \"cpu%%d: cannot %%s shared bitstate\",", + " core_id, core_id?\"open\":\"create\");", + " #else", + " fprintf(stderr, \"cpu%%d: cannot %%s shared hashtable\",", + " core_id, core_id?\"open\":\"create\");", + " #endif", + " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1);", + " }", + "", + " rval = (char *) MapViewOfFile(shmid_S, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */", + " if ((char *) rval == NULL)", + " { fprintf(stderr, \"cpu%%d: cannot attach shared bitstate or hashtable\\n\", core_id);", + " fprintf(stderr, \"pan: check './pan --' for usage details\\n\");", + " pan_exit(1);", + " }", + "#else", + " rval = (char *) emalloc(n);", + "#endif", + " return (uchar *) rval;", + "}", + "", + "static uchar *", + "prep_state_mem(size_t n) /* WIN32/WIN64 sets memory arena for states */", + "{ char *rval;", + " char key[512];", + " static int cnt = 3; /* start larger than earlier ftok calls */", + "", + " if (verbose && core_id == 0)", + " { printf(\"cpu0: step 2+: pre-allocate memory arena %%d of %%g Mb\\n\",", + " cnt-3, (double) n / (1048576.));", + " }", + " #ifdef MEMLIM", + " if (memcnt + (double) n > memlim)", + " { printf(\"cpu%%d: error: M %%.0f + %%.0f exceeds memory limit of %%.0f Kb\\n\",", + " core_id, memcnt/1024.0, (double) n/1024.0, memlim/1024.0);", + " return NULL;", + " }", + " #endif", + "", + " sprintf(key, \"Global\\\\pan_%%s_%%.3d\", PanSource, NCORE+cnt); cnt++;", + "", + " if (core_id == 0)", + " { shmid_M = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,", + "#ifdef WIN64", + " PAGE_READWRITE, (n>>32), (n & 0xffffffff), key);", + "#else", + " PAGE_READWRITE, 0, n, key);", + "#endif", + " } else", + " { shmid_M = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, key);", + " }", + " if (shmid_M == NULL)", + " { printf(\"cpu%%d: failed to get pool of shared memory nr %%d of size %%d\\n\",", + " core_id, cnt-3, n);", + " printf(\"pan: check './pan --' for usage details\\n\");", + " return NULL;", + " }", + " rval = (char *) MapViewOfFile(shmid_M, FILE_MAP_ALL_ACCESS, 0, 0, 0); /* attach */", + "", + " if (rval == NULL)", + " { printf(\"cpu%%d: failed to attach pool of shared memory nr %%d of size %%d\\n\",", + " core_id, cnt-3, n);", + " return NULL;", + " }", + " return (uchar *) rval;", + "}", + "", + "void", + "init_HT(unsigned long n) /* WIN32/WIN64 version */", + "{ volatile char *x;", + " double get_mem;", + "#ifndef SEP_STATE", + " char *dc_mem_start;", + "#endif", + " if (verbose) printf(\"cpu%%d: initialization for Windows\\n\", core_id);", + "", +"#ifdef SEP_STATE", + " #ifndef MEMLIM", + " if (verbose)", + " { printf(\"cpu0: steps 0,1: no -DMEMLIM set\\n\");", + " }", + " #else", + " if (verbose)", + " printf(\"cpu0: steps 0,1: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb)\\n\",", + " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.));", + "#endif", + " get_mem = NCORE * sizeof(double) + (1 + CS_NR) * sizeof(void *)+ 4*sizeof(void *) + 2*sizeof(double);", + " /* NCORE * is_alive + search_terminated + CS_NR * sh_lock + 6 gr vars */", + " get_mem += 4 * NCORE * sizeof(void *);", /* prfree, prfull, prcnt, prmax */ + " #ifdef FULL_TRAIL", + " get_mem += (NCORE) * sizeof(Stack_Tree *);", + " /* NCORE * stack_last */", + " #endif", + " x = (volatile char *) prep_state_mem((size_t) get_mem);", + " shmid_X = (void *) x;", + " if (x == NULL)", + " { printf(\"cpu0: could not allocate shared memory, see ./pan --\\n\");", + " exit(1);", + " }", + " search_terminated = (volatile unsigned int *) x; /* comes first */", + " x += sizeof(void *); /* maintain alignment */", + "", + " is_alive = (volatile double *) x;", + " x += NCORE * sizeof(double);", + "", + " sh_lock = (volatile int *) x;", + " x += CS_NR * sizeof(void *); /* allow 1 word per entry */", + "", + " grfree = (volatile int *) x;", + " x += sizeof(void *);", + " grfull = (volatile int *) x;", + " x += sizeof(void *);", + " grcnt = (volatile int *) x;", + " x += sizeof(void *);", + " grmax = (volatile int *) x;", + " x += sizeof(void *);", + " prfree = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prfull = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prcnt = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prmax = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " gr_readmiss = (volatile double *) x;", + " x += sizeof(double);", + " gr_writemiss = (volatile double *) x;", + " x += sizeof(double);", + "", + " #ifdef FULL_TRAIL", + " stack_last = (volatile Stack_Tree **) x;", + " x += NCORE * sizeof(Stack_Tree *);", + " #endif", + "", + " #ifndef BITSTATE", + " H_tab = (struct H_el **) emalloc(n);", + " #endif", +"#else", + " #ifndef MEMLIM", + " #warning MEMLIM not set", /* cannot happen */ + " #define MEMLIM (2048)", + " #endif", + "", + " if (core_id == 0 && verbose)", + " printf(\"cpu0: step 0: -DMEMLIM=%%d Mb - (hashtable %%g Mb + workqueues %%g Mb) = %%g Mb for state storage\\n\",", + " MEMLIM, ((double)n/(1048576.)), ((double) NCORE * LWQ_SIZE + GWQ_SIZE)/(1048576.),", + " (memlim - memcnt - (double) n - ((double) NCORE * LWQ_SIZE + GWQ_SIZE))/(1048576.));", + " #ifndef BITSTATE", + " H_tab = (struct H_el **) prep_shmid_S((size_t) n); /* hash_table */", + " #endif", + " get_mem = memlim - memcnt - ((double) NCORE) * LWQ_SIZE - GWQ_SIZE;", + " if (get_mem <= 0)", + " { Uerror(\"internal error -- shared state memory\");", + " }", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 2: shared state memory %%g Mb\\n\",", + " get_mem/(1048576.));", + " }", + " x = dc_mem_start = (char *) prep_state_mem((size_t) get_mem); /* for states */", + " if (x == NULL)", + " { printf(\"cpu%%d: insufficient memory -- aborting\\n\", core_id);", + " exit(1);", + " }", + "", + " search_terminated = (volatile unsigned int *) x; /* comes first */", + " x += sizeof(void *); /* maintain alignment */", + "", + " is_alive = (volatile double *) x;", + " x += NCORE * sizeof(double);", + "", + " sh_lock = (volatile int *) x;", + " x += CS_NR * sizeof(int);", + "", + " grfree = (volatile int *) x;", + " x += sizeof(void *);", + " grfull = (volatile int *) x;", + " x += sizeof(void *);", + " grcnt = (volatile int *) x;", + " x += sizeof(void *);", + " grmax = (volatile int *) x;", + " x += sizeof(void *);", + " prfree = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prfull = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prcnt = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " prmax = (volatile int *) x;", + " x += NCORE * sizeof(void *);", + " gr_readmiss = (volatile double *) x;", + " x += sizeof(double);", + " gr_writemiss = (volatile double *) x;", + " x += sizeof(double);", + "", + " #ifdef FULL_TRAIL", + " stack_last = (volatile Stack_Tree **) x;", + " x += NCORE * sizeof(Stack_Tree *);", + " #endif", + " if (((long)x)&(sizeof(void *)-1)) /* word alignment */", + " { x += sizeof(void *)-(((long)x)&(sizeof(void *)-1)); /* 64-bit align */", + " }", + "", + " #ifdef COLLAPSE", + " ncomps = (unsigned long *) x;", + " x += (256+2) * sizeof(unsigned long);", + " #endif", + "", + " dc_shared = (sh_Allocater *) x; /* in shared memory */", + " x += sizeof(sh_Allocater);", + "", + " if (core_id == 0) /* root only */", + " { dc_shared->dc_id = shmid_M;", + " dc_shared->dc_start = (void *) dc_mem_start;", + " dc_shared->dc_arena = x;", + " dc_shared->pattern = 1234567;", + " dc_shared->dc_size = (long) get_mem - (long) (x - dc_mem_start);", + " dc_shared->nxt = NULL;", + " }", +"#endif", + "}", + "", + "#if defined(WIN32) || defined(WIN64) || defined(__i386__) || defined(__x86_64__)", + "extern BOOLEAN InterlockedBitTestAndSet(LONG volatile* Base, LONG Bit);", + "int", + "tas(volatile LONG *s)", /* atomic test and set */ + "{ return InterlockedBitTestAndSet(s, 1);", + "}", + "#else", + " #error missing definition of test and set operation for this platform", + "#endif", + "", + "void", + "cleanup_shm(int val)", + "{ int m;", + " static int nibis = 0;", + "", + " if (nibis != 0)", + " { printf(\"cpu%%d: Redundant call to cleanup_shm(%%d)\\n\", core_id, val);", + " return;", + " } else", + " { nibis = 1;", + " }", + " if (search_terminated != NULL)", + " { *search_terminated |= 16; /* cleanup_shm */", + " }", + "", + " for (m = 0; m < NR_QS; m++)", + " { if (shmid[m] != NULL)", + " { UnmapViewOfFile((char *) shared_mem[m]);", + " CloseHandle(shmid[m]);", + " } }", + "#ifdef SEP_STATE", + " UnmapViewOfFile((void *) shmid_X);", + " CloseHandle((void *) shmid_M);", + "#else", + " #ifdef BITSTATE", + " if (shmid_S != NULL)", + " { UnmapViewOfFile(SS);", + " CloseHandle(shmid_S);", + " }", + " #else", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: done, %%ld Mb of shared state memory left\\n\",", + " dc_shared->dc_size / (long)(1048576));", + " }", + " if (shmid_S != NULL)", + " { UnmapViewOfFile(H_tab);", + " CloseHandle(shmid_S);", + " }", + " shmid_M = (void *) (dc_shared->dc_id);", + " UnmapViewOfFile((char *) dc_shared->dc_start);", + " CloseHandle(shmid_M);", + " #endif", + "#endif", + " /* detached from shared memory - so cannot use cpu_printf */", + " if (verbose)", + " { printf(\"cpu%%d: done -- got %%d states from queue\\n\",", + " core_id, nstates_get);", + " }", + "}", + "", + "void", + "mem_get(void)", + "{ SM_frame *f;", + " int is_parent;", + "", + "#if defined(MA) && !defined(SEP_STATE)", + " #error MA requires SEP_STATE in multi-core mode", + "#endif", + "#ifdef BFS", + " #error BFS is not supported in multi-core mode", + "#endif", + "#ifdef SC", + " #error SC is not supported in multi-core mode", + "#endif", + " init_shm(); /* we are single threaded when this starts */", + " signal(SIGINT, give_up); /* windows control-c interrupt */", + "", + " if (core_id == 0 && verbose)", + " { printf(\"cpu0: step 4: creating additional workers (proxy %%d)\\n\",", + " proxy_pid);", + " }", + "#if 0", + " if NCORE > 1 the child or the parent should fork N-1 more times", + " the parent is the only process with core_id == 0 and is_parent > 0", + " the others (workers) have is_parent = 0 and core_id = 1..NCORE-1", + "#endif", + " if (core_id == 0) /* root starts up the workers */", + " { worker_pids[0] = (DWORD) getpid(); /* for completeness */", + " while (++core_id < NCORE) /* first worker sees core_id = 1 */", + " { char cmdline[64];", + " STARTUPINFO si = { sizeof(si) };", + " PROCESS_INFORMATION pi;", + "", + " if (proxy_pid == core_id) /* always non-zero */", + " { sprintf(cmdline, \"pan_proxy.exe -r %%s-Q%%d -Z%%d\",", + " o_cmdline, getpid(), core_id);", + " } else", + " { sprintf(cmdline, \"pan.exe %%s-Q%%d -Z%%d\",", + " o_cmdline, getpid(), core_id);", + " }", + " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);", + "", + " is_parent = CreateProcess(0, cmdline, 0, 0, FALSE, 0, 0, 0, &si, &pi);", + " if (is_parent == 0)", + " { Uerror(\"fork failed\");", + " }", + " worker_pids[core_id] = pi.dwProcessId;", + " worker_handles[core_id] = pi.hProcess;", + " if (verbose)", + " { cpu_printf(\"created core %%d, pid %%d\\n\",", + " core_id, pi.dwProcessId);", + " }", + " if (proxy_pid == core_id) /* we just created the receive half */", + " { /* add proxy send, store pid in proxy_pid_snd */", + " sprintf(cmdline, \"pan_proxy.exe -s %%s-Q%%d -Z%%d -Y%%d\",", + " o_cmdline, getpid(), core_id, worker_pids[proxy_pid]);", + " if (verbose) printf(\"cpu%%d: spawn %%s\\n\", core_id, cmdline);", + " is_parent = CreateProcess(0, cmdline, 0,0, FALSE, 0,0,0, &si, &pi);", + " if (is_parent == 0)", + " { Uerror(\"fork failed\");", + " }", + " proxy_pid_snd = pi.dwProcessId;", + " proxy_handle_snd = pi.hProcess;", + " if (verbose)", + " { cpu_printf(\"created core %%d, pid %%d (send proxy)\\n\",", + " core_id, pi.dwProcessId);", + " } } }", + " core_id = 0; /* reset core_id for root process */", + " } else /* worker */", + " { static char db0[16]; /* good for up to 10^6 cores */", + " static char db1[16];", + " tprefix = db0; sprefix = db1;", + " sprintf(tprefix, \"cpu%%d_trail\", core_id); /* avoid conflicts on file access */", + " sprintf(sprefix, \"cpu%%d_rst\", core_id);", + " memcnt = 0; /* count only additionally allocated memory */", + " }", + " if (verbose)", + " { cpu_printf(\"starting core_id %%d -- pid %%d\\n\", core_id, getpid());", + " }", + " if (core_id == 0 && !remote_party)", + " { new_state(); /* root starts the search */", + " if (verbose)", + " cpu_printf(\"done with 1st dfs, nstates %%g (put %%d states), start reading q\\n\",", + " nstates, nstates_put);", + " dfs_phase2 = 1;", + " }", + " Read_Queue(core_id); /* all cores */", + "", + " if (verbose)", + " { cpu_printf(\"put %%6d states into queue -- got %%6d\\n\",", + " nstates_put, nstates_get);", + " }", + " done = 1;", + " wrapup();", + " exit(0);", + "}", + "#endif", /* WIN32 || WIN64 */ + "", + "#ifdef BITSTATE", + "void", + "init_SS(unsigned long n)", + "{", + " SS = (uchar *) prep_shmid_S((size_t) n);", + " init_HT(0L);", /* locks and shared memory for Stack_Tree allocations */ + "}", + "#endif", /* BITSTATE */ + "", + "#endif", /* NCORE>1 */ + 0, +}; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pangen7.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/spin/pangen7.c Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,925 @@ +/***** spin: pangen7.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 */ +/* pangen7.c: Version 5.3.0 2010, synchronous product of never claims */ + +#include +#include "spin.h" +#include "y.tab.h" +#include +#ifdef PC +extern int unlink(const char *); +#else +#include +#endif + +extern ProcList *rdy; +extern Element *Al_El; +extern int nclaims, verbose, Strict; + +typedef struct Succ_List Succ_List; +typedef struct SQueue SQueue; +typedef struct OneState OneState; +typedef struct State_Stack State_Stack; +typedef struct Guard Guard; + +struct Succ_List { + SQueue *s; + Succ_List *nxt; +}; + +struct OneState { + int *combo; /* the combination of claim states */ + Succ_List *succ; /* list of ptrs to immediate successor states */ +}; + +struct SQueue { + OneState state; + SQueue *nxt; +}; + +struct State_Stack { + int *n; + State_Stack *nxt; +}; + +struct Guard { + Lextok *t; + Guard *nxt; +}; + +SQueue *sq, *sd, *render; /* states move from sq to sd to render to holding */ +SQueue *holding, *lasthold; +State_Stack *dsts; + +int nst; /* max nr of states in claims */ +int *Ist; /* initial states */ +int *Nacc; /* number of accept states in claim */ +int *Nst; /* next states */ +int **reached; /* n claims x states */ +int unfolding; /* to make sure all accept states are reached */ +int is_accept; /* remember if the current state is accepting in any claim */ +int not_printing; /* set during explore_product */ + +Element ****matrix; /* n x two-dimensional arrays state x state */ +Element **Selfs; /* self-loop states at end of claims */ + +static void get_seq(int, Sequence *); +static void set_el(int n, Element *e); +static void gen_product(void); +static void print_state_nm(char *, int *, char *); +static SQueue *find_state(int *); +static SQueue *retrieve_state(int *); + +static int +same_state(int *a, int *b) +{ int i; + + for (i = 0; i < nclaims; i++) + { if (a[i] != b[i]) + { return 0; + } } + return 1; +} + +static int +in_stack(SQueue *s, SQueue *in) +{ SQueue *q; + + for (q = in; q; q = q->nxt) + { if (same_state(q->state.combo, s->state.combo)) + { return 1; + } } + return 0; +} + +static void +to_render(SQueue *s) +{ SQueue *a, *q, *last; /* find in sd/sq and move to render, if not already there */ + int n; + + for (n = 0; n < nclaims; n++) + { reached[n][ s->state.combo[n] ] |= 2; + } + + for (q = render; q; q = q->nxt) + { if (same_state(q->state.combo, s->state.combo)) + { return; + } } + for (q = holding; q; q = q->nxt) + { if (same_state(q->state.combo, s->state.combo)) + { return; + } } + + a = sd; +more: + for (q = a, last = 0; q; last = q, q = q->nxt) + { if (same_state(q->state.combo, s->state.combo)) + { if (!last) + { if (a == sd) + { sd = q->nxt; + } else if (a == sq) + { sq = q->nxt; + } else + { holding = q->nxt; + } + } else + { last->nxt = q->nxt; + } + q->nxt = render; + render = q; + return; + } } + if (verbose) + { print_state_nm("looking for: ", s->state.combo, "\n"); + } + (void) find_state(s->state.combo); /* creates it in sq */ + if (a != sq) + { a = sq; + goto more; + } + fatal("cannot happen, to_render", 0); +} + +static void +wrap_text(char *pre, Lextok *t, char *post) +{ + printf(pre); + comment(stdout, t, 0); + printf(post); +} + +static State_Stack * +push_dsts(int *n) +{ State_Stack *s; + int i; + + for (s = dsts; s; s = s->nxt) + { if (same_state(s->n, n)) + { if (verbose&64) + { printf("\n"); + for (s = dsts; s; s = s->nxt) + { print_state_nm("\t", s->n, "\n"); + } + print_state_nm("\t", n, "\n"); + } + return s; + } } + + s = (State_Stack *) emalloc(sizeof(State_Stack)); + s->n = (int *) emalloc(nclaims * sizeof(int)); + for (i = 0; i < nclaims; i++) + s->n[i] = n[i]; + s->nxt = dsts; + dsts = s; + return 0; +} + +static void +pop_dsts(void) +{ + assert(dsts); + dsts = dsts->nxt; +} + +static void +complete_transition(Succ_List *sl, Guard *g) +{ Guard *w; + int cnt = 0; + + printf(" :: "); + for (w = g; w; w = w->nxt) + { if (w->t->ntyp == CONST + && w->t->val == 1) + { continue; + } else if (w->t->ntyp == 'c' + && w->t->lft->ntyp == CONST + && w->t->lft->val == 1) + { continue; /* 'true' */ + } + + if (cnt > 0) + { printf(" && "); + } + wrap_text("", w->t, ""); + cnt++; + } + if (cnt == 0) + { printf("true"); + } + print_state_nm(" -> goto ", sl->s->state.combo, ""); + + if (is_accept > 0) + { printf("_U%d\n", (unfolding+1)%nclaims); + } else + { printf("_U%d\n", unfolding); + } +} + +static void +state_body(OneState *s, Guard *guard) +{ Succ_List *sl; + State_Stack *y; + Guard *g; + int i, once; + + for (sl = s->succ; sl; sl = sl->nxt) + { once = 0; + + for (i = 0; i < nclaims; i++) + { Element *e; + e = matrix[i][s->combo[i]][sl->s->state.combo[i]]; + + /* if one of the claims has a DO or IF move + then pull its target state forward, once + */ + + if (!e + || e->n->ntyp == NON_ATOMIC + || e->n->ntyp == DO + || e->n->ntyp == IF) + { s = &(sl->s->state); + y = push_dsts(s->combo); + if (!y) + { if (once++ == 0) + { assert(s->succ); + state_body(s, guard); + } + pop_dsts(); + } else if (!y->nxt) /* self-loop transition */ + { if (!not_printing) printf(" /* self-loop */\n"); + } else + { /* non_fatal("loop in state body", 0); ** maybe ok */ + } + continue; + } else + { g = (Guard *) emalloc(sizeof(Guard)); + g->t = e->n; + g->nxt = guard; + guard = g; + } } + + if (guard && !once) + { if (!not_printing) complete_transition(sl, guard); + to_render(sl->s); + } } +} + +static struct X { + char *s; int n; +} spl[] = { + {"end", 3 }, + {"accept", 6 }, + {0, 0 }, +}; + +static int slcnt; +extern Label *labtab; + +static ProcList * +locate_claim(int n) +{ ProcList *p; + int i; + + for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */ + { if (i == n) + { break; + } } + assert(p && p->b == N_CLAIM); + + return p; +} + +static void +elim_lab(Element *e) +{ Label *l, *lst; + + for (l = labtab, lst = NULL; l; lst = l, l = l->nxt) + { if (l->e == e) + { if (lst) + { lst->nxt = l->nxt; + } else + { labtab = l->nxt; + } + break; + } } +} + +static int +claim_has_accept(ProcList *p) +{ Label *l; + + for (l = labtab; l; l = l->nxt) + { if (strcmp(l->c->name, p->n->name) == 0 + && strncmp(l->s->name, "accept", 6) == 0) + { return 1; + } } + return 0; +} + +static void +prune_accept(void) +{ int n; + + for (n = 0; n < nclaims; n++) + { if ((reached[n][Selfs[n]->seqno] & 2) == 0) + { if (verbose) + { printf("claim %d: selfloop not reachable\n", n); + } + elim_lab(Selfs[n]); + Nacc[n] = claim_has_accept(locate_claim(n)); + } } +} + +static void +mk_accepting(int n, Element *e) +{ ProcList *p; + Label *l; + int i; + + assert(!Selfs[n]); + Selfs[n] = e; + + l = (Label *) emalloc(sizeof(Label)); + l->s = (Symbol *) emalloc(sizeof(Symbol)); + l->s->name = "accept00"; + l->c = (Symbol *) emalloc(sizeof(Symbol)); + l->uiid = 0; /* this is not in an inline */ + + for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */ + { if (i == n) + { l->c->name = p->n->name; + break; + } } + assert(p && p->b == N_CLAIM); + Nacc[n] = 1; + + l->e = e; + l->nxt = labtab; + labtab = l; +} + +static void +check_special(int *nrs) +{ ProcList *p; + Label *l; + int i, j, nmatches; + int any_accepts = 0; + + for (i = 0; i < nclaims; i++) + { any_accepts += Nacc[i]; + } + + is_accept = 0; + for (j = 0; spl[j].n; j++) /* 2 special label prefixes */ + { nmatches = 0; + for (p = rdy, i = 0; p; p = p->nxt, i++) /* check each claim */ + { if (p->b != N_CLAIM) + { continue; + } + /* claim i in state nrs[i], type p->tn, name p->n->name + * either the state has an accept label, or the claim has none, + * so that all its states should be considered accepting + * --- but only if other claims do have accept states! + */ + if (Strict == 0 && j == 1 && Nacc[i] == 0 && any_accepts > 0) + { if ((verbose&32) && i == unfolding) + { printf(" /* claim %d pseudo-accept */\n", i); + } + goto is_accepting; + } + for (l = labtab; l; l = l->nxt) /* check its labels */ + { if (strcmp(l->c->name, p->n->name) == 0 /* right claim */ + && l->e->seqno == nrs[i] /* right state */ + && strncmp(l->s->name, spl[j].s, spl[j].n) == 0) + { if (j == 1) /* accept state */ + { char buf[32]; +is_accepting: if (strchr(p->n->name, ':')) + { sprintf(buf, "N%d", i); + } else + { strcpy(buf, p->n->name); + } + if (unfolding == 0 && i == 0) + { if (!not_printing) + printf("%s_%s_%d:\n", /* true accept */ + spl[j].s, buf, slcnt++); + } else if (verbose&32) + { if (!not_printing) + printf("%s_%s%d:\n", + buf, spl[j].s, slcnt++); + } + if (i == unfolding) + { is_accept++; /* move to next unfolding */ + } + } else + { nmatches++; + } + break; + } } } + if (j == 0 && nmatches == nclaims) /* end-state */ + { if (!not_printing) + { printf("%s%d:\n", spl[j].s, slcnt++); + } } } +} + +static int +render_state(SQueue *q) +{ + if (!q || !q->state.succ) + { if (verbose&64) + { printf(" no exit\n"); + } + return 0; + } + + check_special(q->state.combo); /* accept or end-state labels */ + + dsts = (State_Stack *) 0; + push_dsts(q->state.combo); /* to detect loops */ + + if (!not_printing) + { print_state_nm("", q->state.combo, ""); /* the name */ + printf("_U%d:\n\tdo\n", unfolding); + } + + state_body(&(q->state), (Guard *) 0); + + if (!not_printing) + { printf("\tod;\n"); + } + pop_dsts(); + return 1; +} + +static void +explore_product(void) +{ SQueue *q; + + /* all states are in the sd queue */ + + q = retrieve_state(Ist); /* retrieve from the sd q */ + q->nxt = render; /* put in render q */ + render = q; + do { + q = render; + render = render->nxt; + q->nxt = 0; /* remove from render q */ + + if (verbose&64) + { print_state_nm("explore: ", q->state.combo, "\n"); + } + + not_printing = 1; + render_state(q); /* may add new states */ + not_printing = 0; + + if (lasthold) + { lasthold->nxt = q; + lasthold = q; + } else + { holding = lasthold = q; + } + } while (render); + assert(!dsts); + +} + +static void +print_product(void) +{ SQueue *q; + int cnt; + + if (unfolding == 0) + { printf("never Product {\n"); /* name expected by iSpin */ + q = find_state(Ist); /* should find it in the holding q */ + assert(q); + q->nxt = holding; /* put it at the front */ + holding = q; + } + render = holding; + holding = lasthold = 0; + + printf("/* ============= U%d ============= */\n", unfolding); + cnt = 0; + do { + q = render; + render = render->nxt; + q->nxt = 0; + if (verbose&64) + { print_state_nm("print: ", q->state.combo, "\n"); + } + cnt += render_state(q); + + if (lasthold) + { lasthold->nxt = q; + lasthold = q; + } else + { holding = lasthold = q; + } + } while (render); + assert(!dsts); + + if (cnt == 0) + { printf(" 0;\n"); + } + + if (unfolding == nclaims-1) + { printf("}\n"); + } +} + +static void +prune_dead(void) +{ Succ_List *sl, *last; + SQueue *q; + int cnt; + + do { cnt = 0; + for (q = sd; q; q = q->nxt) + { /* if successor is deadend, remove it + * unless it's a move to the end-state of the claim + */ + last = (Succ_List *) 0; + for (sl = q->state.succ; sl; last = sl, sl = sl->nxt) + { if (!sl->s->state.succ) /* no successor */ + { if (!last) + { q->state.succ = sl->nxt; + } else + { last->nxt = sl->nxt; + } + cnt++; + } } } + } while (cnt > 0); +} + +static void +print_raw(void) +{ int i, j, n; + + printf("#if 0\n"); + for (n = 0; n < nclaims; n++) + { printf("C%d:\n", n); + for (i = 0; i < nst; i++) + { if (reached[n][i]) + for (j = 0; j < nst; j++) + { if (matrix[n][i][j]) + { if (reached[n][i] & 2) printf("+"); + if (i == Ist[n]) printf("*"); + printf("\t%d", i); + wrap_text(" -[", matrix[n][i][j]->n, "]->\t"); + printf("%d\n", j); + } } } } + printf("#endif\n\n"); + fflush(stdout); +} + +void +sync_product(void) +{ ProcList *p; + Element *e; + int n, i; + + if (nclaims <= 1) return; + + (void) unlink("pan.pre"); + + Ist = (int *) emalloc(sizeof(int) * nclaims); + Nacc = (int *) emalloc(sizeof(int) * nclaims); + Nst = (int *) emalloc(sizeof(int) * nclaims); + reached = (int **) emalloc(sizeof(int *) * nclaims); + Selfs = (Element **) emalloc(sizeof(Element *) * nclaims); + matrix = (Element ****) emalloc(sizeof(Element ***) * nclaims); /* claims */ + + for (p = rdy, i = 0; p; p = p->nxt, i++) + { if (p->b == N_CLAIM) + { nst = max(p->s->maxel, nst); + Nacc[i] = claim_has_accept(p); + } } + + for (n = 0; n < nclaims; n++) + { reached[n] = (int *) emalloc(sizeof(int) * nst); + matrix[n] = (Element ***) emalloc(sizeof(Element **) * nst); /* rows */ + for (i = 0; i < nst; i++) /* cols */ + { matrix[n][i] = (Element **) emalloc(sizeof(Element *) * nst); + } } + + for (e = Al_El; e; e = e->Nxt) + { e->status &= ~DONE; + } + + for (p = rdy, n=0; p; p = p->nxt, n++) + { if (p->b == N_CLAIM) + { /* fill in matrix[n] */ + e = p->s->frst; + Ist[n] = huntele(e, e->status, -1)->seqno; + + reached[n][Ist[n]] = 1|2; + get_seq(n, p->s); + } } + + if (verbose) /* show only the input automata */ + { print_raw(); + } + + gen_product(); /* create product automaton */ +} + +static int +nxt_trans(int n, int cs, int frst) +{ int j; + + for (j = frst; j < nst; j++) + { if (reached[n][cs] + && matrix[n][cs][j]) + { return j; + } } + return -1; +} + +static void +print_state_nm(char *p, int *s, char *a) +{ int i; + printf("%sP", p); + for (i = 0; i < nclaims; i++) + { printf("_%d", s[i]); + } + printf("%s", a); +} + +static void +create_transition(OneState *s, SQueue *it) +{ int n, from, upto; + int *F = s->combo; + int *T = it->state.combo; + Succ_List *sl; + Lextok *t; + + if (verbose&64) + { print_state_nm("", F, " "); + print_state_nm("-> ", T, "\t"); + } + + /* check if any of the claims is blocked */ + /* which makes the state a dead-end */ + for (n = 0; n < nclaims; n++) + { from = F[n]; + upto = T[n]; + t = matrix[n][from][upto]->n; + if (verbose&64) + { wrap_text("", t, " "); + } + if (t->ntyp == 'c' + && t->lft->ntyp == CONST) + { if (t->lft->val == 0) /* i.e., false */ + { goto done; + } } } + + sl = (Succ_List *) emalloc(sizeof(Succ_List)); + sl->s = it; + sl->nxt = s->succ; + s->succ = sl; +done: + if (verbose&64) + { printf("\n"); + } +} + +static SQueue * +find_state(int *cs) +{ SQueue *nq, *a = sq; + int i; + +again: /* check in nq, sq, and then in the render q */ + for (nq = a; nq; nq = nq->nxt) + { if (same_state(nq->state.combo, cs)) + { return nq; /* found */ + } } + if (a == sq && sd) + { a = sd; + goto again; /* check the other stack too */ + } else if (a == sd && render) + { a = render; + goto again; + } + + nq = (SQueue *) emalloc(sizeof(SQueue)); + nq->state.combo = (int *) emalloc(nclaims * sizeof(int)); + for (i = 0; i < nclaims; i++) + { nq->state.combo[i] = cs[i]; + } + nq->nxt = sq; /* add to sq stack */ + sq = nq; + + return nq; +} + +static SQueue * +retrieve_state(int *s) +{ SQueue *nq, *last = NULL; + + for (nq = sd; nq; last = nq, nq = nq->nxt) + { if (same_state(nq->state.combo, s)) + { if (last) + { last->nxt = nq->nxt; + } else + { sd = nq; + } + return nq; /* found */ + } } + + fatal("cannot happen: retrieve_state", 0); + return (SQueue *) 0; +} + +static void +all_successors(int n, OneState *cur) +{ int i, j = 0; + + if (n >= nclaims) + { create_transition(cur, find_state(Nst)); + } else + { i = cur->combo[n]; + for (;;) + { j = nxt_trans(n, i, j); + if (j < 0) break; + Nst[n] = j; + all_successors(n+1, cur); + j++; + } } +} + +static void +gen_product(void) +{ OneState *cur_st; + SQueue *q; + + find_state(Ist); /* create initial state */ + + while (sq) + { if (in_stack(sq, sd)) + { sq = sq->nxt; + continue; + } + cur_st = &(sq->state); + + q = sq; + sq = sq->nxt; /* delete from sq stack */ + q->nxt = sd; /* and move to done stack */ + sd = q; + + all_successors(0, cur_st); + } + /* all states are in the sd queue now */ + prune_dead(); + explore_product(); /* check if added accept-self-loops are reachable */ + prune_accept(); + + if (verbose) + { print_raw(); + } + + /* PM: merge states with identical successor lists */ + + /* all outgoing transitions from accept-states + from claim n in copy n connect to states in copy (n+1)%nclaims + only accept states from claim 0 in copy 0 are true accept states + in the product + + PM: what about claims that have no accept states (e.g., restrictions) + */ + + for (unfolding = 0; unfolding < nclaims; unfolding++) + { print_product(); + } +} + +static void +t_record(int n, Element *e, Element *g) +{ int from = e->seqno, upto = g?g->seqno:0; + + assert(from >= 0 && from < nst); + assert(upto >= 0 && upto < nst); + + matrix[n][from][upto] = e; + reached[n][upto] |= 1; +} + +static void +get_sub(int n, Element *e) +{ + if (e->n->ntyp == D_STEP + || e->n->ntyp == ATOMIC) + { fatal("atomic or d_step in never claim product", 0); + } + /* NON_ATOMIC */ + e->n->sl->this->last->nxt = e->nxt; + get_seq(n, e->n->sl->this); + + t_record(n, e, e->n->sl->this->frst); + +} + +static void +set_el(int n, Element *e) +{ Element *g; + + if (e->n->ntyp == '@') /* change to self-loop */ + { e->n->ntyp = CONST; + e->n->val = 1; /* true */ + e->nxt = e; + g = e; + mk_accepting(n, e); + } else + + if (e->n->ntyp == GOTO) + { g = get_lab(e->n, 1); + g = huntele(g, e->status, -1); + } else if (e->nxt) + { g = huntele(e->nxt, e->status, -1); + } else + { g = NULL; + } + + t_record(n, e, g); +} + +static void +get_seq(int n, Sequence *s) +{ SeqList *h; + Element *e; + + e = huntele(s->frst, s->frst->status, -1); + for ( ; e; e = e->nxt) + { if (e->status & DONE) + { goto checklast; + } + e->status |= DONE; + + if (e->n->ntyp == UNLESS) + { fatal("unless stmnt in never claim product", 0); + } + + if (e->sub) /* IF or DO */ + { Lextok *x = NULL; + Lextok *y = NULL; + Lextok *haselse = NULL; + + for (h = e->sub; h; h = h->nxt) + { Lextok *t = h->this->frst->n; + if (t->ntyp == ELSE) + { if (verbose&64) printf("else at line %d\n", t->ln); + haselse = t; + continue; + } + if (t->ntyp != 'c') + { fatal("product, 'else' combined with non-condition", 0); + } + + if (t->lft->ntyp == CONST /* true */ + && t->lft->val == 1 + && y == NULL) + { y = nn(ZN, CONST, ZN, ZN); + y->val = 0; + } else + { if (!x) + x = t; + else + x = nn(ZN, OR, x, t); + if (verbose&64) + { wrap_text(" [", x, "]\n"); + } } } + if (haselse) + { if (!y) + { y = nn(ZN, '!', x, ZN); + } + if (verbose&64) + { wrap_text(" [else: ", y, "]\n"); + } + haselse->ntyp = 'c'; /* replace else */ + haselse->lft = y; + } + + for (h = e->sub; h; h = h->nxt) + { t_record(n, e, h->this->frst); + get_seq(n, h->this); + } + } else + { if (e->n->ntyp == ATOMIC + || e->n->ntyp == D_STEP + || e->n->ntyp == NON_ATOMIC) + { get_sub(n, e); + } else + { set_el(n, e); + } + } +checklast: if (e == s->last) + break; + } +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/pc_zpp.c --- a/sys/src/cmd/spin/pc_zpp.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/pc_zpp.c Tue Mar 06 23:34:10 2012 +0100 @@ -16,14 +16,15 @@ #include #include #include +#include "spin.h" #ifdef PC enum cstate { PLAIN, IN_STRING, IN_QUOTE, S_COMM, COMMENT, E_COMM }; #define MAXNEST 32 #define MAXDEF 128 -#define MAXLINE 512 -#define GENEROUS 4096 +#define MAXLINE 2048 +#define GENEROUS 8192 #define debug(x,y) if (verbose) printf(x,y) @@ -43,7 +44,7 @@ static int process(char *, int, char *); static int zpp_do(char *); -extern char *emalloc(int); /* main.c */ +extern char *emalloc(size_t); /* main.c */ static int do_define(char *p) @@ -116,7 +117,7 @@ if (strlen(in1)+strlen(d[i].trg)+strlen(in2+j) >= GENEROUS) { - printf("spin: circular macro expansion %s -> %s ?\n", + printf("spin: macro expansion overflow %s -> %s ?\n", d[i].src, d[i].trg); return in1; } @@ -230,8 +231,9 @@ } static int -do_else(char *unused) +do_else(char *p) { + debug("zpp: do_else %s", p); if_truth[if_depth] = 1-if_truth[if_depth]; printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth]; @@ -312,13 +314,29 @@ } static int +strip_cpp_comments(char *p) +{ char *q; + + q = strstr(p, "//"); + if (q) + { if (q > p && *(q-1) == '\\') + { return strip_cpp_comments(q+1); + } + *q = '\n'; + *(q+1) = '\0'; + return 1; + } + return 0; +} + +static int zpp_do(char *fnm) { char buf[2048], buf2[MAXLINE], *p; int n, on; FILE *inp; int lno = 0, nw_lno = 0; if ((inp = fopen(fnm, "r")) == NULL) - { fprintf(stdout, "spin: error, '%s': No such file\n", fnm); - return 0; /* 4.1.2 was stderr */ + { fprintf(stdout, "spin: error: No file '%s'\n", fnm); + exit(1); /* 4.1.2 was stderr */ } printing[0] = if_truth[0] = 1; fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm); @@ -327,7 +345,8 @@ on = 0; nw_lno = 0; while (n > 2 && buf[n-2] == '\\') { buf[n-2] = '\0'; -feedme: if (!fgets(buf2, MAXLINE, inp)) +feedme: + if (!fgets(buf2, MAXLINE, inp)) { debug("zpp: unexpected EOF ln %d\n", lno); return 0; /* switch to cpp */ } @@ -339,6 +358,10 @@ strcat(buf, buf2); n = (int) strlen(buf); } + + if (strip_cpp_comments(&buf[on])) + n = (int) strlen(buf); + if (in_comment(&buf[on])) { buf[n-1] = '\0'; /* eat newline */ on = n-1; nw_lno = 1; @@ -360,7 +383,7 @@ int try_zpp(char *fnm, char *onm) { int r; - if ((outpp = fopen(onm, "w")) == NULL) + if ((outpp = fopen(onm, MFLAGS)) == NULL) return 0; r = zpp_do(fnm); fclose(outpp); @@ -390,6 +413,27 @@ for (p = q; *p; p++) if (*p != ' ' && *p != '\t') break; + + if (strncmp(p, "line", 4) == 0) + { p += 4; + while (*p == ' ' || *p == '\t') + { p++; + } + lno = atoi(p); + return 1; /* line directive */ + } + if (isdigit((int) *p)) + { lno = atoi(p); + return 1; + } + if (strncmp(p, "error", 5) == 0) + { printf("spin: %s", p); + exit(1); + } + if (strncmp(p, "warning", 7) == 0) + { printf("spin: %s", p); + return 1; + } for (i = 0; i < (int) (sizeof(s)/sizeof(struct Directives)); i++) if (!strncmp(s[i].directive, p, s[i].len)) { if (s[i].interp diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/ps_msc.c --- a/sys/src/cmd/spin/ps_msc.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/ps_msc.c Tue Mar 06 23:34:10 2012 +0100 @@ -12,14 +12,12 @@ /* The Postscript generation code below was written by Gerard J. Holzmann */ /* in June 1997. Parts of the prolog template are based on similar boiler */ /* plate in the Tcl/Tk distribution. This code is used to support Spin's */ -/* option M for generating a Postscript file from a simulation run. */ +/* option -M for generating a Postscript file from a simulation run. */ #include "spin.h" #include "version.h" -#ifdef PC -extern void free(void *); -#endif +/* extern void free(void *); */ static char *PsPre[] = { "%%%%Pages: (atend)", @@ -110,8 +108,8 @@ 0, }; -int MH = 600; /* page height - can be scaled */ -int oMH = 600; /* page height - not scaled */ +static int MH = 600; /* page height - can be scaled */ +static int oMH = 600; /* page height - not scaled */ #define MW 500 /* page width */ #define LH 100 /* bottom margin */ #define RH 100 /* right margin */ @@ -146,7 +144,7 @@ fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n"); fprintf(pfd, "%d %d [\n", MW/2, LH+oMH+ 5*HH); fprintf(pfd, " (%s -- %s -- MSC -- %d)\n] 10 -0.5 0.5 0 ", - Version, oFname?oFname->name:"", pspno); + SpinVersion, oFname?oFname->name:"", pspno); fprintf(pfd, "false DrawText\ngrestore\n"); } @@ -181,11 +179,11 @@ { char snap[256]; FILE *fd; sprintf(snap, "%s.ps", oFname?oFname->name:"msc"); - if (!(pfd = fopen(snap, "w"))) + if (!(pfd = fopen(snap, MFLAGS))) fatal("cannot create file '%s'", snap); fprintf(pfd, "%%!PS-Adobe-2.0\n"); - fprintf(pfd, "%%%%Creator: %s\n", Version); + fprintf(pfd, "%%%%Creator: %s\n", SpinVersion); fprintf(pfd, "%%%%Title: MSC %s\n", oFname?oFname->name:"--"); fprintf(pfd, "%%%%BoundingBox: 119 154 494 638\n"); ntimes(pfd, 0, 1, PsPre); @@ -204,6 +202,7 @@ while (fgets(snap, 256, fd)) TotSteps++; fclose(fd); } + TotSteps += 10; R = (int *) emalloc(TotSteps * sizeof(int)); D = (int *) emalloc(TotSteps * sizeof(int)); M = (short *) emalloc(TotSteps * sizeof(short)); @@ -227,6 +226,7 @@ pspno, oFname?oFname->name:"msc"); exit(0); } + void psline(int x0, int iy0, int x1, int iy1, float r, float g, float b, int w) { int y0 = MH-iy0; @@ -260,11 +260,10 @@ { int i; for (i = p ; i >= 0; i--) - if (!ProcLine[i]) - { psline(i,0, i,MH-1, - (float) 0.4, (float) 0.4, (float) 1.0, 1); + { if (!ProcLine[i]) + { psline(i, 0, i, MH-1, (float) (0.4), (float) (0.4), (float) (1.0), 1); ProcLine[i] = 1; - } + } } } void @@ -320,7 +319,7 @@ } else { r = (float) 1.; g = (float) 1.; b = (float) 0.; if (!dx - && sscanf(s, "%d:%s", &a, d) == 2 /* was &d */ + && sscanf(s, "%d:%250s", &a, d) == 2 /* was &d */ && a >= 0 && a < TotSteps) { if (!I[a] || strlen(I[a]) <= strlen(s)) @@ -386,7 +385,7 @@ } if (L[i]) { spitbox(M[i], 0, i, L[i]); - free(L[i]); + /* free(L[i]); */ lasti = i; } } @@ -397,10 +396,9 @@ putbox(int x) { if (ldepth >= TotSteps) - { putpostlude(); - fprintf(stderr, "max length of %d steps exceeded\n", + { fprintf(stderr, "max length of %d steps exceeded - ps file truncated\n", TotSteps); - fatal("postscript file truncated", (char *) 0); + putpostlude(); } M[ldepth] = x; if (x > maxx) maxx = x; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/reprosrc.c --- a/sys/src/cmd/spin/reprosrc.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/reprosrc.c Tue Mar 06 23:34:10 2012 +0100 @@ -96,7 +96,7 @@ doindent(); if (e->n->ntyp == C_CODE) { printf("c_code "); - plunk_inline(stdout, e->n->sym->name, 1); + plunk_inline(stdout, e->n->sym->name, 1, 1); } else if (e->n->ntyp == 'c' && e->n->lft->ntyp == C_EXPR) { printf("c_expr { "); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/run.c --- a/sys/src/cmd/spin/run.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/run.c Tue Mar 06 23:34:10 2012 +0100 @@ -18,7 +18,7 @@ extern Element *LastStep; extern int Rvous, lineno, Tval, interactive, MadeChoice; extern int TstOnly, verbose, s_trail, xspin, jumpsteps, depth; -extern int nproc, nstop, no_print, like_java; +extern int analyze, nproc, nstop, no_print, like_java; static long Seed = 1; static int E_Check = 0, Escape_Check = 0; @@ -57,9 +57,9 @@ eval_sub(Element *e) { Element *f, *g; SeqList *z; - int i, j, k; + int i, j, k, only_pos; - if (!e->n) + if (!e || !e->n) return ZE; #ifdef DEBUG printf("\n\teval_sub(%d %s: line %d) ", @@ -69,8 +69,13 @@ #endif if (e->n->ntyp == GOTO) { if (Rvous) return ZE; - LastStep = e; f = get_lab(e->n, 1); + LastStep = e; + f = get_lab(e->n, 1); + f = huntele(f, e->status, -1); /* 5.2.3: was missing */ cross_dsteps(e->n, f->n); +#ifdef DEBUG + printf("GOTO leads to %d\n", f->seqno); +#endif return f; } if (e->n->ntyp == UNLESS) @@ -80,6 +85,7 @@ { Element *has_else = ZE; Element *bas_else = ZE; int nr_else = 0, nr_choices = 0; + only_pos = -1; if (interactive && !MadeChoice && !E_Check @@ -89,8 +95,10 @@ { printf("Select stmnt ("); whoruns(0); printf(")\n"); if (nproc-nstop > 1) - printf("\tchoice 0: other process\n"); - } + { printf("\tchoice 0: other process\n"); + nr_choices++; + only_pos = 0; + } } for (z = e->sub, j=0; z; z = z->nxt) { j++; if (interactive @@ -113,13 +121,21 @@ if (!Enabled0(z->this->frst)) printf("unexecutable, "); else - nr_choices++; + { nr_choices++; + only_pos = j; + } comment(stdout, z->this->frst->n, 0); printf("\n"); } } if (nr_choices == 0 && has_else) - printf("\tchoice %d: (else)\n", nr_else); + { printf("\tchoice %d: (else)\n", nr_else); + only_pos = nr_else; + } + + if (nr_choices <= 1 && only_pos != -1 && !MadeChoice) + { MadeChoice = only_pos; + } if (interactive && depth >= jumpsteps && !Escape_Check @@ -132,8 +148,11 @@ else printf("Select [0-%d]: ", j); fflush(stdout); - scanf("%s", buf); - if (isdigit(buf[0])) + if (scanf("%64s", buf) <= 0) + { printf("no input\n"); + return ZE; + } + if (isdigit((int)buf[0])) k = atoi(buf); else { if (buf[0] == 'q') @@ -155,6 +174,7 @@ else k = Rand()%j; /* nondeterminism */ } + has_else = ZE; bas_else = ZE; for (i = 0, z = e->sub; i < j+k; i++) @@ -234,6 +254,9 @@ if (!(e->status & D_ATOM)) /* escapes don't reach inside d_steps */ /* 4.2.4: only the guard of a d_step can have an escape */ #endif +#if 1 + if (!s_trail) /* trail determines selections, new 5.2.5 */ +#endif { Escape_Check++; if (like_java) { if ((g = rev_escape(e->esc)) != ZE) @@ -246,7 +269,11 @@ { for (x = e->esc; x; x = x->nxt) { if ((g = eval_sub(x->this->frst)) != ZE) { if (verbose&4) - printf("\tEscape taken\n"); + { printf("\tEscape taken "); + if (g->n && g->n->fn) + printf("%s:%d", g->n->fn->name, g->n->ln); + printf("\n"); + } Escape_Check--; return g; } } } @@ -386,13 +413,17 @@ case PRINTM: return TstOnly?1:printm(stdout, now); case ASGN: return assign(now); - case C_CODE: printf("%s:\t", now->sym->name); - plunk_inline(stdout, now->sym->name, 0); + case C_CODE: if (!analyze) + { printf("%s:\t", now->sym->name); + plunk_inline(stdout, now->sym->name, 0, 1); + } return 1; /* uninterpreted */ - case C_EXPR: printf("%s:\t", now->sym->name); - plunk_expr(stdout, now->sym->name); - printf("\n"); + case C_EXPR: if (!analyze) + { printf("%s:\t", now->sym->name); + plunk_expr(stdout, now->sym->name); + printf("\n"); + } return 1; /* uninterpreted */ case ASSERT: if (TstOnly || eval(now->lft)) return 1; @@ -426,7 +457,6 @@ j = n->lft->val; else j = eval(n->lft); - Buf[0] = '\0'; sr_buf(j, 1); dotag(fd, Buf); } @@ -437,9 +467,9 @@ interprint(FILE *fd, Lextok *n) { Lextok *tmp = n->lft; char c, *s = n->sym->name; - int i, j; char lbuf[512]; - extern char Buf[]; - char tBuf[4096]; + int i, j; char lbuf[512]; /* matches value in sr_buf() */ + extern char Buf[]; /* global, size 4096 */ + char tBuf[4096]; /* match size of global Buf[] */ Buf[0] = '\0'; if (!no_print) @@ -490,7 +520,7 @@ } dotag(fd, Buf); } - if (strlen(Buf) > 4096) fatal("printf string too long", 0); + if (strlen(Buf) >= 4096) fatal("printf string too long", 0); return 1; } @@ -600,3 +630,4 @@ } return result; } + diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/sched.c --- a/sys/src/cmd/spin/sched.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/sched.c Tue Mar 06 23:34:10 2012 +0100 @@ -20,7 +20,7 @@ extern int lineno, nr_errs, dumptab, xspin, jumpsteps, columns; extern int u_sync, Elcnt, interactive, TstOnly, cutoff; extern short has_enabled; -extern int limited_vis; +extern int limited_vis, old_scope_rules, product, nclaims; RunList *X = (RunList *) 0; RunList *run = (RunList *) 0; @@ -42,13 +42,16 @@ r->n = p->n; r->tn = p->tn; + r->b = p->b; r->pid = nproc++ - nstop + Skip_claim; - if ((verbose&4) || (verbose&32)) - printf("Starting %s with pid %d\n", p->n->name, r->pid); + if (!noparams && ((verbose&4) || (verbose&32))) + printf("Starting %s with pid %d\n", + p->n?p->n->name:"--", r->pid); if (!p->s) - fatal("parsing error, no sequence %s", p->n?p->n->name:"--"); + fatal("parsing error, no sequence %s", + p->n?p->n->name:"--"); r->pc = huntele(p->s->frst, p->s->frst->status, -1); r->ps = p->s; @@ -59,13 +62,15 @@ r->nxt = run; r->prov = p->prov; r->priority = weight; + if (noparams) setlocals(r); Priority_Sum += weight; + run = r; } ProcList * -ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov) +ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov, enum btypes b) /* n=name, p=formals, s=body det=deterministic prov=provided */ { ProcList *r = (ProcList *) emalloc(sizeof(ProcList)); Lextok *fp, *fpt; int j; extern int Npars; @@ -73,8 +78,12 @@ r->n = n; r->p = p; r->s = s; + r->b = b; r->prov = prov; r->tn = nrRdy++; + if (det != 0 && det != 1) + { fprintf(stderr, "spin: bad value for det (cannot happen)\n"); + } r->det = (short) det; r->nxt = rdy; rdy = r; @@ -135,6 +144,7 @@ if (dumptab || analyze + || product || s_trail || !(verbose&4)) return; @@ -208,26 +218,29 @@ RunList *r, *q = (RunList *) 0; for (p = rdy; p; p = p->nxt) - if (p->tn == n - && strcmp(p->n->name, ":never:") == 0) + if (p->tn == n && p->b == N_CLAIM) { runnable(p, 1, 1); goto found; } - printf("spin: couldn't find claim (ignored)\n"); + printf("spin: couldn't find claim %d (ignored)\n", n); + if (verbose&32) + for (p = rdy; p; p = p->nxt) + printf("\t%d = %s\n", p->tn, p->n->name); + Skip_claim = 1; goto done; found: /* move claim to far end of runlist, and reassign it pid 0 */ if (columns == 2) - { depth = 0; - pstext(0, "0::never:"); + { extern char Buf[]; + depth = 0; + sprintf(Buf, "%d:%s", 0, p->n->name); + pstext(0, Buf); for (r = run; r; r = r->nxt) - { if (!strcmp(r->n->name, ":never:")) - continue; - sprintf(Buf, "%d:%s", - r->pid+1, r->n->name); - pstext(r->pid+1, Buf); - } } + { if (r->b != N_CLAIM) + { sprintf(Buf, "%d:%s", r->pid+1, r->n->name); + pstext(r->pid+1, Buf); + } } } if (run->pid == 0) return; /* it is the first process started */ @@ -457,9 +470,12 @@ } else { char buf[256]; fflush(stdout); - scanf("%s", buf); + if (scanf("%64s", buf) == 0) + { printf("\tno input\n"); + goto try_again; + } j = -1; - if (isdigit(buf[0])) + if (isdigit((int) buf[0])) j = atoi(buf); else { if (buf[0] == 'q') @@ -484,6 +500,24 @@ } void +multi_claims(void) +{ ProcList *p, *q = NULL; + + if (nclaims > 1) + { printf(" the model contains %d never claims:", nclaims); + for (p = rdy; p; p = p->nxt) + { if (p->b == N_CLAIM) + { printf("%s%s", q?", ":" ", p->n->name); + q = p; + } } + printf("\n"); + printf(" only one claim is used in a verification run\n"); + printf(" choose which one with ./pan -N name (defaults to -N %s)\n", + q?q->n->name:"--"); + } +} + +void sched(void) { Element *e; RunList *Y = NULL; /* previous process in run queue */ @@ -504,10 +538,16 @@ printf("models with synchronous channels.\n"); nr_errs++; } + if (product) + { sync_product(); + alldone(0); + } if (analyze) { gensrc(); + multi_claims(); return; - } else if (s_trail) + } + if (s_trail) { match_trail(); return; } @@ -543,7 +583,7 @@ depth++; LastStep = ZE; oX = X; /* a rendezvous could change it */ go = 1; - if (X && X->prov && X->pc + if (X->prov && X->pc && !(X->pc->status & D_ATOM) && !eval(X->prov)) { if (!xspin && ((verbose&32) || (verbose&4))) @@ -570,7 +610,8 @@ if (xspin) printf("\n"); } - if (oX != X) + if (oX != X + || (X->pc->status & (ATOM|D_ATOM))) /* new 5.0 */ { e = silent_moves(e); notbeyond = 0; } @@ -587,10 +628,12 @@ } } else { depth--; - if (oX->pc->status & D_ATOM) - non_fatal("stmnt in d_step blocks", (char *)0); - - if (X->pc->n->ntyp == '@' + if (oX->pc && (oX->pc->status & D_ATOM)) + { non_fatal("stmnt in d_step blocks", (char *)0); + } + if (X->pc + && X->pc->n + && X->pc->n->ntyp == '@' && X->pid == (nproc-nstop-1)) { if (X != run && Y != NULL) Y->nxt = X->nxt; @@ -618,6 +661,9 @@ dotag(stdout, "timeout\n"); X = oX; } } } } + + if (!run || !X) break; /* new 5.0 */ + Y = pickproc(X); notbeyond = 0; } @@ -692,7 +738,9 @@ int i; for (t = r->symtab; t; t = t->next) - if (strcmp(t->name, s->name) == 0) + if (strcmp(t->name, s->name) == 0 + && (old_scope_rules + || strcmp((const char *)t->bscp, (const char *)s->bscp) == 0)) return; /* it's already there */ t = (Symbol *) emalloc(sizeof(Symbol)); @@ -704,13 +752,18 @@ t->ini = s->ini; t->setat = depth; t->context = r->n; + + t->bscp = (unsigned char *) emalloc(strlen((const char *)s->bscp)+1); + strcpy((char *)t->bscp, (const char *)s->bscp); + if (s->type != STRUCT) { if (s->val) /* if already initialized, copy info */ { t->val = (int *) emalloc(s->nel*sizeof(int)); for (i = 0; i < s->nel; i++) t->val[i] = s->val[i]; } else - (void) checkvar(t, 0); /* initialize it */ + { (void) checkvar(t, 0); /* initialize it */ + } } else { if (s->Sval) fatal("saw preinitialized struct %s", s->name); @@ -759,7 +812,7 @@ if (!a) fatal("missing actual parameters: '%s'", p->n->name); - if (t->sym->nel != 1) + if (t->sym->nel > 1 || t->sym->isarray) fatal("array in parameter list, %s", t->sym->name); k = eval(a->lft); @@ -768,7 +821,7 @@ ft = Sym_typ(t); if (at != ft && (at == CHAN || ft == CHAN)) - { char buf[128], tag1[64], tag2[64]; + { char buf[256], tag1[64], tag2[64]; (void) sputtype(tag1, ft); (void) sputtype(tag2, at); sprintf(buf, "type-clash in params of %s(..), (%s<-> %s)", @@ -809,7 +862,8 @@ return ZS; } for (r = X->symtab; r; r = r->next) - if (strcmp(r->name, s->name) == 0) + if (strcmp(r->name, s->name) == 0 + && (old_scope_rules || strcmp((const char *)r->bscp, (const char *)s->bscp) == 0)) break; if (!r) { addsymbol(X, s); @@ -895,6 +949,7 @@ void p_talk(Element *e, int lnr) { static int lastnever = -1; + static char nbuf[128]; int newnever = -1; if (e && e->n) @@ -918,9 +973,22 @@ whoruns(lnr); if (e) - { printf("line %3d %s (state %d)", + { if (e->n) + { char *ptr = e->n->fn->name; + char *qtr = nbuf; + while (*ptr != '\0') + { if (*ptr != '"') + { *qtr++ = *ptr; + } + ptr++; + } + *qtr = '\0'; + } else + { strcpy(nbuf, "-"); + } + printf("%s:%d (state %d)", + nbuf, e->n?e->n->ln:-1, - e->n?e->n->fn->name:"-", e->seqno); if (!xspin && ((e->status&ENDSTATE) || has_lab(e, 2))) /* 2=end */ @@ -978,7 +1046,7 @@ printf(" %s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid); } #endif - i = nproc - nstop; + i = nproc - nstop + Skip_claim; /* 6.0: added Skip_claim */ for (Y = run; Y; Y = Y->nxt) if (--i == prno) { if (strcmp(Y->n->name, n->lft->sym->name) != 0) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/spin.h --- a/sys/src/cmd/spin/spin.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/spin.h Tue Mar 06 23:34:10 2012 +0100 @@ -1,6 +1,6 @@ /***** spin: spin.h *****/ -/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* Copyright (c) 1989-2009 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 */ @@ -16,12 +16,16 @@ #include #include +enum { INIV, PUTV, LOGV }; /* for pangen[14].c */ +enum btypes { NONE, N_CLAIM, I_PROC, A_PROC, P_PROC, E_TRACE, N_TRACE }; + typedef struct Lextok { unsigned short ntyp; /* node type */ short ismtyp; /* CONST derived from MTYP */ int val; /* value attribute */ int ln; /* line number */ int indstep; /* part of d_step sequence */ + int uiid; /* inline id, if non-zero */ struct Symbol *fn; /* file name */ struct Symbol *sym; /* symbol reference */ struct Sequence *sq; /* sequence */ @@ -54,6 +58,8 @@ 64=treat as if local; 128=read at least once */ unsigned char colnr; /* for use with xspin during simulation */ + unsigned char isarray; /* set if decl specifies array bound */ + unsigned char *bscp; /* block scope */ int nbits; /* optional width specifier */ int nel; /* 1 if scalar, >1 if array */ int setat; /* last depth value changed */ @@ -124,7 +130,7 @@ int merge_single; short merge_in; /* nr of incoming edges */ short merge_mark; /* state was generated in merge sequence */ - unsigned char status; /* used by analyzer generator */ + unsigned int status; /* used by analyzer generator */ struct FSM_use *dead; /* optional dead variable list */ struct SeqList *sub; /* subsequences, for compounds */ struct SeqList *esc; /* zero or more escape sequences */ @@ -148,6 +154,7 @@ Symbol *s; Symbol *c; Element *e; + int uiid; /* non-zero if label appears in an inline */ int visible; /* label referenced in claim (slice relevant) */ struct Label *nxt; } Label; @@ -162,6 +169,7 @@ int tn; /* ordinal of type */ int pid; /* process id */ int priority; /* for simulations only */ + enum btypes b; /* the type of process */ Element *pc; /* current stmnt */ Sequence *ps; /* used by analyzer generator */ Lextok *prov; /* provided clause */ @@ -174,8 +182,10 @@ Lextok *p; /* parameters */ Sequence *s; /* body */ Lextok *prov; /* provided clause */ + enum btypes b; /* e.g., claim, trace, proc */ short tn; /* ordinal number */ - short det; /* deterministic */ + unsigned char det; /* deterministic */ + unsigned char unsafe; /* contains global var inits */ struct ProcList *nxt; /* linked list */ } ProcList; @@ -194,7 +204,8 @@ #define DONE2 16 /* used in putcode and main*/ #define D_ATOM 32 /* deterministic atomic */ #define ENDSTATE 64 /* normal endstate */ -#define CHECK2 128 +#define CHECK2 128 /* status bits for remote ref check */ +#define CHECK3 256 /* status bits for atomic jump check */ #define Nhash 255 /* slots in symbol hash-table */ @@ -216,12 +227,17 @@ #define SOMETHINGBIG 65536 #define RATHERSMALL 512 +#define MAXSCOPESZ 1024 #ifndef max #define max(a,b) (((a)<(b)) ? (b) : (a)) #endif -enum { INIV, PUTV, LOGV }; /* for pangen[14].c */ +#ifdef PC + #define MFLAGS "wb" +#else + #define MFLAGS "w" +#endif /***** prototype definitions *****/ Element *eval_sub(Element *); @@ -239,7 +255,7 @@ Lextok *rem_var(Symbol *, Lextok *, Symbol *, Lextok *); Lextok *tail_add(Lextok *, Lextok *); -ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *); +ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *, enum btypes); SeqList *seqlist(Sequence *, SeqList *); Sequence *close_seq(int); @@ -250,7 +266,7 @@ Symbol *lookup(char *); Symbol *prep_inline(Symbol *, Lextok *); -char *emalloc(int); +char *emalloc(size_t); long Rand(void); int any_oper(Lextok *, int); @@ -274,12 +290,14 @@ int in_bound(Symbol *, int); int interprint(FILE *, Lextok *); int printm(FILE *, Lextok *); +int is_inline(void); int ismtype(char *); int isproctype(char *); int isutype(char *); int Lval_struct(Lextok *, Symbol *, int, int); int main(int, char **); int pc_value(Lextok *); +int pid_is_claim(int); int proper_enabler(Lextok *); int putcode(FILE *, Sequence *, Element *, int, int, int); int q_is_sync(Lextok *); @@ -321,6 +339,7 @@ void checkrun(Symbol *, int); void comment(FILE *, Lextok *, int); void cross_dsteps(Lextok *, Lextok *); +void disambiguate(void); void doq(Symbol *, int, RunList *); void dotag(FILE *, char *); void do_locinits(FILE *); @@ -355,7 +374,7 @@ void plunk_c_decls(FILE *); void plunk_c_fcts(FILE *); void plunk_expr(FILE *, char *); -void plunk_inline(FILE *, char *, int); +void plunk_inline(FILE *, char *, int, int); void prehint(Symbol *); void preruse(FILE *, Lextok *); void prune_opts(Lextok *); @@ -378,15 +397,17 @@ void setuname(Lextok *); void setutype(Lextok *, Symbol *, Lextok *); void setxus(Lextok *, int); +void show_lab(void); void Srand(unsigned); void start_claim(int); void struct_name(Lextok *, Symbol *, int, char *); void symdump(void); void symvar(Symbol *); +void sync_product(void); void trackchanuse(Lextok *, Lextok *, int); void trackvar(Lextok *, Lextok *); void trackrun(Lextok *); -void trapwonly(Lextok *, char *); /* spin.y and main.c */ +void trapwonly(Lextok * /* , char * */); /* spin.y and main.c */ void typ2c(Symbol *); void typ_ck(int, int, char *); void undostmnt(Lextok *, int); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/spin.y --- a/sys/src/cmd/spin/spin.y Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/spin.y Tue Mar 06 23:34:10 2012 +0100 @@ -11,26 +11,44 @@ %{ #include "spin.h" +#include +#ifndef PC +#include +#endif #include #define YYDEBUG 0 #define Stop nn(ZN,'@',ZN,ZN) +#define PART0 "place initialized var decl of " +#define PART1 "place initialized chan decl of " +#define PART2 " at start of proctype " + +static Lextok *ltl_to_string(Lextok *); extern Symbol *context, *owner; -extern int u_sync, u_async, dumptab; +extern Lextok *for_body(Lextok *, int); +extern void for_setup(Lextok *, Lextok *, Lextok *); +extern Lextok *for_index(Lextok *, Lextok *); +extern Lextok *sel_index(Lextok *, Lextok *, Lextok *); +extern int u_sync, u_async, dumptab, scope_level; +extern int initialization_ok, split_decl; extern short has_sorted, has_random, has_enabled, has_pcvalue, has_np; extern short has_code, has_state, has_io; extern void count_runs(Lextok *); extern void no_internals(Lextok *); extern void any_runs(Lextok *); +extern void ltl_list(char *, char *); extern void validref(Lextok *, Lextok *); extern char yytext[]; int Mpars = 0; /* max nr of message parameters */ -int runsafe = 1; /* 1 if all run stmnts are in init */ +int nclaims = 0; /* nr of never claims */ +int ltl_mode = 0; /* set when parsing an ltl formula */ int Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0; +int in_for = 0; char *claimproc = (char *) 0; char *eventmap = (char *) 0; +static char *ltl_name; static int Embedded = 0, inEventMap = 0, has_ini = 0; @@ -41,7 +59,7 @@ %token RUN LEN ENABLED EVAL PC_VAL %token TYPEDEF MTYPE INLINE LABEL OF %token GOTO BREAK ELSE SEMI -%token IF FI DO OD SEP +%token IF FI DO OD FOR SELECT IN SEP DOTDOT %token ATOMIC NON_ATOMIC D_STEP UNLESS %token TIMEOUT NONPROGRESS %token ACTIVE PROCTYPE D_PROCTYPE @@ -50,12 +68,16 @@ %token FULL EMPTY NFULL NEMPTY %token CONST TYPE XU /* val */ %token NAME UNAME PNAME INAME /* sym */ -%token STRING CLAIM TRACE INIT /* sym */ +%token STRING CLAIM TRACE INIT LTL /* sym */ %right ASGN %left SND O_SND RCV R_RCV /* SND doubles as boolean negation */ +%left IMPLIES EQUIV /* ltl */ %left OR %left AND +%left ALWAYS EVENTUALLY /* ltl */ +%left UNTIL WEAK_UNTIL RELEASE /* ltl */ +%right NEXT /* ltl */ %left '|' %left '^' %left '&' @@ -81,6 +103,7 @@ unit : proc /* proctype { } */ | init /* init { } */ | claim /* never claim */ + | ltl /* ltl formula */ | events /* event assertions */ | one_decl /* variables, chans */ | utype /* user defined types */ @@ -91,7 +114,7 @@ ; proc : inst /* optional instantiator */ - proctype NAME { + proctype NAME { setptype($3, PROCTYPE, ZN); setpname($3); context = $3->sym; @@ -106,13 +129,22 @@ Opt_priority Opt_enabler body { ProcList *rl; - rl = ready($3->sym, $6, $11->sq, $2->val, $10); if ($1 != ZN && $1->val > 0) { int j; + rl = ready($3->sym, $6, $11->sq, $2->val, $10, A_PROC); for (j = 0; j < $1->val; j++) - runnable(rl, $9?$9->val:1, 1); + { runnable(rl, $9?$9->val:1, 1); + } announce(":root:"); if (dumptab) $3->sym->ini = $1; + } else + { rl = ready($3->sym, $6, $11->sq, $2->val, $10, P_PROC); + } + if (rl && has_ini == 1) /* global initializations, unsafe */ + { /* printf("proctype %s has initialized data\n", + $3->sym->name); + */ + rl->unsafe = 1; } context = ZS; } @@ -133,10 +165,10 @@ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 0; if (!$3->sym->type) - non_fatal("undeclared variable %s", + fatal("undeclared variable %s", $3->sym->name); else if ($3->sym->ini->ntyp != CONST) - non_fatal("need constant initializer for %s\n", + fatal("need constant initializer for %s\n", $3->sym->name); else $$->val = $3->sym->ini->val; @@ -146,30 +178,68 @@ init : INIT { context = $1->sym; } Opt_priority body { ProcList *rl; - rl = ready(context, ZN, $4->sq, 0, ZN); + rl = ready(context, ZN, $4->sq, 0, ZN, I_PROC); runnable(rl, $3?$3->val:1, 1); announce(":root:"); context = ZS; } ; -claim : CLAIM { context = $1->sym; - if (claimproc) - non_fatal("claim %s redefined", claimproc); +ltl : LTL optname2 { ltl_mode = 1; ltl_name = $2->sym->name; } + ltl_body { if ($4) ltl_list($2->sym->name, $4->sym->name); + ltl_mode = 0; + } + ; + +ltl_body: '{' full_expr OS '}' { $$ = ltl_to_string($2); } + | error { $$ = NULL; } + ; + +claim : CLAIM optname { if ($2 != ZN) + { $1->sym = $2->sym; /* new 5.3.0 */ + } + nclaims++; + context = $1->sym; + if (claimproc && !strcmp(claimproc, $1->sym->name)) + { fatal("claim %s redefined", claimproc); + } claimproc = $1->sym->name; } - body { (void) ready($1->sym, ZN, $3->sq, 0, ZN); + body { (void) ready($1->sym, ZN, $4->sq, 0, ZN, N_CLAIM); context = ZS; } ; +optname : /* empty */ { char tb[32]; + memset(tb, 0, 32); + sprintf(tb, "never_%d", nclaims); + $$ = nn(ZN, NAME, ZN, ZN); + $$->sym = lookup(tb); + } + | NAME { $$ = $1; } + ; + +optname2 : /* empty */ { char tb[32]; static int nltl = 0; + memset(tb, 0, 32); + sprintf(tb, "ltl_%d", nltl++); + $$ = nn(ZN, NAME, ZN, ZN); + $$->sym = lookup(tb); + } + | NAME { $$ = $1; } + ; + events : TRACE { context = $1->sym; if (eventmap) non_fatal("trace %s redefined", eventmap); eventmap = $1->sym->name; inEventMap++; } - body { (void) ready($1->sym, ZN, $3->sq, 0, ZN); + body { + if (strcmp($1->sym->name, ":trace:") == 0) + { (void) ready($1->sym, ZN, $3->sq, 0, ZN, E_TRACE); + } else + { (void) ready($1->sym, ZN, $3->sq, 0, ZN, N_TRACE); + } context = ZS; inEventMap--; } @@ -252,7 +322,12 @@ body : '{' { open_seq(1); } sequence OS { add_seq(Stop); } - '}' { $$->sq = close_seq(0); } + '}' { $$->sq = close_seq(0); + if (scope_level != 0) + { non_fatal("missing '}' ?", 0); + scope_level = 0; + } + } ; sequence: step { if ($1) add_seq($1); } @@ -277,7 +352,9 @@ | ASGN ; -one_decl: vis TYPE var_list { setptype($3, $2->val, $1); $$ = $3; } +one_decl: vis TYPE var_list { setptype($3, $2->val, $1); + $$ = $3; + } | vis UNAME var_list { setutype($3, $2->sym, $1); $$ = expand($3, Expand_Ok); } @@ -314,17 +391,34 @@ $1->sym->ini = nn(ZN,CONST,ZN,ZN); $1->sym->ini->val = 0; } - | vardcl ASGN expr { $1->sym->ini = $3; $$ = $1; - trackvar($1,$3); has_ini = 1; + | vardcl ASGN expr { $$ = $1; + $1->sym->ini = $3; + trackvar($1,$3); + if ($3->ntyp == CONST + || ($3->ntyp == NAME && $3->sym->context)) + { has_ini = 2; /* local init */ + } else + { has_ini = 1; /* possibly global */ + } + if (!initialization_ok && split_decl) + { nochan_manip($1, $3, 0); + no_internals($1); + non_fatal(PART0 "'%s'" PART2, $1->sym->name); + } } | vardcl ASGN ch_init { $1->sym->ini = $3; $$ = $1; has_ini = 1; + if (!initialization_ok && split_decl) + { non_fatal(PART1 "'%s'" PART2, $1->sym->name); + } } ; ch_init : '[' CONST ']' OF - '{' typ_list '}' { if ($2->val) u_async++; - else u_sync++; + '{' typ_list '}' { if ($2->val) + u_async++; + else + u_sync++; { int i = cnt_mpars($6); Mpars = max(Mpars, i); } @@ -342,13 +436,18 @@ } $1->sym->nel = 1; $$ = $1; } - | NAME '[' CONST ']' { $1->sym->nel = $3->val; $$ = $1; } + | NAME '[' CONST ']' { $1->sym->nel = $3->val; $1->sym->isarray = 1; $$ = $1; } ; varref : cmpnd { $$ = mk_explicit($1, Expand_Ok, NAME); } ; -pfld : NAME { $$ = nn($1, NAME, ZN, ZN); } +pfld : NAME { $$ = nn($1, NAME, ZN, ZN); + if ($1->sym->isarray && !in_for) + { non_fatal("missing array index for '%s'", + $1->sym->name); + } + } | NAME { owner = ZS; } '[' expr ']' { $$ = nn($1, NAME, $4, ZN); } ; @@ -363,7 +462,7 @@ Embedded--; if (!Embedded && !NamesNotAdded && !$1->sym->type) - non_fatal("undeclared variable: %s", + fatal("undeclared variable: %s", $1->sym->name); if ($3) validref($1, $3->lft); owner = ZS; @@ -374,13 +473,19 @@ | '.' cmpnd %prec DOT { $$ = nn(ZN, '.', $2, ZN); } ; -stmnt : Special { $$ = $1; } - | Stmnt { $$ = $1; +stmnt : Special { $$ = $1; initialization_ok = 0; } + | Stmnt { $$ = $1; initialization_ok = 0; if (inEventMap) non_fatal("not an event", (char *)0); } ; +for_pre : FOR '(' { in_for = 1; } + varref { $$ = $4; } + ; + +for_post: '{' sequence OS '}' ; + Special : varref RCV { Expand_Ok++; } rargs { Expand_Ok--; has_io++; $$ = nn($1, 'r', $1, $4); @@ -392,6 +497,18 @@ $$->val=0; trackchanuse($4, ZN, 'S'); any_runs($4); } + | for_pre ':' expr DOTDOT expr ')' { + for_setup($1, $3, $5); in_for = 0; + } + for_post { $$ = for_body($1, 1); + } + | for_pre IN varref ')' { $$ = for_index($1, $3); in_for = 0; + } + for_post { $$ = for_body($5, 1); + } + | SELECT '(' varref ':' expr DOTDOT expr ')' { + $$ = sel_index($3, $5, $7); + } | IF options FI { $$ = nn($1, IF, ZN, ZN); $$->sl = $2->sl; prune_opts($$); @@ -422,7 +539,7 @@ } ; -Stmnt : varref ASGN expr { $$ = nn($1, ASGN, $1, $3); +Stmnt : varref ASGN full_expr { $$ = nn($1, ASGN, $1, $3); trackvar($1, $3); nochan_manip($1, $3, 0); no_internals($1); @@ -482,7 +599,9 @@ $$->sl = seqlist(close_seq(3), 0); make_atomic($$->sl->this, 0); } - | D_STEP '{' { open_seq(0); rem_Seq(); } + | D_STEP '{' { open_seq(0); + rem_Seq(); + } sequence OS '}' { $$ = nn($1, D_STEP, ZN, ZN); $$->sl = seqlist(close_seq(4), 0); make_atomic($$->sl->this, D_ATOM); @@ -548,10 +667,8 @@ | RUN aname { Expand_Ok++; if (!context) - fatal("used 'run' outside proctype", + fatal("used 'run' outside proctype", (char *) 0); - if (strcmp(context->name, ":init:") != 0) - runsafe = 0; } '(' args ')' Opt_priority { Expand_Ok--; @@ -572,7 +689,7 @@ $$ = nn($1, 'R', $1, $5); $$->val = has_random = 1; } - | varref { $$ = $1; trapwonly($1, "varref"); } + | varref { $$ = $1; trapwonly($1 /*, "varref" */); } | cexpr { $$ = $1; } | CONST { $$ = nn(ZN,CONST,ZN,ZN); $$->ismtyp = $1->ismtyp; @@ -591,6 +708,7 @@ { $$ = rem_var($1->sym, $3, $6->sym, $6->lft); } | PNAME '@' NAME { $$ = rem_lab($1->sym, ZN, $3->sym); } | PNAME ':' pfld { $$ = rem_var($1->sym, ZN, $3->sym, $3->lft); } + | ltl_expr { $$ = $1; } ; Opt_priority: /* none */ { $$ = ZN; } @@ -598,7 +716,39 @@ ; full_expr: expr { $$ = $1; } - | Expr { $$ = $1; } + | Expr { $$ = $1; } + ; + +ltl_expr: expr UNTIL expr { $$ = nn(ZN, UNTIL, $1, $3); } + | expr RELEASE expr { $$ = nn(ZN, RELEASE, $1, $3); } + | expr WEAK_UNTIL expr { $$ = nn(ZN, ALWAYS, $1, ZN); + $$ = nn(ZN, OR, $$, nn(ZN, UNTIL, $1, $3)); + } + | expr IMPLIES expr { + $$ = nn(ZN, '!', $1, ZN); + $$ = nn(ZN, OR, $$, $3); + } + | expr EQUIV expr { $$ = nn(ZN, EQUIV, $1, $3); } + | NEXT expr %prec NEG { $$ = nn(ZN, NEXT, $2, ZN); } + | ALWAYS expr %prec NEG { $$ = nn(ZN, ALWAYS,$2, ZN); } + | EVENTUALLY expr %prec NEG { $$ = nn(ZN, EVENTUALLY, $2, ZN); } + ; + + /* an Expr cannot be negated - to protect Probe expressions */ +Expr : Probe { $$ = $1; } + | '(' Expr ')' { $$ = $2; } + | Expr AND Expr { $$ = nn(ZN, AND, $1, $3); } + | Expr AND expr { $$ = nn(ZN, AND, $1, $3); } + | expr AND Expr { $$ = nn(ZN, AND, $1, $3); } + | Expr OR Expr { $$ = nn(ZN, OR, $1, $3); } + | Expr OR expr { $$ = nn(ZN, OR, $1, $3); } + | expr OR Expr { $$ = nn(ZN, OR, $1, $3); } + ; + +Probe : FULL '(' varref ')' { $$ = nn($3, FULL, $3, ZN); } + | NFULL '(' varref ')' { $$ = nn($3, NFULL, $3, ZN); } + | EMPTY '(' varref ')' { $$ = nn($3, EMPTY, $3, ZN); } + | NEMPTY '(' varref ')' { $$ = nn($3,NEMPTY, $3, ZN); } ; Opt_enabler: /* none */ { $$ = ZN; } @@ -615,23 +765,6 @@ } ; - /* an Expr cannot be negated - to protect Probe expressions */ -Expr : Probe { $$ = $1; } - | '(' Expr ')' { $$ = $2; } - | Expr AND Expr { $$ = nn(ZN, AND, $1, $3); } - | Expr AND expr { $$ = nn(ZN, AND, $1, $3); } - | Expr OR Expr { $$ = nn(ZN, OR, $1, $3); } - | Expr OR expr { $$ = nn(ZN, OR, $1, $3); } - | expr AND Expr { $$ = nn(ZN, AND, $1, $3); } - | expr OR Expr { $$ = nn(ZN, OR, $1, $3); } - ; - -Probe : FULL '(' varref ')' { $$ = nn($3, FULL, $3, ZN); } - | NFULL '(' varref ')' { $$ = nn($3, NFULL, $3, ZN); } - | EMPTY '(' varref ')' { $$ = nn($3, EMPTY, $3, ZN); } - | NEMPTY '(' varref ')' { $$ = nn($3,NEMPTY, $3, ZN); } - ; - basetype: TYPE { $$->sym = ZS; $$->val = $1->val; if ($$->val == UNSIGNED) @@ -676,9 +809,9 @@ ; rarg : varref { $$ = $1; trackvar($1, $1); - trapwonly($1, "rarg"); } + trapwonly($1 /*, "rarg" */); } | EVAL '(' expr ')' { $$ = nn(ZN,EVAL,$3,ZN); - trapwonly($1, "eval rarg"); } + trapwonly($1 /*, "eval rarg" */); } | CONST { $$ = nn(ZN,CONST,ZN,ZN); $$->ismtyp = $1->ismtyp; $$->val = $1->val; @@ -715,6 +848,98 @@ ; %% +#define binop(n, sop) fprintf(fd, "("); recursive(fd, n->lft); \ + fprintf(fd, ") %s (", sop); recursive(fd, n->rgt); \ + fprintf(fd, ")"); +#define unop(n, sop) fprintf(fd, "%s (", sop); recursive(fd, n->lft); \ + fprintf(fd, ")"); + +static void +recursive(FILE *fd, Lextok *n) +{ + if (n) + switch (n->ntyp) { + case NEXT: + unop(n, "X"); + break; + case ALWAYS: + unop(n, "[]"); + break; + case EVENTUALLY: + unop(n, "<>"); + break; + case '!': + unop(n, "!"); + break; + case UNTIL: + binop(n, "U"); + break; + case WEAK_UNTIL: + binop(n, "W"); + break; + case RELEASE: /* see http://en.wikipedia.org/wiki/Linear_temporal_logic */ + binop(n, "V"); + break; + case OR: + binop(n, "||"); + break; + case AND: + binop(n, "&&"); + break; + case IMPLIES: + binop(n, "->"); + break; + case EQUIV: + binop(n, "<->"); + break; + default: + comment(fd, n, 0); + break; + } +} + +#define TMP_FILE "_S_p_I_n_.tmp" + +extern int unlink(const char *); + +static Lextok * +ltl_to_string(Lextok *n) +{ Lextok *m = nn(ZN, 0, ZN, ZN); + char *retval; + char formula[1024]; + FILE *tf = fopen(TMP_FILE, "w+"); /* tmpfile() fails on Windows 7 */ + + /* convert the parsed ltl to a string + by writing into a file, using existing functions, + and then passing it to the existing interface for + conversion into a never claim + (this means parsing everything twice, which is + a little redundant, but adds only miniscule overhead) + */ + + if (!tf) + { fatal("cannot create temporary file", (char *) 0); + } + recursive(tf, n); + (void) fseek(tf, 0L, SEEK_SET); + + memset(formula, 0, sizeof(formula)); + retval = fgets(formula, sizeof(formula), tf); + fclose(tf); + (void) unlink(TMP_FILE); + + if (!retval) + { printf("%p\n", retval); + fatal("could not translate ltl formula", 0); + } + + if (1) printf("ltl %s: %s\n", ltl_name, formula); + + m->sym = lookup(formula); + + return m; +} + void yyerror(char *fmt, ...) { diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/spinlex.c --- a/sys/src/cmd/spin/spinlex.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/spinlex.c Tue Mar 06 23:34:10 2012 +0100 @@ -23,6 +23,7 @@ Lextok *params; /* formal pars if any */ char **anms; /* literal text for actual pars */ char *prec; /* precondition for c_code or c_expr */ + int uiid; /* unique inline id */ int dln, cln; /* def and call linenr */ Symbol *dfn, *cfn; /* def and call filename */ struct IType *nxt; /* linked list */ @@ -37,14 +38,16 @@ extern RunList *X; extern ProcList *rdy; -extern Symbol *Fname; +extern Symbol *Fname, *oFname; extern Symbol *context, *owner; extern YYSTYPE yylval; extern short has_last, has_code; -extern int verbose, IArgs, hastrack, separate; +extern int verbose, IArgs, hastrack, separate, ltl_mode; short has_stack = 0; int lineno = 1; +int scope_seq[128], scope_level = 0; +char CurScope[MAXSCOPESZ]; char yytext[2048]; FILE *yyin, *yyout; @@ -81,20 +84,23 @@ #if 1 #define Getchar() ((Inlining<0)?getc(yyin):getinline()) -#define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline(); } +#define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline();} #else static int Getchar(void) { int c; + if (Inlining<0) c = getc(yyin); else c = getinline(); -#if 1 - printf("<%c>", c); -#endif + if (0) + { printf("<%c:%d>[%d] ", c, c, Inlining); + } else + { printf("%c", c); + } return c; } @@ -105,13 +111,18 @@ ungetc(c,yyin); else uninline(); -#if 1 - printf(""); -#endif + if (0) + { printf(""); + } } #endif static int +notdollar(int c) +{ return (c != '$' && c != '\n'); +} + +static int notquote(int c) { return (c != '\"' && c != '\n'); } @@ -133,14 +144,15 @@ static void getword(int first, int (*tst)(int)) -{ int i=0; char c; +{ int i=0, c; yytext[i++]= (char) first; while (tst(c = Getchar())) - { yytext[i++] = c; + { yytext[i++] = (char) c; if (c == '\\') - yytext[i++] = Getchar(); /* no tst */ - } + { c = Getchar(); + yytext[i++] = (char) c; /* no tst */ + } } yytext[i] = '\0'; Ungetch(c); } @@ -161,10 +173,11 @@ static void def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms) { IType *tmp; - char *nw = (char *) emalloc((int) strlen(ptr)+1); + int cnt = 0; + char *nw = (char *) emalloc(strlen(ptr)+1); strcpy(nw, ptr); - for (tmp = seqnames; tmp; tmp = tmp->nxt) + for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt) if (!strcmp(s->name, tmp->nm->name)) { non_fatal("procedure name %s redefined", tmp->nm->name); @@ -179,11 +192,12 @@ tmp->cn = (Lextok *) nw; tmp->params = nms; if (strlen(prc) > 0) - { tmp->prec = (char *) emalloc((int) strlen(prc)+1); + { tmp->prec = (char *) emalloc(strlen(prc)+1); strcpy(tmp->prec, prc); } tmp->dln = ln; tmp->dfn = Fname; + tmp->uiid = cnt+1; /* so that 0 means: not an inline */ tmp->nxt = seqnames; seqnames = tmp; } @@ -269,8 +283,8 @@ Inlining--; #if 0 if (verbose&32) - printf("spin: line %d, done inlining %s\n", - lineno, Inline_stub[Inlining+1]->nm->name); + printf("spin: %s:%d, done inlining %s\n", + Fname, lineno, Inline_stub[Inlining+1]->nm->name); #endif return Getchar(); } @@ -286,6 +300,16 @@ Inliner[Inlining]--; } +int +is_inline(void) +{ + if (Inlining < 0) + return 0; /* i.e., not an inline */ + if (Inline_stub[Inlining] == NULL) + fatal("unexpected, inline_stub not set", 0); + return Inline_stub[Inlining]->uiid; +} + IType * find_inline(char *s) { IType *tmp; @@ -295,6 +319,7 @@ break; if (!tmp) fatal("cannot happen, missing inline def %s", s); + return tmp; } @@ -329,7 +354,7 @@ && strcmp(stackonly->name, "\"StackOnly\"") != 0) non_fatal("expecting '[Un]Matched', saw %s", stackonly->name); else - has_stack = 1; + has_stack = 1; /* unmatched stack */ } } @@ -514,32 +539,38 @@ } void +c_stack_size(FILE *fd) +{ C_Added *r; + int cnt = 0; + + for (r = c_tracked; r; r = r->nxt) + if (r->ival != ZS) + { fprintf(fd, "%s%s", + (cnt==0)?"":"+", r->t->name); + cnt++; + } + if (cnt == 0) + { fprintf(fd, "WS"); + } +} + +void c_add_stack(FILE *fd) { C_Added *r; int cnt = 0; - if ((!c_added && !c_tracked) || !has_stack) return; - + if ((!c_added && !c_tracked) || !has_stack) + { return; + } for (r = c_tracked; r; r = r->nxt) if (r->ival != ZS) - cnt++; + { cnt++; + } - if (cnt == 0) return; - - fprintf(fd, " uchar c_stack["); - - cnt = 0; - for (r = c_tracked; r; r = r->nxt) - { if (r->ival == ZS) continue; - - fprintf(fd, "%s%s", - (cnt==0)?"":"+", r->t->name); - cnt++; + if (cnt > 0) + { fprintf(fd, " uchar c_stack[StackSize];\n"); } - - if (cnt == 0) fprintf(fd, "WS"); /* can't happen */ - fprintf(fd, "];\n"); } void @@ -610,9 +641,10 @@ } if (has_stack) - { fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n"); + { fprintf(fd, "int cpu_printf(const char *, ...);\n"); + fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n"); fprintf(fd, "#ifdef VERBOSE\n"); - fprintf(fd, " printf(\"c_stack %%u\\n\", p_t_r);\n"); + fprintf(fd, " cpu_printf(\"c_stack %%u\\n\", p_t_r);\n"); fprintf(fd, "#endif\n"); for (r = c_tracked; r; r = r->nxt) { if (r->ival == ZS) continue; @@ -660,7 +692,7 @@ if (has_stack) { fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n"); fprintf(fd, "#ifdef VERBOSE\n"); - fprintf(fd, " printf(\"c_unstack %%u\\n\", p_t_r);\n"); + fprintf(fd, " cpu_printf(\"c_unstack %%u\\n\", p_t_r);\n"); fprintf(fd, "#endif\n"); for (r = c_tracked; r; r = r->nxt) { if (r->ival == ZS) continue; @@ -792,7 +824,7 @@ if (tmp->prec) { fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec); fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;"); - fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec); + fprintf(fd, "trpt->st = tt; uerror(\"%s\"); continue; } ", tmp->prec); fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec); fprintf(fd, "_m = 3; goto P999; } } \n\t\t"); } @@ -814,7 +846,7 @@ } void -plunk_inline(FILE *fd, char *s, int how) /* c_code with precondition */ +plunk_inline(FILE *fd, char *s, int how, int gencode) /* c_code with precondition */ { IType *tmp; tmp = find_inline(s); @@ -822,12 +854,19 @@ fprintf(fd, "{ "); if (how && tmp->prec) - { fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec); - fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t;"); - fprintf(fd, "trpt->st = tt; Uerror(\"%s\"); } ", tmp->prec); - fprintf(fd, "else { printf(\"pan: precondition false: %s\\n\"); ", tmp->prec); - fprintf(fd, "_m = 3; goto P999; } } "); + { fprintf(fd, "if (!(%s)) { if (!readtrail) {", + tmp->prec); + fprintf(fd, " uerror(\"%s\"); continue; ", + tmp->prec); + fprintf(fd, "} else { "); + fprintf(fd, "printf(\"pan: precondition false: %s\\n\"); _m = 3; goto P999; } } ", + tmp->prec); } + + if (!gencode) /* not in d_step */ + { fprintf(fd, "\n\t\tsv_save();"); + } + fprintf(fd, "%s", (char *) tmp->cn); fprintf(fd, " }\n"); } @@ -875,8 +914,7 @@ tmp = find_inline(t->name); if (++Inlining >= MAXINL) - fatal("inline fcts too deeply nested", 0); - + fatal("inlines nested too deeply", 0); tmp->cln = lineno; /* remember calling point */ tmp->cfn = Fname; /* and filename */ @@ -887,7 +925,7 @@ tmp->anms = (char **) emalloc(j * sizeof(char *)); for (p = apars, j = 0; p; p = p->rgt, j++) - { tmp->anms[j] = (char *) emalloc((int) strlen(IArg_cont[j])+1); + { tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1); strcpy(tmp->anms[j], IArg_cont[j]); } @@ -897,8 +935,8 @@ Inline_stub[Inlining] = tmp; #if 0 if (verbose&32) - printf("spin: line %d, file %s, inlining '%s' (from line %d, file %s)\n", - tmp->cln, tmp->cfn->name, t->name, tmp->dln, tmp->dfn->name); + printf("spin: %s:%d, inlining '%s' (from %s:%d)\n", + tmp->cfn->name, tmp->cln, t->name, tmp->dfn->name, tmp->dln); #endif for (j = 0; j < Inlining; j++) if (Inline_stub[j] == Inline_stub[Inlining]) @@ -930,13 +968,15 @@ fatal("malformed preprocessor directive - .fname", 0); if ((c = Getchar()) != '\"') - fatal("malformed preprocessor directive - .fname", 0); + { printf("got %c, expected \" -- lineno %d\n", c, lineno); + fatal("malformed preprocessor directive - .fname (%s)", yytext); + } - getword(c, notquote); + getword(Getchar(), notquote); /* was getword(c, notquote); */ if (Getchar() != '\"') fatal("malformed preprocessor directive - fname.", 0); - strcat(yytext, "\""); + /* strcat(yytext, "\""); */ Fname = lookup(yytext); done: while (Getchar() != '\n') @@ -965,41 +1005,43 @@ break; } } - fatal("cannot happen", (char *) 0); + fatal("cannot happen", (char *) 0); /* unreachable */ } + Symbol * prep_inline(Symbol *s, Lextok *nms) { int c, nest = 1, dln, firstchar, cnr; - char *p, buf[SOMETHINGBIG], buf2[RATHERSMALL]; + char *p; Lextok *t; + static char Buf1[SOMETHINGBIG], Buf2[RATHERSMALL]; static int c_code = 1; for (t = nms; t; t = t->rgt) if (t->lft) { if (t->lft->ntyp != NAME) - fatal("bad param to inline %s", s->name); + fatal("bad param to inline %s", s?s->name:"--"); t->lft->sym->hidden |= 32; } if (!s) /* C_Code fragment */ { s = (Symbol *) emalloc(sizeof(Symbol)); - s->name = (char *) emalloc((int) strlen("c_code")+26); + s->name = (char *) emalloc(strlen("c_code")+26); sprintf(s->name, "c_code%d", c_code++); s->context = context; s->type = CODE_FRAG; } else s->type = PREDEF; - p = &buf[0]; - buf2[0] = '\0'; + p = &Buf1[0]; + Buf2[0] = '\0'; for (;;) { c = Getchar(); switch (c) { case '[': if (s->type != CODE_FRAG) goto bad; - precondition(&buf2[0]); /* e.g., c_code [p] { r = p-r; } */ + precondition(&Buf2[0]); /* e.g., c_code [p] { r = p-r; } */ continue; case '{': break; @@ -1017,19 +1059,20 @@ dln = lineno; if (s->type == CODE_FRAG) { if (verbose&32) - sprintf(buf, "\t/* line %d %s */\n\t\t", + sprintf(Buf1, "\t/* line %d %s */\n\t\t", lineno, Fname->name); else - strcpy(buf, ""); + strcpy(Buf1, ""); } else - sprintf(buf, "\n#line %d %s\n{", lineno, Fname->name); - p += strlen(buf); + sprintf(Buf1, "\n#line %d \"%s\"\n{", lineno, Fname->name); + p += strlen(Buf1); firstchar = 1; cnr = 1; /* not zero */ more: - *p++ = c = Getchar(); - if (p - buf >= SOMETHINGBIG) + c = Getchar(); + *p++ = (char) c; + if (p - Buf1 >= SOMETHINGBIG) fatal("inline text too long", 0); switch (c) { case '\n': @@ -1046,8 +1089,8 @@ { *p = '\0'; if (s->type == CODE_FRAG) *--p = '\0'; /* remove trailing '}' */ - def_inline(s, dln, &buf[0], &buf2[0], nms); - if (firstchar && s) + def_inline(s, dln, &Buf1[0], &Buf2[0], nms); + if (firstchar) printf("%3d: %s, warning: empty inline definition (%s)\n", dln, Fname->name, s->name); return s; /* normal return */ @@ -1057,19 +1100,38 @@ if (cnr == 0) { p--; do_directive(c); /* reads to newline */ - break; - } /* else fall through */ - default: - firstchar = 0; + } else + { firstchar = 0; + cnr++; + } + break; case '\t': case ' ': case '\f': cnr++; break; + default: + firstchar = 0; + cnr++; + break; } goto more; } +static void +set_cur_scope(void) +{ int i; + char tmpbuf[256]; + + strcpy(CurScope, "_"); + + if (context) + for (i = 0; i < scope_level; i++) + { sprintf(tmpbuf, "%d_", scope_seq[i]); + strcat(CurScope, tmpbuf); + } +} + static int lex(void) { int c; @@ -1079,6 +1141,8 @@ yytext[0] = (char) c; yytext[1] = '\0'; switch (c) { + case EOF: + return c; case '\n': /* newline */ lineno++; case '\r': /* carriage return */ @@ -1099,6 +1163,13 @@ strcat(yytext, "\""); SymToken(lookup(yytext), STRING) + case '$': + getword('\"', notdollar); + if (Getchar() != '$') + fatal("ltl definition not terminated", yytext); + strcat(yytext, "\""); + SymToken(lookup(yytext), STRING) + case '\'': /* new 3.0.9 */ c = Getchar(); if (c == '\\') @@ -1131,6 +1202,26 @@ goto again; } + if (ltl_mode) + { switch (c) { + case '-': c = follow('>', IMPLIES, '-'); break; + case '[': c = follow(']', ALWAYS, '['); break; + case '<': c = follow('>', EVENTUALLY, '<'); + if (c == '<') + { c = Getchar(); + if (c == '-') + { c = follow('>', EQUIV, '-'); + if (c == '-') + { Ungetch(c); + c = '<'; + } + } else + { Ungetch(c); + c = '<'; + } } + default: break; + } } + switch (c) { case '/': c = follow('*', 0, '/'); if (!c) { in_comment = 1; goto again; } @@ -1149,12 +1240,35 @@ case '&': c = follow('&', AND, '&'); break; case '|': c = follow('|', OR, '|'); break; case ';': c = SEMI; break; + case '.': c = follow('.', DOTDOT, '.'); break; + case '{': scope_seq[scope_level++]++; set_cur_scope(); break; + case '}': scope_level--; set_cur_scope(); break; default : break; } Token(c) } static struct { + char *s; int tok; +} LTL_syms[] = { + /* [], <>, ->, and <-> are intercepted in lex() */ + { "U", UNTIL }, + { "V", RELEASE }, + { "W", WEAK_UNTIL }, + { "X", NEXT }, + { "always", ALWAYS }, + { "eventually", EVENTUALLY }, + { "until", UNTIL }, + { "stronguntil",UNTIL }, + { "weakuntil", WEAK_UNTIL }, + { "release", RELEASE }, + { "next", NEXT }, + { "implies", IMPLIES }, + { "equivalent", EQUIV }, + { 0, 0 }, +}; + +static struct { char *s; int tok; int val; char *sym; } Names[] = { {"active", ACTIVE, 0, 0}, @@ -1178,14 +1292,18 @@ {"eval", EVAL, 0, 0}, {"false", CONST, 0, 0}, {"fi", FI, 0, 0}, + {"for", FOR, 0, 0}, {"full", FULL, 0, 0}, {"goto", GOTO, 0, 0}, {"hidden", HIDDEN, 0, ":hide:"}, {"if", IF, 0, 0}, + {"in", IN, 0, 0}, {"init", INIT, 0, ":init:"}, + {"inline", INLINE, 0, 0}, {"int", TYPE, INT, 0}, {"len", LEN, 0, 0}, {"local", ISLOCAL, 0, ":local:"}, + {"ltl", LTL, 0, ":ltl:"}, {"mtype", TYPE, MTYPE, 0}, {"nempty", NEMPTY, 0, 0}, {"never", CLAIM, 0, ":never:"}, @@ -1203,7 +1321,7 @@ {"provided", PROVIDED, 0, 0}, {"run", RUN, 0, 0}, {"d_step", D_STEP, 0, 0}, - {"inline", INLINE, 0, 0}, + {"select", SELECT, 0, 0}, {"short", TYPE, SHORT, 0}, {"skip", CONST, 1, 0}, {"timeout", TIMEOUT, 0, 0}, @@ -1223,13 +1341,20 @@ { int i; yylval = nn(ZN, 0, ZN, ZN); + + if (ltl_mode) + { for (i = 0; LTL_syms[i].s; i++) + { if (strcmp(s, LTL_syms[i].s) == 0) + { return LTL_syms[i].tok; + } } } + for (i = 0; Names[i].s; i++) - if (strcmp(s, Names[i].s) == 0) + { if (strcmp(s, Names[i].s) == 0) { yylval->val = Names[i].val; if (Names[i].sym) yylval->sym = lookup(Names[i].sym); return Names[i].tok; - } + } } if ((yylval->val = ismtype(s)) != 0) { yylval->ismtyp = 1; @@ -1253,19 +1378,29 @@ Inline_stub[Inlining]->nm->name, Inline_stub[Inlining]->anms[i]); #endif - for (tt = Inline_stub[Inlining]->params; tt; tt = tt->rgt) if (!strcmp(Inline_stub[Inlining]->anms[i], tt->lft->sym->name)) { /* would be cyclic if not caught */ - printf("spin: line %d replacement value: %s\n", - lineno, tt->lft->sym->name); - fatal("formal par of %s matches replacement value", + printf("spin: %s:%d replacement value: %s\n", + oFname->name?oFname->name:"--", lineno, tt->lft->sym->name); + fatal("formal par of %s contains replacement value", Inline_stub[Inlining]->nm->name); yylval->ntyp = tt->lft->ntyp; yylval->sym = lookup(tt->lft->sym->name); return NAME; } + + /* check for occurrence of param as field of struct */ + { char *ptr = Inline_stub[Inlining]->anms[i]; + while ((ptr = strstr(ptr, s)) != NULL) + { if (*(ptr-1) == '.' + || *(ptr+strlen(s)) == '.') + { fatal("formal par of %s used in structure name", + Inline_stub[Inlining]->nm->name); + } + ptr++; + } } ReDiRect = Inline_stub[Inlining]->anms[i]; return 0; } } @@ -1353,6 +1488,9 @@ } else if (c == CONST && yytext[0] == '\'') { sprintf(yytext, "'%c'", yylval->val); strcat(IArg_cont[IArgno], yytext); + } else if (c == CONST) + { sprintf(yytext, "%d", yylval->val); + strcat(IArg_cont[IArgno], yytext); } else { switch (c) { @@ -1379,6 +1517,5 @@ strcat(IArg_cont[IArgno], yytext); } } - return c; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/structs.c --- a/sys/src/cmd/spin/structs.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/structs.c Tue Mar 06 23:34:10 2012 +0100 @@ -19,7 +19,7 @@ } UType; extern Symbol *Fname; -extern int lineno, depth, Expand_Ok; +extern int lineno, depth, Expand_Ok, has_hidden, in_for; Symbol *owner; @@ -33,14 +33,16 @@ setuname(Lextok *n) { UType *tmp; + if (!owner) + fatal("illegal reference inside typedef", (char *) 0); + for (tmp = Unames; tmp; tmp = tmp->nxt) if (!strcmp(owner->name, tmp->nm->name)) { non_fatal("typename %s was defined before", tmp->nm->name); return; } - if (!owner) fatal("illegal reference inside typedef", - (char *) 0); + tmp = (UType *) emalloc(sizeof(UType)); tmp->nm = owner; tmp->cn = n; @@ -102,21 +104,22 @@ { lineno = n->ln; Fname = n->fn; if (n->sym->type) - non_fatal("redeclaration of '%s'", n->sym->name); + fatal("redeclaration of '%s'", n->sym->name); if (n->sym->nbits > 0) - non_fatal("(%s) only an unsigned can have width-field", - n->sym->name); + non_fatal("(%s) only an unsigned can have width-field", + n->sym->name); if (Expand_Ok) n->sym->hidden |= (4|8|16); /* formal par */ if (vis) - { if (strncmp(vis->sym->name, ":hide:", 6) == 0) - n->sym->hidden |= 1; - else if (strncmp(vis->sym->name, ":show:", 6) == 0) + { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0) + { n->sym->hidden |= 1; + has_hidden++; + } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0) n->sym->hidden |= 2; - else if (strncmp(vis->sym->name, ":local:", 7) == 0) + else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0) n->sym->hidden |= 64; } n->sym->type = STRUCT; /* classification */ @@ -196,6 +199,7 @@ fatal("non-zero 'rgt' on non-structure", 0); ix = eval(tmp->lft); +/* printf("%d: ix: %d (%d) %d\n", depth, ix, tl->nel, tl->val[ix]); */ if (ix >= tl->nel || ix < 0) fatal("indexing error \'%s\'", tl->name); @@ -222,10 +226,12 @@ fatal("indexing error \'%s\'", tl->name); if (tl->nbits > 0) - a = (a & ((1<nbits)-1)); - tl->val[ix] = a; - tl->setat = depth; + a = (a & ((1<nbits)-1)); + if (a != tl->val[ix]) + { tl->val[ix] = a; + tl->setat = depth; + } return 1; } @@ -246,7 +252,7 @@ for (fp = n; fp; fp = fp->rgt) for (tl = fp->lft; tl; tl = tl->rgt) { if (tl->sym->type == STRUCT) - { if (tl->sym->nel != 1) + { if (tl->sym->nel > 1 || tl->sym->isarray) fatal("array of structures in param list, %s", tl->sym->name); cnt += Cnt_flds(tl->sym->Slst); @@ -266,9 +272,9 @@ return s->type; if (!t->rgt - || !t->rgt->ntyp == '.' + || t->rgt->ntyp != '.' /* gh: had ! in wrong place */ || !t->rgt->lft) - return STRUCT; /* not a field reference */ + return STRUCT; /* not a field reference */ return Sym_typ(t->rgt->lft); } @@ -315,6 +321,7 @@ if (!s) return ZN; d = (Lextok *) emalloc(sizeof(Lextok)); + d->uiid = s->uiid; d->ntyp = s->ntyp; d->val = s->val; d->ln = s->ln; @@ -353,7 +360,7 @@ goto out; } fprintf(fd, ".%s", tl->name); -out: if (tmp->sym->nel > 1) +out: if (tmp->sym->nel > 1 || tmp->sym->isarray == 1) { fprintf(fd, "[%d]", eval(tmp->lft)); hiddenarrays = 1; } @@ -391,7 +398,7 @@ } sprintf(lbuf, ".%s", tl->name); strcat(buf, lbuf); - if (tmp->sym->nel > 1) + if (tmp->sym->nel > 1 || tmp->sym->isarray == 1) { sprintf(lbuf, "[%d]", eval(tmp->lft)); strcat(buf, lbuf); } @@ -405,10 +412,10 @@ extern void Done_case(char *, Symbol *); ini_struct(z); - if (z->nel == 1) + if (z->nel == 1 && z->isarray == 0) sprintf(eprefix, "%s%s.", s, z->name); for (ix = 0; ix < z->nel; ix++) - { if (z->nel > 1) + { if (z->nel > 1 || z->isarray == 1) sprintf(eprefix, "%s%s[%d].", s, z->name, ix); for (fp = z->Sval[ix]; fp; fp = fp->rgt) for (tl = fp->lft; tl; tl = tl->rgt) @@ -426,10 +433,10 @@ int ix; ini_struct(z); - if (z->nel == 1) + if (z->nel == 1 && z->isarray == 0) sprintf(eprefix, "%s%s.", s, z->name); for (ix = 0; ix < z->nel; ix++) - { if (z->nel > 1) + { if (z->nel > 1 || z->isarray == 1) sprintf(eprefix, "%s%s[%d].", s, z->name, ix); for (fp = z->Sval[ix]; fp; fp = fp->rgt) for (tl = fp->lft; tl; tl = tl->rgt) @@ -443,7 +450,7 @@ void c_struct(FILE *fd, char *ipref, Symbol *z) { Lextok *fp, *tl; - char pref[256], eprefix[256]; + char pref[256], eprefix[300]; int ix; ini_struct(z); @@ -452,7 +459,7 @@ for (fp = z->Sval[ix]; fp; fp = fp->rgt) for (tl = fp->lft; tl; tl = tl->rgt) { strcpy(eprefix, ipref); - if (z->nel > 1) + if (z->nel > 1 || z->isarray == 1) { /* insert index before last '.' */ eprefix[strlen(eprefix)-1] = '\0'; sprintf(pref, "[ %d ].", ix); @@ -476,7 +483,7 @@ ini_struct(z); for (ix = 0; ix < z->nel; ix++) - { if (z->nel > 1) + { if (z->nel > 1 || z->isarray == 1) sprintf(eprefix, "%s[%d]", prefix, ix); else strcpy(eprefix, prefix); @@ -484,7 +491,7 @@ for (fp = z->Sval[ix]; fp; fp = fp->rgt) for (tl = fp->lft; tl; tl = tl->rgt) { if (tl->sym->type == STRUCT) - { char pref[256]; + { char pref[300]; strcpy(pref, eprefix); strcat(pref, "."); strcat(pref, tl->sym->name); @@ -498,7 +505,7 @@ if (r) printf("%s(%d):", r->n->name, r->pid); printf("%s.%s", eprefix, tl->sym->name); - if (tl->sym->nel > 1) + if (tl->sym->nel > 1 || tl->sym->isarray == 1) printf("[%d]", jx); printf(" = "); sr_mesg(stdout, tl->sym->val[jx], @@ -579,9 +586,11 @@ int i, cnt; extern int IArgs; if (n->sym->type != STRUCT + || in_for || is_explicit(n)) return n; + if (n->rgt && n->rgt->ntyp == '.' && n->rgt->lft diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/sym.c --- a/sys/src/cmd/spin/sym.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/sym.c Tue Mar 06 23:34:10 2012 +0100 @@ -14,14 +14,19 @@ extern Symbol *Fname, *owner; extern int lineno, depth, verbose, NamesNotAdded, deadvar; +extern int has_hidden, m_loss, old_scope_rules; extern short has_xu; +extern char CurScope[MAXSCOPESZ]; Symbol *context = ZS; Ordered *all_names = (Ordered *)0; int Nid = 0; +Lextok *Mtype = (Lextok *) 0; + static Ordered *last_name = (Ordered *)0; static Symbol *symtab[Nhash+1]; +static Lextok *runstmnts = ZN; static int samename(Symbol *a, Symbol *b) @@ -44,31 +49,77 @@ return h&Nhash; } +void +disambiguate(void) +{ Ordered *walk; + Symbol *sp; + + if (old_scope_rules) + return; + + /* if the same name appears in two different scopes, + prepend the scope_prefix to the names */ + + for (walk = all_names; walk; walk = walk->next) + { sp = walk->entry; + if (sp->type != 0 + && sp->type != LABEL + && strlen((const char *)sp->bscp) > 1) + { char *n = (char *) emalloc(strlen((const char *)sp->name) + + strlen((const char *)sp->bscp) + 1); + sprintf(n, "%s%s", sp->bscp, sp->name); + sp->name = n; /* discord the old memory */ + } } +} + Symbol * lookup(char *s) { Symbol *sp; Ordered *no; int h = hash(s); + if (old_scope_rules) + { /* same scope - global refering to global or local to local */ + for (sp = symtab[h]; sp; sp = sp->next) + { if (strcmp(sp->name, s) == 0 + && samename(sp->context, context) + && samename(sp->owner, owner)) + { return sp; /* found */ + } } + } else + { /* added 6.0.0: more traditional, scope rule */ + for (sp = symtab[h]; sp; sp = sp->next) + { if (strcmp(sp->name, s) == 0 + && samename(sp->context, context) + && (strcmp((const char *)sp->bscp, CurScope) == 0 + || strncmp((const char *)sp->bscp, CurScope, strlen((const char *)sp->bscp)) == 0) + && samename(sp->owner, owner)) + { + if (!samename(sp->owner, owner)) + { printf("spin: different container %s\n", sp->name); + printf(" old: %s\n", sp->owner?sp->owner->name:"--"); + printf(" new: %s\n", owner?owner->name:"--"); + /* alldone(1); */ + } + return sp; /* found */ + } } } + + if (context) /* in proctype, refers to global */ for (sp = symtab[h]; sp; sp = sp->next) - if (strcmp(sp->name, s) == 0 - && samename(sp->context, context) - && samename(sp->owner, owner)) - return sp; /* found */ - - if (context) /* in proctype */ - for (sp = symtab[h]; sp; sp = sp->next) - if (strcmp(sp->name, s) == 0 + { if (strcmp(sp->name, s) == 0 && !sp->context && samename(sp->owner, owner)) - return sp; /* global */ + { return sp; /* global */ + } } sp = (Symbol *) emalloc(sizeof(Symbol)); - sp->name = (char *) emalloc((int) strlen(s) + 1); + sp->name = (char *) emalloc(strlen(s) + 1); strcpy(sp->name, s); sp->nel = 1; sp->setat = depth; sp->context = context; sp->owner = owner; /* if fld in struct */ + sp->bscp = (unsigned char *) emalloc(strlen((const char *)CurScope)+1); + strcpy((char *)sp->bscp, CurScope); if (NamesNotAdded == 0) { sp->next = symtab[h]; @@ -109,8 +160,6 @@ } } -Lextok *runstmnts = ZN; - void trackrun(Lextok *n) { @@ -151,11 +200,11 @@ strcpy(buf2, (!(res&4))?"bit":"byte"); sputtype(buf, parnm->type); i = (int) strlen(buf); - while (buf[--i] == ' ') buf[i] = '\0'; - if (strcmp(buf, buf2) == 0) return; + while (i > 0 && buf[--i] == ' ') buf[i] = '\0'; + if (i == 0 || strcmp(buf, buf2) == 0) return; prehint(parnm); printf("proctype %s, '%s %s' could be declared", - parnm->context->name, buf, parnm->name); + parnm->context?parnm->context->name:"", buf, parnm->name); printf(" '%s %s'\n", buf2, parnm->name); } } @@ -178,9 +227,9 @@ while (n) { if (n->sym->type && !(n->sym->hidden&32)) - { lineno = n->ln; Fname = n->fn; - non_fatal("redeclaration of '%s'", n->sym->name); - lineno = oln; + { lineno = n->ln; Fname = n->fn; + fatal("redeclaration of '%s'", n->sym->name); + lineno = oln; } n->sym->type = (short) t; @@ -201,14 +250,15 @@ n->sym->name); } if (vis) - { if (strncmp(vis->sym->name, ":hide:", 6) == 0) + { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0) { n->sym->hidden |= 1; + has_hidden++; if (t == BIT) fatal("bit variable (%s) cannot be hidden", n->sym->name); - } else if (strncmp(vis->sym->name, ":show:", 6) == 0) + } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0) { n->sym->hidden |= 2; - } else if (strncmp(vis->sym->name, ":local:", 7) == 0) + } else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0) { n->sym->hidden |= 64; } } @@ -268,7 +318,13 @@ setxus(Lextok *p, int t) { Lextok *m, *n; - has_xu = 1; + has_xu = 1; + + if (m_loss && t == XS) + { printf("spin: warning, %s:%d, xs tag not compatible with -m (message loss)\n", + (p->fn != NULL) ? p->fn->name : "stdin", p->ln); + } + if (!context) { lineno = p->ln; Fname = p->fn; @@ -276,6 +332,7 @@ } for (m = p; m; m = m->rgt) { Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok)); + Xu_new->uiid = p->uiid; Xu_new->val = t; Xu_new->lft = m->lft; Xu_new->sym = context; @@ -297,8 +354,6 @@ } } -Lextok *Mtype = (Lextok *) 0; - void setmtype(Lextok *m) { Lextok *n; @@ -332,7 +387,7 @@ } lineno = oln; if (cnt > 256) - fatal("too many mtype elements (>255)", (char *)0); + fatal("too many mtype elements (>255)", (char *)0); } int @@ -389,11 +444,11 @@ printf("\t"); if (sp->owner) printf("%s.", sp->owner->name); printf("%s", sp->name); - if (sp->nel > 1) printf("[%d]", sp->nel); + if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel); if (sp->type == CHAN) printf("\t%d", (sp->ini)?sp->ini->val:0); - else if (sp->type == STRUCT) /* Frank Weil, 2.9.8 */ + else if (sp->type == STRUCT && sp->Snm != NULL) /* Frank Weil, 2.9.8 */ printf("\t%s", sp->Snm->name); else printf("\t%d", eval(sp->ini)); @@ -408,8 +463,13 @@ if (sp->Nid < 0) /* formal parameter */ printf("\t", -(sp->Nid)); + else if (sp->type == MTYPE) + printf("\t"); + else if (sp->isarray) + printf("\t"); else printf("\t"); + if (sp->type == CHAN && sp->ini) { int i; for (m = sp->ini->rgt, i = 0; m; m = m->rgt) @@ -423,6 +483,9 @@ if (m->rgt) printf("\t"); } } + +if (1) printf("\t{scope %s}", sp->bscp); + printf("\n"); } @@ -440,11 +503,10 @@ if (sp->context) printf("%s-", sp->context->name); if (sp->owner) printf("%s.", sp->owner->name); printf("%s", sp->name); - if (sp->nel > 1) printf("[%d]", sp->nel); + if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel); printf("\t"); } - static struct X { int typ; char *nm; } xx[] = { diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl.h --- a/sys/src/cmd/spin/tl.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl.h Tue Mar 06 23:34:10 2012 +0100 @@ -82,7 +82,7 @@ Symbol *getsym(Symbol *); Symbol *DoDump(Node *); -char *emalloc(int); /* in main.c */ +extern char *emalloc(size_t); /* in main.c */ int anywhere(int, Node *, Node *); int dump_cond(Node *, Node *, int); @@ -100,6 +100,10 @@ void Fatal(char *, char *); void fatal(char *, char *); void fsm_print(void); +void ini_buchi(void); +void ini_cache(void); +void ini_rewrt(void); +void ini_trans(void); void releasenode(int, Node *); void tfree(void *); void tl_explain(int); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_buchi.c --- a/sys/src/cmd/spin/tl_buchi.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_buchi.c Tue Mar 06 23:34:10 2012 +0100 @@ -15,6 +15,7 @@ #include "tl.h" extern int tl_verbose, tl_clutter, Total, Max_Red; +extern char *claim_name; FILE *tl_out; /* if standalone: = stdout; */ @@ -38,6 +39,13 @@ static State *never = (State *) 0; static int hitsall; +void +ini_buchi(void) +{ + never = (State *) 0; + hitsall = 0; +} + static int sametrans(Transition *s, Transition *t) { @@ -626,13 +634,13 @@ if (tl_clutter) clutter(); b = findstate("T0_init"); - if (Max_Red == 0) + if (b && (Max_Red == 0)) b->accepting = 1; mergestates(0); b = findstate("T0_init"); - fprintf(tl_out, "never { /* "); + fprintf(tl_out, "never %s { /* ", claim_name?claim_name:""); put_uform(); fprintf(tl_out, " */\n"); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_cache.c --- a/sys/src/cmd/spin/tl_cache.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_cache.c Tue Mar 06 23:34:10 2012 +0100 @@ -28,6 +28,14 @@ extern void fatal(char *, char *); int sameform(Node *, Node *); +void +ini_cache(void) +{ + stored = (Cache *) 0; + Caches = 0; + CacheHits = 0; +} + #if 0 void cache_dump(void) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_lex.c --- a/sys/src/cmd/spin/tl_lex.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_lex.c Tue Mar 06 23:34:10 2012 +0100 @@ -18,6 +18,7 @@ static Symbol *symtab[Nhash+1]; static int tl_lex(void); +extern int tl_peek(int); extern YYSTYPE tl_yylval; extern char yytext[]; @@ -54,12 +55,79 @@ tl_yylex(void) { int c = tl_lex(); #if 0 - printf("c = %d\n", c); + printf("c = %c (%d)\n", c, c); #endif return c; } static int +is_predicate(int z) +{ char c, c_prev = z; + char want = (z == '{') ? '}' : ')'; + int i = 0, j, nesting = 0; + char peek_buf[512]; + + c = tl_peek(i++); /* look ahead without changing position */ + while ((c != want || nesting > 0) && c != -1 && i < 2047) + { if (islower((int) c)) + { peek_buf[0] = c; + j = 1; + while (j < (int) sizeof(peek_buf) && isalnum((int)(c = tl_peek(i)))) + { peek_buf[j++] = c; + i++; + } + c = 0; /* make sure we don't match on z or want on the peekahead */ + if (j >= (int) sizeof(peek_buf)) + { peek_buf[j-1] = '\0'; + fatal("name '%s' in ltl formula too long", peek_buf); + } + peek_buf[j] = '\0'; + if (strcmp(peek_buf, "always") == 0 + || strcmp(peek_buf, "eventually") == 0 + || strcmp(peek_buf, "until") == 0 + || strcmp(peek_buf, "next") == 0) + { return 0; + } + } else + { char c_nxt = tl_peek(i); + if (((c == 'U' || c == 'V' || c == 'X') && !isalnum_(c_prev) && !isalnum_(c_nxt)) + || (c == '<' && c_nxt == '>') + || (c == '[' && c_nxt == ']')) + { return 0; + } } + + if (c == z) + { nesting++; + } + if (c == want) + { nesting--; + } + c_prev = c; + c = tl_peek(i++); + } + return 1; +} + +static void +read_upto_closing(int z) +{ char c, want = (z == '{') ? '}' : ')'; + int i = 0, nesting = 0; + + c = tl_Getchar(); + while ((c != want || nesting > 0) && c != -1 && i < 2047) /* yytext is 2048 */ + { yytext[i++] = c; + if (c == z) + { nesting++; + } + if (c == want) + { nesting--; + } + c = tl_Getchar(); + } + yytext[i] = '\0'; +} + +static int tl_lex(void) { int c; @@ -74,6 +142,17 @@ } while (c == ' '); /* '\t' is removed in tl_main.c */ + if (c == '{' || c == '(') /* new 6.0.0 */ + { if (is_predicate(c)) + { read_upto_closing(c); + tl_yylval = tl_nn(PREDICATE,ZN,ZN); + tl_yylval->sym = tl_lookup(yytext); + return PREDICATE; + } } + + if (c == '}') + { tl_yyerror("unexpected '}'"); + } if (islower(c)) { tl_getword(c, isalnum_); if (strcmp("true", yytext) == 0) @@ -82,10 +161,28 @@ if (strcmp("false", yytext) == 0) { Token(FALSE); } + if (strcmp("always", yytext) == 0) + { Token(ALWAYS); + } + if (strcmp("eventually", yytext) == 0) + { Token(EVENTUALLY); + } + if (strcmp("until", yytext) == 0) + { Token(U_OPER); + } +#ifdef NXT + if (strcmp("next", yytext) == 0) + { Token(NEXT); + } +#endif + if (strcmp("not", yytext) == 0) + { Token(NOT); + } tl_yylval = tl_nn(PREDICATE,ZN,ZN); tl_yylval->sym = tl_lookup(yytext); return PREDICATE; } + if (c == '<') { c = tl_Getchar(); if (c == '>') diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_main.c --- a/sys/src/cmd/spin/tl_main.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_main.c Tue Mar 06 23:34:10 2012 +0100 @@ -21,7 +21,10 @@ int tl_verbose = 0; int tl_terse = 0; int tl_clutter = 0; +int state_cnt = 0; + unsigned long All_Mem = 0; +char *claim_name; static char uform[4096]; static int hasuform=0, cnt=0; @@ -38,6 +41,15 @@ return -1; } +int +tl_peek(int n) +{ + if (cnt+n < hasuform) + { return uform[cnt+n]; + } + return -1; +} + void tl_balanced(void) { int i; @@ -79,16 +91,33 @@ int tl_main(int argc, char *argv[]) { int i; - extern int verbose, xspin; - tl_verbose = verbose; + extern int /* verbose, */ xspin; + + tl_verbose = 0; /* was: tl_verbose = verbose; */ tl_clutter = 1-xspin; /* use -X -f to turn off uncluttering */ + newstates = 0; + state_cnt = 0; + tl_errs = 0; + tl_terse = 0; + All_Mem = 0; + memset(uform, 0, sizeof(uform)); + hasuform=0; + cnt=0; + claim_name = (char *) 0; + + ini_buchi(); + ini_cache(); + ini_rewrt(); + ini_trans(); + while (argc > 1 && argv[1][0] == '-') - { switch (argv[1][1]) { + { + switch (argv[1][1]) { case 'd': newstates = 1; /* debugging mode */ break; case 'f': argc--; argv++; - for (i = 0; i < argv[1][i]; i++) + for (i = 0; argv[1][i]; i++) { if (argv[1][i] == '\t' || argv[1][i] == '\"' || argv[1][i] == '\n') @@ -101,6 +130,10 @@ break; case 'n': tl_terse = 1; break; + case 'c': argc--; argv++; + claim_name = (char *) emalloc(strlen(argv[1])+1); + strcpy(claim_name, argv[1]); + break; default : printf("spin -f: saw '-%c'\n", argv[1][1]); goto nogood; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_parse.c --- a/sys/src/cmd/spin/tl_parse.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_parse.c Tue Mar 06 23:34:10 2012 +0100 @@ -48,7 +48,6 @@ break; case ALWAYS: tl_yychar = tl_yylex(); - ptr = tl_factor(); #ifndef NO_OPT if (ptr->ntyp == FALSE @@ -385,7 +384,10 @@ void tl_parse(void) -{ Node *n = tl_formula(); +{ Node *n; + + /* tl_verbose = 1; */ + n = tl_formula(); if (tl_verbose) { printf("formula: "); dump(n); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_rewrt.c --- a/sys/src/cmd/spin/tl_rewrt.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_rewrt.c Tue Mar 06 23:34:10 2012 +0100 @@ -18,6 +18,12 @@ static Node *can = ZN; +void +ini_rewrt(void) +{ + can = ZN; +} + Node * right_linked(Node *n) { @@ -146,7 +152,10 @@ prev = ZN; for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt) { t = DoDump(m->lft); - cmp = strcmp(s->name, t->name); + if (t != ZS) + cmp = strcmp(s->name, t->name); + else + cmp = 0; if (cmp == 0) /* duplicate */ return; if (cmp < 0) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/tl_trans.c --- a/sys/src/cmd/spin/tl_trans.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/tl_trans.c Tue Mar 06 23:34:10 2012 +0100 @@ -15,7 +15,7 @@ #include "tl.h" extern FILE *tl_out; -extern int tl_errs, tl_verbose, tl_terse, newstates; +extern int tl_errs, tl_verbose, tl_terse, newstates, state_cnt; int Stack_mx=0, Max_Red=0, Total=0; @@ -51,6 +51,24 @@ static void push_stack(Graph *); static void sdump(Node *); +void +ini_trans(void) +{ + Stack_mx = 0; + Max_Red = 0; + Total = 0; + + Mapped = (Mapping *) 0; + Nodes_Set = (Graph *) 0; + Nodes_Stack = (Graph *) 0; + + memset(dumpbuf, 0, sizeof(dumpbuf)); + Red_cnt = 0; + Lab_cnt = 0; + Base = 0; + Stack_sz = 0; +} + static void dump_graph(Graph *g) { Node *n1; @@ -101,9 +119,8 @@ static char * newname(void) -{ static int cnt = 0; - static char buf[32]; - sprintf(buf, "S%d", cnt++); +{ static char buf[32]; + sprintf(buf, "S%d", state_cnt++); return buf; } @@ -342,7 +359,7 @@ fsm_trans(Graph *p, int count, char *curnm) { Graph *r; Symbol *s; - char prefix[128], nwnm[128]; + char prefix[128], nwnm[256]; if (!p->outgoing) addtrans(p, curnm, False, "accept_all"); @@ -722,6 +739,8 @@ push_stack(g); break; case V_OPER: + Assert(now->rgt != ZN, now->ntyp); + Assert(now->lft != ZN, now->ntyp); Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->rgt; @@ -759,6 +778,7 @@ #ifdef NXT case NEXT: + Assert(now->lft != ZN, now->ntyp); nx = dupnode(now->lft); nx->nxt = g->Next; g->Next = nx; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/vars.c --- a/sys/src/cmd/spin/vars.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/vars.c Tue Mar 06 23:34:10 2012 +0100 @@ -110,6 +110,7 @@ } } lineno = oln; Fname = ofnm; + return 1; } @@ -145,7 +146,7 @@ } if (v != i+s+ (int) u) - { char buf[32]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t); + { char buf[64]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t); non_fatal("value (%s) truncated in assignment", buf); } return (int)(i+s+u); @@ -159,9 +160,12 @@ else { int n = eval(v->lft); if (checkvar(v->sym, n)) - { v->sym->val[n] = cast_val(v->sym->type, m, v->sym->nbits); - v->sym->setat = depth; - } } + { int oval = v->sym->val[n]; + int nval = cast_val(v->sym->type, m, v->sym->nbits); + v->sym->val[n] = nval; + if (oval != nval) + { v->sym->setat = depth; + } } } return 1; } @@ -215,7 +219,12 @@ continue; if (sp->type == STRUCT) - { dump_struct(sp, sp->name, 0); + { if ((verbose&4) && !(verbose&64) + && (sp->setat < depth + && jumpsteps != depth)) + { continue; + } + dump_struct(sp, sp->name, 0); continue; } for (j = 0; j < sp->nel; j++) @@ -227,13 +236,15 @@ if ((verbose&4) && !(verbose&64) && (sp->setat < depth && jumpsteps != depth)) - continue; + { continue; + } + dummy->sym = sp; dummy->lft->val = j; /* in case of cast_val warnings, do this first: */ prefetch = getglobal(dummy); printf("\t\t%s", sp->name); - if (sp->nel > 1) printf("[%d]", j); + if (sp->nel > 1 || sp->isarray) printf("[%d]", j); printf(" = "); sr_mesg(stdout, prefetch, sp->type == MTYPE); @@ -266,7 +277,7 @@ depth, colpos); printf("(state 0)\t[printf('MSC: globvar\\\\n')]\n"); printf("\t\t%s", sp->name); - if (sp->nel > 1) printf("[%d]", j); + if (sp->nel > 1 || sp->isarray) printf("[%d]", j); printf(" = %s\n", Buf); } } } } @@ -303,8 +314,8 @@ dummy->lft->val = i; printf("\t\t%s(%d):%s", - r->n->name, r->pid, z->name); - if (z->nel > 1) printf("[%d]", i); + r->n->name, r->pid - Have_claim, z->name); + if (z->nel > 1 || z->isarray) printf("[%d]", i); printf(" = "); sr_mesg(stdout, getval(dummy), z->type == MTYPE); printf("\n"); @@ -341,7 +352,7 @@ printf("(state 0)\t[printf('MSC: locvar\\\\n')]\n"); printf("\t\t%s(%d):%s", r->n->name, r->pid, z->name); - if (z->nel > 1) printf("[%d]", i); + if (z->nel > 1 || z->isarray) printf("[%d]", i); printf(" = %s\n", Buf); } } } } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/spin/version.h --- a/sys/src/cmd/spin/version.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/spin/version.h Tue Mar 06 23:34:10 2012 +0100 @@ -1,1 +1,1 @@ -#define Version "Spin Version 4.3.0 -- 22 June 2007" +#define SpinVersion "Spin Version 6.1.0 -- 4 May 2011" diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/ssh/ssh.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/ssh/ssh.c Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,591 @@ +#include "ssh.h" + +int cooked = 0; /* user wants cooked mode */ +int raw = 0; /* console is in raw mode */ +int crstrip; +int interactive = -1; +int usemenu = 1; +int isatty(int); +int rawhack; +int forwardagent = 0; +char *buildcmd(int, char**); +void fromnet(Conn*); +void fromstdin(Conn*); +void winchanges(Conn*); +static void sendwritemsg(Conn *c, char *buf, int n); + +/* + * Lifted from telnet.c, con.c + */ +static int consctl = -1; +static int outfd = 1; /* changed during system */ +static void system(Conn*, char*); + +Cipher *allcipher[] = { + &cipherrc4, + &cipherblowfish, + &cipher3des, + &cipherdes, + &ciphernone, + &ciphertwiddle, +}; + +Auth *allauth[] = { + &authpassword, + &authrsa, + &authtis, +}; + +char *cipherlist = "blowfish rc4 3des"; +char *authlist = "rsa password tis"; + +Cipher* +findcipher(char *name, Cipher **list, int nlist) +{ + int i; + + for(i=0; iname) == 0) + return list[i]; + error("unknown cipher %s", name); + return nil; +} + +Auth* +findauth(char *name, Auth **list, int nlist) +{ + int i; + + for(i=0; iname) == 0) + return list[i]; + error("unknown auth %s", name); + return nil; +} + +void +usage(void) +{ + fprint(2, "usage: ssh [-CiImPpRr] [-A authlist] [-c cipherlist] [user@]hostname [cmd [args]]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int i, dowinchange, fd, usepty; + char *host, *cmd, *user, *p; + char *f[16]; + Conn c; + Msg *m; + + fmtinstall('B', mpfmt); + fmtinstall('H', encodefmt); + atexit(atexitkiller); + atexitkill(getpid()); + + dowinchange = 0; + if(getenv("LINES")) + dowinchange = 1; + usepty = -1; + user = nil; + ARGBEGIN{ + case 'B': /* undocumented, debugging */ + doabort = 1; + break; + case 'D': /* undocumented, debugging */ + debuglevel = strtol(EARGF(usage()), nil, 0); + break; + case 'l': /* deprecated */ + case 'u': + user = EARGF(usage()); + break; + case 'a': /* used by Unix scp implementations; we must ignore them. */ + case 'x': + break; + + case 'A': + authlist = EARGF(usage()); + break; + case 'C': + cooked = 1; + break; + case 'c': + cipherlist = EARGF(usage()); + break; + case 'f': + forwardagent = 1; + break; + case 'I': + interactive = 0; + break; + case 'i': + interactive = 1; + break; + case 'm': + usemenu = 0; + break; + case 'P': + usepty = 0; + break; + case 'p': + usepty = 1; + break; + case 'R': + rawhack = 1; + break; + case 'r': + crstrip = 1; + break; + default: + usage(); + }ARGEND + + if(argc < 1) + usage(); + + host = argv[0]; + + cmd = nil; + if(argc > 1) + cmd = buildcmd(argc-1, argv+1); + + if((p = strchr(host, '@')) != nil){ + *p++ = '\0'; + user = host; + host = p; + } + if(user == nil) + user = getenv("user"); + if(user == nil) + sysfatal("cannot find user name"); + + privatefactotum(); + if(interactive==-1) + interactive = isatty(0); + + if((fd = dial(netmkaddr(host, "tcp", "ssh"), nil, nil, nil)) < 0) + sysfatal("dialing %s: %r", host); + + memset(&c, 0, sizeof c); + c.interactive = interactive; + c.fd[0] = c.fd[1] = fd; + c.user = user; + c.host = host; + setaliases(&c, host); + + c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", "); + c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher); + for(i=0; i=9 && strcmp(buf+strlen(buf)-9, "/dev/cons")==0) + return 1; + return 0; +} + +char* +buildcmd(int argc, char **argv) +{ + int i, len; + char *s, *t; + + len = argc-1; + for(i=0; itype){ + default: + badmsg(m, 0); + + case SSH_SMSG_EXITSTATUS: + ex = getlong(m); + if(ex==0) + exits(0); + sprint(buf, "%lud", ex); + exits(buf); + + case SSH_MSG_DISCONNECT: + s = getstring(m); + error("disconnect: %s", s); + + /* + * If we ever add reverse port forwarding, we'll have to + * revisit this. It assumes that the agent connections are + * the only ones. + */ + case SSH_SMSG_AGENT_OPEN: + if(!forwardagent) + error("server tried to use agent forwarding"); + handleagentopen(m); + break; + case SSH_MSG_CHANNEL_INPUT_EOF: + if(!forwardagent) + error("server tried to use agent forwarding"); + handleagentieof(m); + break; + case SSH_MSG_CHANNEL_OUTPUT_CLOSED: + if(!forwardagent) + error("server tried to use agent forwarding"); + handleagentoclose(m); + break; + case SSH_MSG_CHANNEL_DATA: + if(!forwardagent) + error("server tried to use agent forwarding"); + handleagentmsg(m); + break; + + case SSH_SMSG_STDOUT_DATA: + fd = outfd; + goto Dataout; + case SSH_SMSG_STDERR_DATA: + fd = 2; + goto Dataout; + Dataout: + len = getlong(m); + s = (char*)getbytes(m, len); + if(crstrip){ + es = s+len; + for(r=w=s; r>> "); + for(done = 0; !done; ){ + n = read(0, buf, sizeof(buf)-1); + if(n <= 0) + return -1; + buf[n] = 0; + switch(buf[0]){ + case '!': + print(buf); + system(c, buf+1); + print("!\n"); + done = 1; + break; + case 'i': + buf[0] = 0x1c; + sendwritemsg(c, buf, 1); + done = 1; + break; + case '.': + case 'q': + done = 1; + break; + case 'r': + crstrip = 1-crstrip; + done = 1; + break; + default: + fprint(2, STDHELP); + break; + } + if(!done) + fprint(2, ">>> "); + } + + if(wasraw) + rawon(); + else + rawoff(); + return buf[0]; +} + +static void +sendwritemsg(Conn *c, char *buf, int n) +{ + Msg *m; + + if(n==0) + m = allocmsg(c, SSH_CMSG_EOF, 0); + else{ + m = allocmsg(c, SSH_CMSG_STDIN_DATA, 4+n); + putlong(m, n); + putbytes(m, buf, n); + } + sendmsg(m); +} + +/* + * run a command with the network connection as standard IO + */ +static void +system(Conn *c, char *cmd) +{ + int pid; + int p; + int pfd[2]; + int n; + int wasconsctl; + char buf[4096]; + + if(pipe(pfd) < 0){ + perror("pipe"); + return; + } + outfd = pfd[1]; + + wasconsctl = consctl; + close(consctl); + consctl = -1; + switch(pid = fork()){ + case -1: + perror("con"); + return; + case 0: + close(pfd[1]); + dup(pfd[0], 0); + dup(pfd[0], 1); + close(c->fd[0]); /* same as c->fd[1] */ + close(pfd[0]); + if(*cmd) + execl("/bin/rc", "rc", "-c", cmd, nil); + else + execl("/bin/rc", "rc", nil); + perror("con"); + exits("exec"); + break; + default: + close(pfd[0]); + while((n = read(pfd[1], buf, sizeof(buf))) > 0) + sendwritemsg(c, buf, n); + p = waitpid(); + outfd = 1; + close(pfd[1]); + if(p < 0 || p != pid) + return; + break; + } + if(wasconsctl >= 0){ + consctl = open("/dev/consctl", OWRITE); + if(consctl < 0) + error("cannot open consctl"); + } +} + +static void +cookedcatchint(void*, char *msg) +{ + if(strstr(msg, "interrupt")) + noted(NCONT); + else if(strstr(msg, "kill")) + noted(NDFLT); + else + noted(NCONT); +} + +static int +wasintr(void) +{ + char err[64]; + + rerrstr(err, sizeof err); + return strstr(err, "interrupt") != 0; +} + +void +fromstdin(Conn *c) +{ + int n; + char buf[1024]; + int pid; + int eofs; + + switch(pid = rfork(RFMEM|RFPROC|RFNOWAIT)){ + case -1: + error("fork: %r"); + case 0: + break; + default: + atexitkill(pid); + return; + } + + atexit(atexitkiller); + if(interactive) + rawon(); + + notify(cookedcatchint); + + eofs = 0; + for(;;){ + n = read(0, buf, sizeof(buf)); + if(n < 0){ + if(wasintr()){ + if(!raw){ + buf[0] = 0x7f; + n = 1; + }else + continue; + }else + break; + } + if(n == 0){ + if(!c->interactive || ++eofs > 32) + break; + }else + eofs = 0; + if(interactive && usemenu && n && memchr(buf, 0x1c, n)) { + if(menu(c)=='q'){ + sendwritemsg(c, "", 0); + exits("quit"); + } + continue; + } + if(!raw && n==0){ + buf[0] = 0x4; + n = 1; + } + sendwritemsg(c, buf, n); + } + sendwritemsg(c, "", 0); + atexitdont(atexitkiller); + exits(nil); +} + +void +winchanges(Conn *c) +{ + int nrow, ncol, width, height; + int pid; + + switch(pid = rfork(RFMEM|RFPROC|RFNOWAIT)){ + case -1: + error("fork: %r"); + case 0: + break; + default: + atexitkill(pid); + return; + } + + for(;;){ + if(readgeom(&nrow, &ncol, &width, &height) < 0) + break; + sendwindowsize(c, nrow, ncol, width, height); + } + exits(nil); +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/tar.c --- a/sys/src/cmd/tar.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/tar.c Tue Mar 06 23:34:10 2012 +0100 @@ -30,8 +30,8 @@ USED(argv); USED(argc); } #define TARGC() (_argc) -#define ROUNDUP(a, b) (((a) + (b) - 1)/(b)) -#define BYTES2TBLKS(bytes) ROUNDUP(bytes, Tblock) +#define HOWMANY(a, size) (((a) + (size) - 1) / (size)) +#define BYTES2TBLKS(bytes) HOWMANY(bytes, Tblock) /* read big-endian binary integers; args must be (uchar *) */ #define G2BEBYTE(x) (((x)[0]<<8) | (x)[1]) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/tarsplit/mkfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/tarsplit/mkfile Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,11 @@ + +#include +#include +#include "tar.h" + +enum { + Stdin, + Stdout, +}; + +static int debug; + +/* don't copy zero blocks at end */ +static void +catenate(int in, char *inname) +{ + vlong len; + static Hblock hdr; + Hblock *hp = &hdr; + + if (debug) + fprint(2, "%s: reading %s\n", inname, argv0); + while (getdir(hp, in, &len)) { + writetar(Stdout, (char *)hp, Tblock); /* write dir block */ + passtar(hp, in, Stdout, len); + } +} + +void +main(int argc, char **argv) +{ + int errflg = 0; + + ARGBEGIN { + case 'd': + ++debug; + break; + default: + errflg++; + break; + } ARGEND + if (errflg) { + fprint(2, "usage: %s [-d] [file]...\n", argv0); + exits("usage"); + } + + if (argc <= 0) + catenate(Stdin, "/fd/0"); + else + for (; argc-- > 0; argv++) { + int in = open(argv[0], OREAD); + + if (in < 0) + sysfatal("%s: %r", argv[0]); + catenate(in, argv[0]); + close(in); + } + closeout(Stdout, "/fd/1", 0); + exits(0); +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/tarsplit/tarsplit.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/tarsplit/tarsplit.c Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,104 @@ +/* + * tarsplit [-d] [-p pfx] [-s size] - split a tar archive into independent + * tar archives under some size + */ + +#include +#include +#include +#include "tar.h" + +enum { + Stdin, + Endsize = 2 * Tblock, /* size of zero blocks at archive end */ +}; + +/* private data */ +static char *filenm; +static char *prefix = "ts."; +static vlong size = 512*1024*1024; /* fits on a CD with room to spare */ + +static int +opennext(int out, char *prefix) +{ + static int filenum = 0; + + if (out >= 0) { + fprint(2, "%s: opennext called with file open\n", argv0); + exits("open botch"); + } + free(filenm); + filenm = smprint("%s%.5d", prefix, filenum++); + fprint(2, "%s: %s ...", filenm, thisnm); + out = create(filenm, OWRITE, 0666); + if (out < 0) + sysfatal("%s: %r", filenm); + newarch(); + return out; +} + +static int +split(int in, int out, char * /* inname */) +{ + vlong len, membsz; + uvlong outoff = 0; + static Hblock hdr; + Hblock *hp = &hdr; + + while (getdir(hp, in, &len)) { + membsz = Tblock + ROUNDUP((uvlong)len, Tblock); + if (outoff + membsz + Endsize > size) { /* won't fit? */ + out = closeout(out, filenm, 1); + if (membsz + Endsize > size) + sysfatal("archive member %s (%,lld) + overhead " + "exceeds size limit %,lld", hp->name, + len, size); + } + if (out < 0) + out = opennext(out, prefix); + /* write directory block */ + writetar(out, (char *)hp, Tblock); + outoff = passtar(hp, in, out, len); + } + return out; +} + +void +usage(void) +{ + fprint(2, "usage: %s [-p pfx] [-s size] [file]...\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + int out = -1; + + ARGBEGIN { + case 'p': + prefix = EARGF(usage()); + break; + case 's': + size = atoll(EARGF(usage())); + if (size < Tblock + Endsize) + sysfatal("implausible max size of %lld bytes", size); + break; + default: + usage(); + } ARGEND + + if (argc <= 0) + out = split(Stdin, out, "/fd/0"); + else + for (; argc-- > 0; argv++) { + int in = open(argv[0], OREAD); + + if (in < 0) + sysfatal("%s: %r", argv[0]); + out = split(in, out, argv[0]); + close(in); + } + closeout(out, filenm, 1); + exits(0); +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/tarsplit/tarsub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/tarsplit/tarsub.c Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,159 @@ +/* + * tar archive manipulation functions + */ + +#include +#include +#include +#include "tar.h" + +enum { + Blocksxfr = 32, +}; + +/* exports */ +char *thisnm, *lastnm; + +/* private data */ +static uvlong outoff = 0; /* maintained by newarch, writetar */ + +unsigned +checksum(Hblock *hp) +{ + int i; + uchar *cp, *csum, *end; + + i = ' ' * sizeof hp->chksum; /* pretend blank chksum field */ + csum = (uchar *)hp->chksum; + end = &hp->dummy[Tblock]; + /* + * Unixware gets this wrong; it adds *signed* chars. + * i += (Uflag? *(schar *)cp: *cp); + */ + for (cp = hp->dummy; cp < csum; ) + i += *cp++; + /* skip checksum field */ + for (cp += sizeof hp->chksum; cp < end; ) + i += *cp++; + return i; +} + +void +readtar(int in, char *buffer, long size) +{ + int i; + unsigned bytes; + + bytes = i = readn(in, buffer, size); + if (i <= 0) + sysfatal("archive read error: %r"); + if (bytes % Tblock != 0) + sysfatal("archive blocksize error"); + if (bytes != size) { + /* + * buffering would be screwed up by only partially + * filling tbuf, yet this might be the last (short) + * record in a tar disk archive, so just zero the rest. + */ + fprint(2, "%s: warning: short archive block\n", argv0); + memset(buffer + bytes, '\0', size - bytes); + } +} + +void +newarch(void) +{ + outoff = 0; +} + +uvlong +writetar(int outf, char *buffer, ulong size) +{ + if (write(outf, buffer, size) < size) { + fprint(2, "%s: archive write error: %r\n", argv0); + fprint(2, "%s: archive seek offset: %llud\n", argv0, outoff); + exits("write"); + } + outoff += size; + return outoff; +} + +ulong +otoi(char *s) +{ + int c; + ulong ul = 0; + + while (isascii(*s) && isspace(*s)) + s++; + while ((c = *s++) >= '0' && c <= '7') { + ul <<= 3; + ul |= c - '0'; + } + return ul; +} + +int +getdir(Hblock *hp, int in, vlong *lenp) +{ + *lenp = 0; + readtar(in, (char*)hp, Tblock); + if (hp->name[0] == '\0') { /* zero block indicates end-of-archive */ + lastnm = strdup(thisnm); + return 0; + } + *lenp = otoi(hp->size); + if (otoi(hp->chksum) != checksum(hp)) + sysfatal("directory checksum error"); + if (lastnm != nil) + free(lastnm); + lastnm = thisnm; + thisnm = strdup(hp->name); + return 1; +} + +uvlong +passtar(Hblock *hp, int in, int outf, vlong len) +{ + ulong bytes; + vlong off; + uvlong blks; + char bigbuf[Blocksxfr*Tblock]; /* 2*(8192 == MAXFDATA) */ + + off = outoff; + if (islink(hp->linkflag)) + return off; + for (blks = TAPEBLKS((uvlong)len); blks >= Blocksxfr; + blks -= Blocksxfr) { + readtar(in, bigbuf, sizeof bigbuf); + off = writetar(outf, bigbuf, sizeof bigbuf); + } + if (blks > 0) { + bytes = blks*Tblock; + readtar(in, bigbuf, bytes); + off = writetar(outf, bigbuf, bytes); + } + return off; +} + +void +putempty(int out) +{ + static char buf[Tblock]; + + writetar(out, buf, sizeof buf); +} + +/* emit zero blocks at end */ +int +closeout(int outf, char *, int prflag) +{ + if (outf < 0) + return -1; + putempty(outf); + putempty(outf); + if (lastnm && prflag) + fprint(2, " %s\n", lastnm); + close(outf); /* guaranteed to succeed on plan 9 */ + return -1; +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/troff/find --- a/sys/src/cmd/troff/find Tue Mar 06 23:32:10 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -grep $1 *.[ch] diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/unix/u9fs/u9fs.c --- a/sys/src/cmd/unix/u9fs/u9fs.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/unix/u9fs/u9fs.c Tue Mar 06 23:34:10 2012 +0100 @@ -401,6 +401,8 @@ seterror(tx, Eauth); return; } + if (none != nil) + rx->uname = none->name; } else { if((e = auth->attach(rx, tx)) != nil){ seterror(tx, e); @@ -1605,7 +1607,7 @@ return -1; } /* race */ - if(mkdir(npath, perm&0777) < 0){ + if(mkdir(npath, (perm|0400)&0777) < 0){ *ep = strerror(errno); free(npath); return -1; @@ -1759,6 +1761,8 @@ sysfatal("chroot '%s' failed", argv[0]); none = uname2user("none"); + if(none == nil) + none = uname2user("nobody"); serve(0, 1); return 0; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/upas/smtp/smtpd.c --- a/sys/src/cmd/upas/smtp/smtpd.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/upas/smtp/smtpd.c Tue Mar 06 23:34:10 2012 +0100 @@ -386,11 +386,11 @@ rdot = him; else rdot++; - if (cistrcmp(rdot, "localdomain") == 0 || + if (!trusted && (cistrcmp(rdot, "localdomain") == 0 || cistrcmp(rdot, "localhost") == 0 || cistrcmp(rdot, "example") == 0 || cistrcmp(rdot, "invalid") == 0 || - cistrcmp(rdot, "test") == 0) + cistrcmp(rdot, "test") == 0)) goto Liarliar; /* bad top-level domain */ /* check second-level RFC 2606 domains: example\.(com|net|org) */ if (rdot != him) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/disk/disk.c --- a/sys/src/cmd/usb/disk/disk.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/disk/disk.c Tue Mar 06 23:34:10 2012 +0100 @@ -9,6 +9,7 @@ #include #include #include +#include #include "scsireq.h" #include "usb.h" #include "usbfs.h" @@ -481,6 +482,13 @@ count = usbdirread(fs, q, data, count, offset, dirgen, nil); break; case Qctl: + /* + * Some usb disks need an extra opportunity to divulge their + * capacity (e.g. M-Systems/SanDisk 1GB flash drive). + */ + if(lun->lbsize <= 0) + umscapacity(lun); + s = buf; e = buf + sizeof(buf); if(lun->flags & Finqok) diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/disk/main.c --- a/sys/src/cmd/usb/disk/main.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/disk/main.c Tue Mar 06 23:34:10 2012 +0100 @@ -5,6 +5,7 @@ #include #include #include +#include #include "scsireq.h" #include "usb.h" #include "usbfs.h" diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/disk/scsireq.c --- a/sys/src/cmd/usb/disk/scsireq.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/disk/scsireq.c Tue Mar 06 23:34:10 2012 +0100 @@ -16,6 +16,7 @@ #include #include #include +#include #include "scsireq.h" enum { diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/disk/scsireq.h --- a/sys/src/cmd/usb/disk/scsireq.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/disk/scsireq.h Tue Mar 06 23:34:10 2012 +0100 @@ -77,68 +77,6 @@ Status_RO = 0x85, /* device is read-only */ }; -enum { /* SCSI command codes */ - ScmdTur = 0x00, /* test unit ready */ - ScmdRewind = 0x01, /* rezero/rewind */ - ScmdRsense = 0x03, /* request sense */ - ScmdFormat = 0x04, /* format unit */ - ScmdRblimits = 0x05, /* read block limits */ - ScmdRead = 0x08, /* read */ - ScmdWrite = 0x0A, /* write */ - ScmdSeek = 0x0B, /* seek */ - ScmdFmark = 0x10, /* write filemarks */ - ScmdSpace = 0x11, /* space forward/backward */ - ScmdInq = 0x12, /* inquiry */ - ScmdMselect6 = 0x15, /* mode select */ - ScmdMselect10 = 0x55, /* mode select */ - ScmdMsense6 = 0x1A, /* mode sense */ - ScmdMsense10 = 0x5A, /* mode sense */ - ScmdStart = 0x1B, /* start/stop unit */ - ScmdRcapacity = 0x25, /* read capacity */ - ScmdRcapacity16 = 0x9e, /* long read capacity */ - ScmdExtread = 0x28, /* extended read */ - ScmdExtwrite = 0x2A, /* extended write */ - ScmdExtseek = 0x2B, /* extended seek */ - - ScmdSynccache = 0x35, /* flush cache */ - ScmdRTOC = 0x43, /* read TOC data */ - ScmdRdiscinfo = 0x51, /* read disc information */ - ScmdRtrackinfo = 0x52, /* read track information */ - ScmdReserve = 0x53, /* reserve track */ - ScmdBlank = 0xA1, /* blank *-RW media */ - - ScmdCDpause = 0x4B, /* pause/resume */ - ScmdCDstop = 0x4E, /* stop play/scan */ - ScmdCDplay = 0xA5, /* play audio */ - ScmdCDload = 0xA6, /* load/unload */ - ScmdCDscan = 0xBA, /* fast forward/reverse */ - ScmdCDstatus = 0xBD, /* mechanism status */ - Scmdgetconf = 0x46, /* get configuration */ - - ScmdEInitialise = 0x07, /* initialise element status */ - ScmdMMove = 0xA5, /* move medium */ - ScmdEStatus = 0xB8, /* read element status */ - ScmdMExchange = 0xA6, /* exchange medium */ - ScmdEposition = 0x2B, /* position to element */ - - ScmdReadDVD = 0xAD, /* read dvd structure */ - ScmdReportKey = 0xA4, /* read dvd key */ - ScmdSendKey = 0xA3, /* write dvd key */ - - ScmdClosetracksess= 0x5B, - ScmdRead12 = 0xA8, - ScmdSetcdspeed = 0xBB, - ScmdReadcd = 0xBE, - - /* vendor-specific */ - ScmdFwaddr = 0xE2, /* first writeable address */ - ScmdTreserve = 0xE4, /* reserve track */ - ScmdTinfo = 0xE5, /* read track info */ - ScmdTwrite = 0xE6, /* write track */ - ScmdMload = 0xE7, /* medium load/unload */ - ScmdFixation = 0xE9, /* fixation */ -}; - enum { /* sense data byte 0 */ Sd0valid = 0x80, /* valid sense data present */ diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/ether/ether.c --- a/sys/src/cmd/usb/ether/ether.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/ether/ether.c Tue Mar 06 23:34:10 2012 +0100 @@ -47,31 +47,32 @@ Cinfo cinfo[] = { /* Asix controllers. - * Only A88178 and A881772 are implemented. + * Only A88178 and A88772 are implemented. * Others are easy to add by borrowing code * from other systems. */ + {0x0411, 0x003d, A8817x}, /* buffalo */ + {0x0411, 0x006e, A88178}, + {0x04f1, 0x3008, A8817x}, + {0x050d, 0x5055, A88178}, + {0x0557, 0x2009, A8817x}, + {0x05ac, 0x1402, A88772}, /* Apple */ {0x077b, 0x2226, A8817x}, - {0x0b95, 0x1720, A8817x}, - {0x0557, 0x2009, A8817x}, - {0x0411, 0x003d, A8817x}, - {0x0411, 0x006e, A88178}, + {0x07aa, 0x0017, A8817x}, + {0x07d1, 0x3c05, A88772}, + {0x0b95, 0x1720, A8817x}, /* asix */ + {0x0b95, 0x1780, A88178}, /* Geoff */ + {0x0b95, 0x7720, A88772}, + {0x0b95, 0x772a, A88772}, + {0x0db0, 0xa877, A88772}, + {0x1189, 0x0893, A8817x}, + {0x13b1, 0x0018, A88772}, + {0x14ea, 0xab11, A88178}, + {0x1557, 0x7720, A88772}, + {0x1631, 0x6200, A8817x}, + {0x1737, 0x0039, A88178}, + {0x2001, 0x3c05, A88772}, {0x6189, 0x182d, A8817x}, - {0x07aa, 0x0017, A8817x}, - {0x1189, 0x0893, A8817x}, - {0x1631, 0x6200, A8817x}, - {0x04f1, 0x3008, A8817x}, - {0x0b95, 0x1780, A88178}, /* Geoff */ - {0x13b1, 0x0018, A88772}, - {0x1557, 0x7720, A88772}, - {0x07d1, 0x3c05, A88772}, - {0x2001, 0x3c05, A88772}, - {0x1737, 0x0039, A88178}, - {0x050d, 0x5055, A88178}, - {0x05ac, 0x1402, A88772}, /* Apple */ - {0x0b95, 0x772a, A88772}, - {0x14ea, 0xab11, A88178}, - {0x0db0, 0xa877, A88772}, {0, 0, 0}, }; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/kb/hid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sys/src/cmd/usb/kb/hid.c Tue Mar 06 23:34:10 2012 +0100 @@ -0,0 +1,199 @@ +#include +#include +#include +#include "usb.h" +#include "hid.h" + +/* + * Rough hid descriptor parsing and interpretation for mice + * + * Chain and its operations build the infrastructure needed + * to manipulate non-aligned fields, which do appear (sigh!). + */ + +/* Get, at most, 8 bits*/ +static uchar +get8bits(Chain *ch, int nbits) +{ + int b, nbyb, nbib, nlb; + uchar low, high; + + b = ch->b + nbits - 1; + nbib = ch->b % 8; + nbyb = ch->b / 8; + nlb = 8 - nbib; + if(nlb > nbits) + nlb = nbits; + + low = MSK(nlb) & (ch->buf[nbyb] >> nbib); + if(IsCut(ch->b, b)) + high = (ch->buf[nbyb + 1] & MSK(nbib)) << nlb; + else + high = 0; + ch->b += nbits; + return high | low; +} + +static void +getbits(void *p, Chain *ch, int nbits) +{ + int nby, nbi, i; + uchar *vp; + + assert(ch->e >= ch->b); + nby = nbits / 8; + nbi = nbits % 8; + + vp = p; + for(i = 0; i < nby; i++) + *vp++ = get8bits(ch, 8); + + if(nbi != 0) + *vp = get8bits(ch, nbi); +} + +/* TODO check report id, when it does appear (not all devices) */ +int +parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz) +{ + int i, j, l, n, isptr, hasxy, hasbut, nk; + int ks[MaxVals]; + HidInterface *ifs; + + ifs = temp->ifcs; + isptr = 0; + hasxy = hasbut = 0; + n = 0; + nk = 0; + memset(ifs, 0, sizeof *ifs * MaxIfc); + for(i = 0; i < repsz / 2; i += 2){ + if(n == MaxIfc || repdesc[i] == HidEnd) + break; + + switch(repdesc[i]){ + case HidTypeUsg: + switch(repdesc[i+1]){ + case HidX: + hasxy++; + ks[nk++] = KindX; + break; + case HidY: + hasxy++; + ks[nk++] = KindY; + break; + case HidWheel: + ks[nk++] = KindWheel; + break; + case HidPtr: + isptr++; + break; + } + break; + case HidTypeUsgPg: + switch(repdesc[i+1]){ + case HidPgButts: + hasbut++; + ks[nk++] = KindButtons; + break; + } + break; + case HidTypeRepSz: + ifs[n].nbits = repdesc[i+1]; + break; + case HidTypeCnt: + ifs[n].count = repdesc[i+1]; + break; + case HidInput: + for(j = 0; j nifcs = n; + if(isptr && hasxy && hasbut) + return 0; + fprint(2, "bad report: isptr %d, hasxy %d, hasbut %d\n", + isptr, hasxy, hasbut); + return -1; +} + +int +parsereport(HidRepTempl *templ, Chain *rep) +{ + int i, j, k, ifssz; + ulong u; + uchar *p; + HidInterface *ifs; + + ifssz = templ->nifcs; + ifs = templ->ifcs; + for(i = 0; i < ifssz; i++) + for(j = 0; j < ifs[i].count; j++){ + if(ifs[i].nbits > 8 * sizeof ifs[i].v[0]){ + fprint(2, "ptr: bad bits in parsereport"); + return -1; + } + u =0; + getbits(&u, rep, ifs[i].nbits); + p = (uchar *)&u; + /* le to host */ + ifs[i].v[j] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]<<0; + k = ifs[i].kind[j]; + if(k == KindX || k == KindY || k == KindWheel){ + /* propagate sign */ + if(ifs[i].v[j] & (1 << (ifs[i].nbits - 1))) + ifs[i].v[j] |= ~MSK(ifs[i].nbits); + } + } + return 0; +} + +/* TODO: fmt representation */ +void +dumpreport(HidRepTempl *templ) +{ + int i, j, ifssz; + HidInterface *ifs; + + ifssz = templ->nifcs; + ifs = templ->ifcs; + for(i = 0; i < ifssz; i++){ + fprint(2, "\tcount %#ux", ifs[i].count); + fprint(2, " nbits %d ", ifs[i].nbits); + fprint(2, "\n"); + for(j = 0; j < ifs[i].count; j++){ + fprint(2, "\t\tkind %#ux ", ifs[i].kind[j]); + fprint(2, "v %#lux\n", ifs[i].v[j]); + } + fprint(2, "\n"); + } + fprint(2, "\n"); +} + +/* could precalculate indices after parsing the descriptor */ +int +hidifcval(HidRepTempl *templ, int kind, int n) +{ + int i, j, ifssz; + HidInterface *ifs; + + ifssz = templ->nifcs; + ifs = templ->ifcs; + assert(n <= nelem(ifs[i].v)); + for(i = 0; i < ifssz; i++) + for(j = 0; j < ifs[i].count; j++) + if(ifs[i].kind[j] == kind && n-- == 0) + return (int)ifs[i].v[j]; + return 0; /* least damage (no buttons, no movement) */ +} diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/kb/hid.h --- a/sys/src/cmd/usb/kb/hid.h Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/kb/hid.h Tue Mar 06 23:34:10 2012 +0100 @@ -1,8 +1,12 @@ /* * USB keyboard/mouse constants */ + +typedef struct Chain Chain; +typedef struct HidInterface HidInterface; +typedef struct HidRepTempl HidRepTempl; + enum { - Stack = 32 * 1024, /* HID class subclass protocol ids */ @@ -11,6 +15,7 @@ /* Requests */ Getproto = 0x03, + Setidle = 0x0a, Setproto = 0x0b, /* protocols for SET_PROTO request */ @@ -39,7 +44,6 @@ MaxAcc = 3, /* max. ptr acceleration */ PtrMask= 0xf, /* 4 buttons: should allow for more. */ - }; /* @@ -49,8 +53,8 @@ /* Scan codes (see kbd.c) */ SCesc1 = 0xe0, /* first of a 2-character sequence */ SCesc2 = 0xe1, - SClshift = 0x2a, - SCrshift = 0x36, + SClshift = 0x2a, + SCrshift = 0x36, SCctrl = 0x1d, SCcompose = 0x38, Keyup = 0x80, /* flag bit */ @@ -58,3 +62,64 @@ }; int kbmain(Dev *d, int argc, char*argv[]); + +enum{ + MaxChLen = 16, /* bytes */ +}; + +struct Chain { + int b; /* offset start in bits, (first full) */ + int e; /* offset end in bits (first empty) */ + uchar buf[MaxChLen]; +}; + +#define MSK(nbits) ((1UL << (nbits)) - 1) +#define IsCut(bbits, ebits) (((ebits)/8 - (bbits)/8) > 0) + +enum { + KindPad = 0, + KindButtons, + KindX, + KindY, + KindWheel, + + MaxVals = 8, + MaxIfc = 8, +}; + +struct HidInterface { + ulong v[MaxVals]; /* one ulong per val should be enough */ + int kind[MaxVals]; + int nbits; + int count; +}; + +struct HidRepTempl{ + int nifcs; + HidInterface ifcs[MaxIfc]; +}; + +enum { + /* report types */ + HidTypeUsgPg = 0x05, + HidPgButts = 0x09, + + HidTypeRepSz = 0x75, + HidTypeCnt = 0x95, + + HidTypeUsg = 0x09, + HidPtr = 0x01, + HidX = 0x30, + HidY = 0x31, + HidWheel = 0x38, + + HidInput = 0x81, + HidReportId = 0x85, + + HidEnd = 0x0c, +}; + +void dumpreport(HidRepTempl *templ); +int hidifcval(HidRepTempl *templ, int kind, int n); +int parsereport(HidRepTempl *templ, Chain *rep); +int parsereportdesc(HidRepTempl *temp, uchar *repdesc, int repsz); diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/kb/kb.c --- a/sys/src/cmd/usb/kb/kb.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/kb/kb.c Tue Mar 06 23:34:10 2012 +0100 @@ -4,10 +4,11 @@ * If there's no usb keyboard, it tries to setup the mouse, if any. * It should be started at boot time. * - * Mouse events are converted to the format of mouse(3)'s - * mousein file. + * Mouse events are converted to the format of mouse(3)'s mousein file. * Keyboard keycodes are translated to scan codes and sent to kbin(3). * + * If there is no keyboard, it tries to setup the mouse properly, else it falls + * back to boot protocol. */ #include @@ -18,8 +19,8 @@ enum { - Awakemsg=0xdeaddead, - Diemsg = 0xbeefbeef, + Awakemsg= 0xdeaddead, + Diemsg = 0xbeefbeef, }; typedef struct KDev KDev; @@ -32,6 +33,9 @@ Kin* in; /* used to send events to kernel */ Channel*repeatc; /* only for keyboard */ int accel; /* only for mouse */ + int bootp; /* has associated keyboard */ + HidRepTempl templ; + int (*ptrvals)(KDev *kd, Chain *ch, int *px, int *py, int *pb); }; /* @@ -62,7 +66,7 @@ * key code to scan code; for the page table used by * the logitech bluetooth keyboard. */ -static char sctab[256] = +static char sctab[256] = { [0x00] 0x0, 0x0, 0x0, 0x0, 0x1e, 0x30, 0x2e, 0x20, [0x08] 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, @@ -114,16 +118,59 @@ static int kbdebug; +static int ptrbootpvals(KDev *kd, Chain *ch, int *px, int *py, int *pb); +static int ptrrepvals(KDev *kd, Chain *ch, int *px, int *py, int *pb); + static int -setbootproto(KDev* f, int eid) +setbootproto(KDev* f, int eid, uchar *, int) { int r, id; + f->ptrvals = ptrbootpvals; r = Rh2d|Rclass|Riface; + dprint(2, "setting boot protocol\n"); id = f->dev->usb->ep[eid]->iface->id; return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0); } +static uchar ignoredesc[128]; + +static int +setfirstconfig(KDev* f, int eid, uchar *desc, int descsz) +{ + int nr, r, id, i; + + dprint(2, "setting first config\n"); + if(desc == nil){ + descsz = sizeof ignoredesc; + desc = ignoredesc; + } + id = f->dev->usb->ep[eid]->iface->id; + r = Rh2d | Rstd | Rdev; + nr =usbcmd(f->dev, r, Rsetconf, 1, id, nil, 0); + if(nr < 0) + return -1; + r = Rh2d | Rclass | Riface; + nr=usbcmd(f->dev, r, Setidle, 0, id, nil, 0); + if(nr < 0) + return -1; + r = Rd2h | Rstd | Riface; + nr=usbcmd(f->dev, r, Rgetdesc, Dreport<<8, id, desc, descsz); + if(nr < 0) + return -1; + if(kbdebug && nr > 0){ + fprint(2, "report descriptor:"); + for(i = 0; i < nr; i++){ + if(i%8 == 0) + fprint(2, "\n\t"); + fprint(2, "%#2.2ux ", desc[i]); + } + fprint(2, "\n"); + } + f->ptrvals = ptrrepvals; + return nr; +} + /* * Try to recover from a babble error. A port reset is the only way out. * BUG: we should be careful not to reset a bundle with several devices. @@ -136,9 +183,15 @@ close(f->dev->dfd); /* it's for usbd now */ devctl(f->dev, "reset"); for(i = 0; i < 10; i++){ + if(i == 5) + f->bootp++; sleep(500); if(opendevdata(f->dev, ORDWR) >= 0){ - setbootproto(f, f->ep->id); + if(f->bootp) + /* TODO func pointer */ + setbootproto(f, f->ep->id, nil, 0); + else + setfirstconfig(f, f->ep->id, nil, 0); break; } /* else usbd still working... */ @@ -207,36 +260,85 @@ char fn[30]; int fd; - snprint(fn, sizeof(fn), "/proc/%d/ctl", getpid()); + snprint(fn, sizeof fn, "/proc/%d/ctl", getpid()); fd = open(fn, OWRITE); - if(fd < 0) - return; - fprint(fd, "pri 13"); - close(fd); + if(fd >= 0) { + fprint(fd, "pri 13"); + close(fd); + } +} + +static int +ptrrepvals(KDev *kd, Chain *ch, int *px, int *py, int *pb) +{ + int i, x, y, b, c; + static char buts[] = {0x0, 0x2, 0x1}; + + c = ch->e / 8; + parsereport(&kd->templ, ch); + + if(kbdebug) + dumpreport(&kd->templ); + if(c < 3) + return -1; + x = hidifcval(&kd->templ, KindX, 0); + y = hidifcval(&kd->templ, KindY, 0); + b = 0; + for(i = 0; itempl, KindButtons, i) & 1) << buts[i]; + if(c > 3 && hidifcval(&kd->templ, KindWheel, 0) > 0) /* up */ + b |= 0x10; + if(c > 3 && hidifcval(&kd->templ, KindWheel, 0) < 0) /* down */ + b |= 0x08; + + *px = x; + *py = y; + *pb = b; + return 0; +} + +static int +ptrbootpvals(KDev *kd, Chain *ch, int *px, int *py, int *pb) +{ + int b, c; + char x, y; + static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7}; + + c = ch->e / 8; + if(c < 3) + return -1; + x = hidifcval(&kd->templ, KindX, 0); + y = hidifcval(&kd->templ, KindY, 0); + + b = maptab[ch->buf[0] & 0x7]; + if(c > 3 && ch->buf[3] == 1) /* up */ + b |= 0x08; + if(c > 3 && ch->buf[3] == 0xff) /* down */ + b |= 0x10; + *px = x; + *py = y; + *pb = b; + return 0; } static void ptrwork(void* a) { - static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7}; - int x, y, b, c, ptrfd; - int mfd, nerrs; - char buf[32]; - char mbuf[80]; - KDev* f = a; - int hipri; + int hipri, mfd, nerrs, x, y, b, c, ptrfd; + char mbuf[80]; + Chain ch; + KDev* f = a; hipri = nerrs = 0; ptrfd = f->ep->dfd; mfd = f->in->fd; - - if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf) + if(f->ep->maxpkt < 3 || f->ep->maxpkt > MaxChLen) kbfatal(f, "weird mouse maxpkt"); for(;;){ - memset(buf, 0, sizeof buf); + memset(ch.buf, 0, MaxChLen); if(f->ep == nil) kbfatal(f, nil); - c = read(ptrfd, buf, f->ep->maxpkt); + c = read(ptrfd, ch.buf, f->ep->maxpkt); assert(f->dev != nil); assert(f->ep != nil); if(c < 0){ @@ -248,20 +350,15 @@ } if(c <= 0) kbfatal(f, nil); - if(c < 3) + ch.b = 0; + ch.e = 8 * c; + if(f->ptrvals(f, &ch, &x, &y, &b) < 0) continue; + if(f->accel){ - x = scale(f, buf[1]); - y = scale(f, buf[2]); - }else{ - x = buf[1]; - y = buf[2]; + x = scale(f, x); + y = scale(f, y); } - b = maptab[buf[0] & 0x7]; - if(c > 3 && buf[3] == 1) /* up */ - b |= 0x08; - if(c > 3 && buf[3] == -1) /* down */ - b |= 0x10; if(kbdebug > 1) fprint(2, "kb: m%11d %11d %11d\n", x, y, b); seprint(mbuf, mbuf+sizeof(mbuf), "m%11d %11d %11d", x, y,b); @@ -502,9 +599,10 @@ } static void -kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), int accel) +kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), KDev *kd) { - KDev *kd; + uchar desc[128]; + int res; qlock(&inlck); if(in->fd < 0){ @@ -517,15 +615,23 @@ } in->ref++; /* for kd->in = in */ qunlock(&inlck); - kd = d->aux = emallocz(sizeof(KDev), 1); d->free = freekdev; kd->in = in; kd->dev = d; - if(setbootproto(kd, ep->id) < 0){ - fprint(2, "kb: %s: bootproto: %r\n", d->dir); - return; - } - kd->accel = accel; + res = -1; + if(!kd->bootp) + res= setfirstconfig(kd, ep->id, desc, sizeof desc); + if(res > 0) + res = parsereportdesc(&kd->templ, desc, sizeof desc); + /* if we could not set the first config, we give up */ + if(kd->bootp || res < 0){ + kd->bootp = 1; + if(setbootproto(kd, ep->id, nil, 0) < 0){ + fprint(2, "kb: %s: bootproto: %r\n", d->dir); + return; + } + }else if(kbdebug) + dumpreport(&kd->templ); kd->ep = openep(d, ep->id); if(kd->ep == nil){ fprint(2, "kb: %s: openep %d: %r\n", d->dir, ep->id); @@ -545,18 +651,20 @@ static int usage(void) { - werrstr("usage: usb/kb [-dkm] [-a n] [-N nb]"); + werrstr("usage: usb/kb [-bdkm] [-a n] [-N nb]"); return -1; } int kbmain(Dev *d, int argc, char* argv[]) { - int i, kena, pena, accel, devid; + int bootp, i, kena, pena, accel, devid; + Ep *ep; + KDev *kd; Usbdev *ud; - Ep *ep; kena = pena = 1; + bootp = 0; accel = 0; devid = d->id; ARGBEGIN{ @@ -577,25 +685,43 @@ case 'N': devid = atoi(EARGF(usage())); /* ignore dev number */ break; + case 'b': + bootp++; + break; default: return usage(); }ARGEND; - if(argc != 0){ + if(argc != 0) return usage(); - } USED(devid); ud = d->usb; d->aux = nil; dprint(2, "kb: main: dev %s ref %ld\n", d->dir, d->ref); + + if(kena) + for(i = 0; i < nelem(ud->ep); i++) + if((ep = ud->ep[i]) == nil) + break; + else if(ep->iface->csp == KbdCSP) + bootp = 1; + for(i = 0; i < nelem(ud->ep); i++){ if((ep = ud->ep[i]) == nil) break; - if(kena && ep->type == Eintr && ep->dir == Ein) - if(ep->iface->csp == KbdCSP) - kbstart(d, ep, &kbdin, kbdwork, accel); - if(pena && ep->type == Eintr && ep->dir == Ein) - if(ep->iface->csp == PtrCSP) - kbstart(d, ep, &ptrin, ptrwork, accel); + if(kena && ep->type == Eintr && ep->dir == Ein && + ep->iface->csp == KbdCSP){ + kd = d->aux = emallocz(sizeof(KDev), 1); + kd->accel = 0; + kd->bootp = 1; + kbstart(d, ep, &kbdin, kbdwork, kd); + } + if(pena && ep->type == Eintr && ep->dir == Ein && + ep->iface->csp == PtrCSP){ + kd = d->aux = emallocz(sizeof(KDev), 1); + kd->accel = accel; + kd->bootp = bootp; + kbstart(d, ep, &ptrin, ptrwork, kd); + } } return 0; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/kb/main.c --- a/sys/src/cmd/usb/kb/main.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/kb/main.c Tue Mar 06 23:34:10 2012 +0100 @@ -16,7 +16,7 @@ static void usage(void) { - fprint(2, "usage: %s [-dkm] [-a n] [-N nb] [dev...]\n", argv0); + fprint(2, "usage: %s [-bdkm] [-a n] [-N nb] [dev...]\n", argv0); threadexitsall("usage"); } @@ -53,6 +53,9 @@ devid = atoi(EARGF(usage())); /* ignore dev number */ USED(devid); break; + case 'b': + as = seprint(as, ae, " -b"); + break; default: usage(); }ARGEND; diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/kb/mkfile --- a/sys/src/cmd/usb/kb/mkfile Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/kb/mkfile Tue Mar 06 23:34:10 2012 +0100 @@ -2,7 +2,9 @@ TARG=kb OFILES=main.$O -LIBDOFILES=kb.$O +LIBDOFILES=kb.$O\ + hid.$O + HFILES=\ ../lib/usb.h\ hid.h\ diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/usb/serial/serial.c --- a/sys/src/cmd/usb/serial/serial.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/usb/serial/serial.c Tue Mar 06 23:34:10 2012 +0100 @@ -542,13 +542,11 @@ count = rcount; break; case Qctl: - if(offset != 0) + if(offset != 0 || p->isjtag) count = 0; else { - if(!p->isjtag){ - e = serdumpst(p, buf, Serbufsize); - count = usbreadbuf(data, count, 0, buf, e - buf); - } + e = serdumpst(p, buf, Serbufsize); + count = usbreadbuf(data, count, 0, buf, e - buf); } break; } diff -r dbb1bddf6759 -r 5f9e0e495d43 sys/src/cmd/vac/file.c --- a/sys/src/cmd/vac/file.c Tue Mar 06 23:32:10 2012 +0100 +++ b/sys/src/cmd/vac/file.c Tue Mar 06 23:34:10 2012 +0100 @@ -1594,6 +1594,11 @@ f->dir.gid = vtstrdup(dir->gid); } + if(strcmp(f->dir.mid, dir->mid) != 0){ + vtfree(f->dir.mid); + f->dir.mid = vtstrdup(dir->mid); + } + f->dir.mtime = dir->mtime; f->dir.atime = dir->atime; @@ -1776,7 +1781,7 @@ char *prefix; if(vtparsescore(file, &prefix, score) >= 0){ - if(strcmp(prefix, "vac") != 0){ + if(prefix == nil || strcmp(prefix, "vac") != 0){ werrstr("not a vac file"); return nil; }