1*219b2ee8SDavid du Colombier#define NBUFS 2 2*219b2ee8SDavid du Colombier#define READMAX 2 3*219b2ee8SDavid du Colombier#define BUFSIZ 2*READMAX 4*219b2ee8SDavid du Colombier#define EOF 255 5*219b2ee8SDavid du Colombier#define TIMEOUT 254 6*219b2ee8SDavid du Colombier#define FILEMAXLEN 20 7*219b2ee8SDavid du Colombier 8*219b2ee8SDavid du Colombierbyte n[NBUFS]; 9*219b2ee8SDavid du Colombierbyte ntotal[NBUFS]; 10*219b2ee8SDavid du Colombierbyte putnext[NBUFS]; 11*219b2ee8SDavid du Colombierbyte getnext[NBUFS]; 12*219b2ee8SDavid du Colombierbool eof[NBUFS]; 13*219b2ee8SDavid du Colombierbool roomwait[NBUFS]; 14*219b2ee8SDavid du Colombierbool datawait[NBUFS]; 15*219b2ee8SDavid du Colombierbyte rwant; 16*219b2ee8SDavid du Colombier 17*219b2ee8SDavid du Colombier/* use one big data array to simulate 2-d array */ 18*219b2ee8SDavid du Colombier#define bufstart(slot) (slot*BUFSIZ) 19*219b2ee8SDavid du Colombier#define bufend(slot) ((slot+1)*BUFSIZ) 20*219b2ee8SDavid du Colombier/* bit data[BUFSIZ*NBUFS]; */ 21*219b2ee8SDavid du Colombier 22*219b2ee8SDavid du Colombierbool selwait; 23*219b2ee8SDavid du Colombier/* bool hastimeout; */ 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier#define get 0 26*219b2ee8SDavid du Colombier#define release 1 27*219b2ee8SDavid du Colombier 28*219b2ee8SDavid du Colombierchan lock = [0] of { bit }; 29*219b2ee8SDavid du Colombierchan lockkill = [0] of { bit }; 30*219b2ee8SDavid du Colombierchan sel = [0] of { byte }; 31*219b2ee8SDavid du Colombierchan selcall = [0] of { byte }; 32*219b2ee8SDavid du Colombierchan selans = [0] of { byte, byte }; 33*219b2ee8SDavid du Colombierchan selkill = [0] of { bit }; 34*219b2ee8SDavid du Colombierchan readcall = [0] of { byte, byte }; 35*219b2ee8SDavid du Colombierchan readans = [0] of { byte }; 36*219b2ee8SDavid du Colombierchan readkill = [0] of { bit }; 37*219b2ee8SDavid du Colombierchan croom[NBUFS] = [0] of { bit }; 38*219b2ee8SDavid du Colombierchan cdata[NBUFS] = [0] of { bit }; 39*219b2ee8SDavid du Colombier 40*219b2ee8SDavid du Colombierproctype Lockrendez() 41*219b2ee8SDavid du Colombier{ 42*219b2ee8SDavid du Colombier do 43*219b2ee8SDavid du Colombier :: lock!get -> lock?release 44*219b2ee8SDavid du Colombier :: lockkill?release -> break 45*219b2ee8SDavid du Colombier od 46*219b2ee8SDavid du Colombier} 47*219b2ee8SDavid du Colombier 48*219b2ee8SDavid du Colombierproctype Copy(byte fd) 49*219b2ee8SDavid du Colombier{ 50*219b2ee8SDavid du Colombier byte num; 51*219b2ee8SDavid du Colombier bit b; 52*219b2ee8SDavid du Colombier 53*219b2ee8SDavid du Colombier do :: 1 -> 54*219b2ee8SDavid du Colombier /* make sure there's room */ 55*219b2ee8SDavid du Colombier lock?get; 56*219b2ee8SDavid du Colombier if 57*219b2ee8SDavid du Colombier :: (BUFSIZ-putnext[fd]) < READMAX -> 58*219b2ee8SDavid du Colombier if 59*219b2ee8SDavid du Colombier :: getnext[fd] == putnext[fd] -> 60*219b2ee8SDavid du Colombier getnext[fd] = 0; 61*219b2ee8SDavid du Colombier putnext[fd] = 0; 62*219b2ee8SDavid du Colombier lock!release 63*219b2ee8SDavid du Colombier :: getnext[fd] != putnext[fd] -> 64*219b2ee8SDavid du Colombier roomwait[fd] = 1; 65*219b2ee8SDavid du Colombier lock!release; 66*219b2ee8SDavid du Colombier croom[fd]?b 67*219b2ee8SDavid du Colombier fi 68*219b2ee8SDavid du Colombier :: (BUFSIZ-putnext[fd]) >= READMAX -> 69*219b2ee8SDavid du Colombier lock!release 70*219b2ee8SDavid du Colombier fi; 71*219b2ee8SDavid du Colombier /* simulate read into data buf at putnext */ 72*219b2ee8SDavid du Colombier if 73*219b2ee8SDavid du Colombier :: ntotal[fd] > FILEMAXLEN -> 74*219b2ee8SDavid du Colombier num = EOF 75*219b2ee8SDavid du Colombier :: ntotal[fd] <= FILEMAXLEN -> 76*219b2ee8SDavid du Colombier if 77*219b2ee8SDavid du Colombier :: num = 1 78*219b2ee8SDavid du Colombier :: num = READMAX 79*219b2ee8SDavid du Colombier :: num = EOF 80*219b2ee8SDavid du Colombier fi 81*219b2ee8SDavid du Colombier fi; 82*219b2ee8SDavid du Colombier /* here is where data transfer would happen */ 83*219b2ee8SDavid du Colombier lock?get; 84*219b2ee8SDavid du Colombier if 85*219b2ee8SDavid du Colombier :: num == EOF -> 86*219b2ee8SDavid du Colombier eof[fd] = 1; 87*219b2ee8SDavid du Colombier/* printf("Copy %d got eof\n", fd);/**/ 88*219b2ee8SDavid du Colombier if 89*219b2ee8SDavid du Colombier :: datawait[fd] -> 90*219b2ee8SDavid du Colombier datawait[fd] = 0; 91*219b2ee8SDavid du Colombier lock!release; 92*219b2ee8SDavid du Colombier cdata[fd]!1 93*219b2ee8SDavid du Colombier :: !datawait[fd] && (rwant & (1<<fd)) && selwait -> 94*219b2ee8SDavid du Colombier selwait = 0; 95*219b2ee8SDavid du Colombier lock!release; 96*219b2ee8SDavid du Colombier sel!fd 97*219b2ee8SDavid du Colombier :: !datawait[fd] && !((rwant & (1<<fd)) && selwait) -> 98*219b2ee8SDavid du Colombier lock!release 99*219b2ee8SDavid du Colombier fi; 100*219b2ee8SDavid du Colombier break 101*219b2ee8SDavid du Colombier :: num != EOF -> 102*219b2ee8SDavid du Colombier/* printf("Copy %d putting %d in; old putnext=%d, old n=%d\n", fd, num, putnext[fd], n[fd]); /* */ 103*219b2ee8SDavid du Colombier putnext[fd] = putnext[fd] + num; 104*219b2ee8SDavid du Colombier n[fd] = n[fd] + num; 105*219b2ee8SDavid du Colombier ntotal[fd] = ntotal[fd] + num; 106*219b2ee8SDavid du Colombier assert(n[fd] > 0); 107*219b2ee8SDavid du Colombier if 108*219b2ee8SDavid du Colombier :: datawait[fd] -> 109*219b2ee8SDavid du Colombier datawait[fd] = 0; 110*219b2ee8SDavid du Colombier lock!release; 111*219b2ee8SDavid du Colombier cdata[fd]!1 112*219b2ee8SDavid du Colombier :: !datawait[fd] && (rwant & (1<<fd)) && selwait -> 113*219b2ee8SDavid du Colombier selwait = 0; 114*219b2ee8SDavid du Colombier lock!release; 115*219b2ee8SDavid du Colombier sel!fd 116*219b2ee8SDavid du Colombier :: !datawait[fd] && !((rwant & (1<<fd)) && selwait) -> 117*219b2ee8SDavid du Colombier lock!release 118*219b2ee8SDavid du Colombier fi 119*219b2ee8SDavid du Colombier fi; 120*219b2ee8SDavid du Colombier od 121*219b2ee8SDavid du Colombier} 122*219b2ee8SDavid du Colombier 123*219b2ee8SDavid du Colombierproctype Read() 124*219b2ee8SDavid du Colombier{ 125*219b2ee8SDavid du Colombier byte ngot; 126*219b2ee8SDavid du Colombier byte fd; 127*219b2ee8SDavid du Colombier byte nwant; 128*219b2ee8SDavid du Colombier bit b; 129*219b2ee8SDavid du Colombier 130*219b2ee8SDavid du Colombier do 131*219b2ee8SDavid du Colombier :: readcall?fd,nwant -> 132*219b2ee8SDavid du Colombier if 133*219b2ee8SDavid du Colombier :: eof[fd] && n[fd] == 0 -> 134*219b2ee8SDavid du Colombier readans!EOF 135*219b2ee8SDavid du Colombier :: !(eof[fd] && n[fd] == 0) -> 136*219b2ee8SDavid du Colombier lock?get; 137*219b2ee8SDavid du Colombier ngot = putnext[fd] - getnext[fd]; 138*219b2ee8SDavid du Colombier/* printf("Reading %d, want %d: ngot = %d - %d, n = %d\n", fd, nwant, putnext[fd], getnext[fd], n[fd]); /* */ 139*219b2ee8SDavid du Colombier if 140*219b2ee8SDavid du Colombier :: ngot == 0 -> 141*219b2ee8SDavid du Colombier if 142*219b2ee8SDavid du Colombier :: eof[fd] -> 143*219b2ee8SDavid du Colombier skip 144*219b2ee8SDavid du Colombier :: !eof[fd] -> 145*219b2ee8SDavid du Colombier /* sleep until there's data */ 146*219b2ee8SDavid du Colombier datawait[fd] = 1; 147*219b2ee8SDavid du Colombier/* printf("Read sleeping\n"); /* */ 148*219b2ee8SDavid du Colombier lock!release; 149*219b2ee8SDavid du Colombier cdata[fd]?b; 150*219b2ee8SDavid du Colombier lock?get; 151*219b2ee8SDavid du Colombier ngot = putnext[fd] - getnext[fd]; 152*219b2ee8SDavid du Colombier/* printf("Read awoke, ngot = %d\n", ngot); /**/ 153*219b2ee8SDavid du Colombier fi 154*219b2ee8SDavid du Colombier :: ngot != 0 -> skip 155*219b2ee8SDavid du Colombier fi; 156*219b2ee8SDavid du Colombier if 157*219b2ee8SDavid du Colombier :: ngot > nwant -> ngot = nwant 158*219b2ee8SDavid du Colombier :: ngot <= nwant -> skip 159*219b2ee8SDavid du Colombier fi; 160*219b2ee8SDavid du Colombier /* here would take ngot elements from data, from getnext[fd] ... */ 161*219b2ee8SDavid du Colombier getnext[fd] = getnext[fd] + ngot; 162*219b2ee8SDavid du Colombier assert(n[fd] >= ngot); 163*219b2ee8SDavid du Colombier n[fd] = n[fd] - ngot; 164*219b2ee8SDavid du Colombier if 165*219b2ee8SDavid du Colombier :: ngot == 0 -> 166*219b2ee8SDavid du Colombier assert(eof[fd]); 167*219b2ee8SDavid du Colombier ngot = EOF 168*219b2ee8SDavid du Colombier :: ngot != 0 -> skip 169*219b2ee8SDavid du Colombier fi; 170*219b2ee8SDavid du Colombier if 171*219b2ee8SDavid du Colombier :: getnext[fd] == putnext[fd] && roomwait[fd] -> 172*219b2ee8SDavid du Colombier getnext[fd] = 0; 173*219b2ee8SDavid du Colombier putnext[fd] = 0; 174*219b2ee8SDavid du Colombier roomwait[fd] = 0; 175*219b2ee8SDavid du Colombier lock!release; 176*219b2ee8SDavid du Colombier croom[fd]!0 177*219b2ee8SDavid du Colombier :: getnext[fd] != putnext[fd] || !roomwait[fd] -> 178*219b2ee8SDavid du Colombier lock!release 179*219b2ee8SDavid du Colombier fi; 180*219b2ee8SDavid du Colombier readans!ngot 181*219b2ee8SDavid du Colombier fi 182*219b2ee8SDavid du Colombier :: readkill?b -> break 183*219b2ee8SDavid du Colombier od 184*219b2ee8SDavid du Colombier} 185*219b2ee8SDavid du Colombier 186*219b2ee8SDavid du Colombierproctype Select() 187*219b2ee8SDavid du Colombier{ 188*219b2ee8SDavid du Colombier byte num; 189*219b2ee8SDavid du Colombier byte i; 190*219b2ee8SDavid du Colombier byte fd; 191*219b2ee8SDavid du Colombier byte r; 192*219b2ee8SDavid du Colombier bit b; 193*219b2ee8SDavid du Colombier 194*219b2ee8SDavid du Colombier do 195*219b2ee8SDavid du Colombier :: selcall?r -> 196*219b2ee8SDavid du Colombier/* printf("Select called, r=%d\n", r); /**/ 197*219b2ee8SDavid du Colombier i = 0; 198*219b2ee8SDavid du Colombier do 199*219b2ee8SDavid du Colombier :: i < NBUFS -> 200*219b2ee8SDavid du Colombier if 201*219b2ee8SDavid du Colombier :: r & (1<<i) -> 202*219b2ee8SDavid du Colombier if 203*219b2ee8SDavid du Colombier :: eof[i] && n[i] == 0 -> 204*219b2ee8SDavid du Colombier/* printf("Select got eof on %d\n", i);/**/ 205*219b2ee8SDavid du Colombier num = EOF; 206*219b2ee8SDavid du Colombier r = i; 207*219b2ee8SDavid du Colombier goto donesel 208*219b2ee8SDavid du Colombier :: !eof[i] || n[i] != 0 -> skip 209*219b2ee8SDavid du Colombier fi 210*219b2ee8SDavid du Colombier :: !(r & (1<<i)) -> skip 211*219b2ee8SDavid du Colombier fi; 212*219b2ee8SDavid du Colombier i = i+1 213*219b2ee8SDavid du Colombier :: i >= NBUFS -> break 214*219b2ee8SDavid du Colombier od; 215*219b2ee8SDavid du Colombier num = 0; 216*219b2ee8SDavid du Colombier lock?get; 217*219b2ee8SDavid du Colombier rwant = 0; 218*219b2ee8SDavid du Colombier i = 0; 219*219b2ee8SDavid du Colombier do 220*219b2ee8SDavid du Colombier :: i < NBUFS -> 221*219b2ee8SDavid du Colombier if 222*219b2ee8SDavid du Colombier :: r & (1<<i) -> 223*219b2ee8SDavid du Colombier if 224*219b2ee8SDavid du Colombier :: n[i] > 0 || eof[i] -> 225*219b2ee8SDavid du Colombier/* printf("Select found %d has n==%d\n", i, n[i]); /**/ 226*219b2ee8SDavid du Colombier num = num+1 227*219b2ee8SDavid du Colombier :: n[i] == 0 && !eof[i] -> 228*219b2ee8SDavid du Colombier/* printf("Select asks to wait for %d\n", i); /**/ 229*219b2ee8SDavid du Colombier r = r &(~(1<<i)); 230*219b2ee8SDavid du Colombier rwant = rwant | (1<<i) 231*219b2ee8SDavid du Colombier fi 232*219b2ee8SDavid du Colombier :: !(r & (1<<i)) -> skip 233*219b2ee8SDavid du Colombier fi; 234*219b2ee8SDavid du Colombier i = i+1 235*219b2ee8SDavid du Colombier :: i >= NBUFS -> break 236*219b2ee8SDavid du Colombier od; 237*219b2ee8SDavid du Colombier if 238*219b2ee8SDavid du Colombier :: num > 0 || rwant == 0 -> 239*219b2ee8SDavid du Colombier rwant = 0; 240*219b2ee8SDavid du Colombier lock!release; 241*219b2ee8SDavid du Colombier :: num == 0 && rwant != 0 -> 242*219b2ee8SDavid du Colombier selwait = 1; 243*219b2ee8SDavid du Colombier lock!release; 244*219b2ee8SDavid du Colombier/* printf("Select sleeps\n"); /**/ 245*219b2ee8SDavid du Colombier sel?fd; 246*219b2ee8SDavid du Colombier/* printf("Select wakes up, fd=%d\n", fd); /**/ 247*219b2ee8SDavid du Colombier if 248*219b2ee8SDavid du Colombier :: fd != TIMEOUT -> 249*219b2ee8SDavid du Colombier if 250*219b2ee8SDavid du Colombier :: (rwant & (1<<fd)) && (n[fd] > 0) -> 251*219b2ee8SDavid du Colombier r = r | (1<<fd); 252*219b2ee8SDavid du Colombier num = 1 253*219b2ee8SDavid du Colombier :: !(rwant & (1<<fd)) || (n[fd] == 0) -> 254*219b2ee8SDavid du Colombier num = 0 255*219b2ee8SDavid du Colombier fi 256*219b2ee8SDavid du Colombier :: fd == TIMEOUT -> skip 257*219b2ee8SDavid du Colombier fi; 258*219b2ee8SDavid du Colombier rwant = 0 259*219b2ee8SDavid du Colombier fi; 260*219b2ee8SDavid du Colombier donesel: 261*219b2ee8SDavid du Colombier selans!num,r 262*219b2ee8SDavid du Colombier :: selkill?b -> break 263*219b2ee8SDavid du Colombier od 264*219b2ee8SDavid du Colombier} 265*219b2ee8SDavid du Colombier 266*219b2ee8SDavid du Colombier/* This routine is written knowing NBUFS == 2 in several places */ 267*219b2ee8SDavid du Colombierproctype User() 268*219b2ee8SDavid du Colombier{ 269*219b2ee8SDavid du Colombier byte ndone; 270*219b2ee8SDavid du Colombier byte i; 271*219b2ee8SDavid du Colombier byte rw; 272*219b2ee8SDavid du Colombier byte num; 273*219b2ee8SDavid du Colombier byte nwant; 274*219b2ee8SDavid du Colombier byte fd; 275*219b2ee8SDavid du Colombier bool goteof[NBUFS]; 276*219b2ee8SDavid du Colombier 277*219b2ee8SDavid du Colombier ndone = 0; 278*219b2ee8SDavid du Colombier do 279*219b2ee8SDavid du Colombier :: ndone == NBUFS -> break 280*219b2ee8SDavid du Colombier :: ndone < NBUFS -> 281*219b2ee8SDavid du Colombier if 282*219b2ee8SDavid du Colombier :: 1-> 283*219b2ee8SDavid du Colombier /* maybe use Read */ 284*219b2ee8SDavid du Colombier/* printf("User trying to read. Current goteofs: %d %d\n", goteof[0], goteof[1]); /**/ 285*219b2ee8SDavid du Colombier /* randomly pick fd 0 or 1 from non-eof ones */ 286*219b2ee8SDavid du Colombier if 287*219b2ee8SDavid du Colombier :: !goteof[0] -> fd = 0 288*219b2ee8SDavid du Colombier :: !goteof[1] -> fd = 1 289*219b2ee8SDavid du Colombier fi; 290*219b2ee8SDavid du Colombier if 291*219b2ee8SDavid du Colombier :: nwant = 1 292*219b2ee8SDavid du Colombier :: nwant = READMAX 293*219b2ee8SDavid du Colombier fi; 294*219b2ee8SDavid du Colombier readcall!fd,nwant; 295*219b2ee8SDavid du Colombier readans?num; 296*219b2ee8SDavid du Colombier if 297*219b2ee8SDavid du Colombier :: num == EOF -> 298*219b2ee8SDavid du Colombier goteof[fd] = 1; 299*219b2ee8SDavid du Colombier ndone = ndone + 1 300*219b2ee8SDavid du Colombier :: num != EOF -> assert(num != 0) 301*219b2ee8SDavid du Colombier fi 302*219b2ee8SDavid du Colombier :: 1-> 303*219b2ee8SDavid du Colombier/* printf("User trying to select. Current goteofs: %d %d\n", goteof[0], goteof[1]); /**/ 304*219b2ee8SDavid du Colombier /* maybe use Select, then Read */ 305*219b2ee8SDavid du Colombier /* randomly set the "i want" bit for non-eof fds */ 306*219b2ee8SDavid du Colombier if 307*219b2ee8SDavid du Colombier :: !goteof[0] && !goteof[1] -> rw = (1<<0) | (1<<1) 308*219b2ee8SDavid du Colombier :: !goteof[0] -> rw = (1<<0) 309*219b2ee8SDavid du Colombier :: !goteof[1] -> rw = (1<<1) 310*219b2ee8SDavid du Colombier fi; 311*219b2ee8SDavid du Colombier selcall!rw; 312*219b2ee8SDavid du Colombier selans?i,rw; 313*219b2ee8SDavid du Colombier if 314*219b2ee8SDavid du Colombier :: i == EOF -> 315*219b2ee8SDavid du Colombier goteof[rw] = 1; 316*219b2ee8SDavid du Colombier ndone = ndone + 1 317*219b2ee8SDavid du Colombier :: i != EOF -> 318*219b2ee8SDavid du Colombier /* this next statement knows NBUFS == 2 ! */ 319*219b2ee8SDavid du Colombier if 320*219b2ee8SDavid du Colombier :: rw & (1<<0) -> fd = 0 321*219b2ee8SDavid du Colombier :: rw & (1<<1) -> fd = 1 322*219b2ee8SDavid du Colombier :: rw == 0 -> fd = EOF 323*219b2ee8SDavid du Colombier fi; 324*219b2ee8SDavid du Colombier if 325*219b2ee8SDavid du Colombier :: nwant = 1 326*219b2ee8SDavid du Colombier :: nwant = READMAX 327*219b2ee8SDavid du Colombier fi; 328*219b2ee8SDavid du Colombier if 329*219b2ee8SDavid du Colombier :: fd != EOF -> 330*219b2ee8SDavid du Colombier readcall!fd,nwant; 331*219b2ee8SDavid du Colombier readans?num; 332*219b2ee8SDavid du Colombier assert(num != 0) 333*219b2ee8SDavid du Colombier :: fd == EOF -> skip 334*219b2ee8SDavid du Colombier fi 335*219b2ee8SDavid du Colombier fi 336*219b2ee8SDavid du Colombier fi 337*219b2ee8SDavid du Colombier od; 338*219b2ee8SDavid du Colombier lockkill!release; 339*219b2ee8SDavid du Colombier selkill!release; 340*219b2ee8SDavid du Colombier readkill!release 341*219b2ee8SDavid du Colombier} 342*219b2ee8SDavid du Colombier 343*219b2ee8SDavid du Colombierinit 344*219b2ee8SDavid du Colombier{ 345*219b2ee8SDavid du Colombier byte i; 346*219b2ee8SDavid du Colombier 347*219b2ee8SDavid du Colombier atomic { 348*219b2ee8SDavid du Colombier run Lockrendez(); 349*219b2ee8SDavid du Colombier i = 0; 350*219b2ee8SDavid du Colombier do 351*219b2ee8SDavid du Colombier :: i < NBUFS -> 352*219b2ee8SDavid du Colombier run Copy(i); 353*219b2ee8SDavid du Colombier i = i+1 354*219b2ee8SDavid du Colombier :: i >= NBUFS -> break 355*219b2ee8SDavid du Colombier od; 356*219b2ee8SDavid du Colombier run Select(); 357*219b2ee8SDavid du Colombier run Read(); 358*219b2ee8SDavid du Colombier run User() 359*219b2ee8SDavid du Colombier } 360*219b2ee8SDavid du Colombier} 361