/* * Define a user named label to have the offset of the next opcode. * * given: * name label name */ void definelabel(char *name) { register LABEL *lp; /* current label */ long i; /* current label index */ i = findstr(&labelnames, name); if (i >= 0) { lp = &labels[i]; if (lp->l_offset >= 0) { scanerror(T_NULL, "Label \"%s\" is multiply defined", name); return; } setlabel(lp); return; } if (labelcount >= MAXLABELS) { scanerror(T_NULL, "Too many labels in use"); return; } lp = &labels[labelcount++]; lp->l_chain = -1L; lp->l_offset = (long)curfunc->f_opcodecount; lp->l_name = addstr(&labelnames, name); clearopt(); }
/* Address of the source must already have been loaded in PRI, the * destination address in ALT. * This routine makes a loop that copies the minor dimension vector * by vector. */ SC_FUNC void copyarray2d(int majordim,int minordim) { int looplbl=getlabel(); stgwrite("\tpush.alt\n"); stgwrite("\tpush.pri\n"); stgwrite("\tzero.alt\n"); /* ALT = index = 0 */ setlabel(looplbl); stgwrite("\tpush.alt\n"); /* save index */ stgwrite("\tpick 8\n"); /* PRI = dest */ stgwrite("\txchg\n"); /* ALT = dest, PRI = index */ stgwrite("\tidxaddr\n"); /* PRI = dest + index * sizeof(cell) */ stgwrite("\tmove.alt\n"); /* ALT = dest + index * sizeof(cell) */ stgwrite("\tload.i\n"); /* PRI = dest[index * sizeof(cell)] */ stgwrite("\tadd\n"); /* PRI = dest + index * sizeof(cell) + dest[index * sizeof(cell)] */ stgwrite("\tpush.pri\n"); stgwrite("\tpick 8\n"); /* PRI = source */ stgwrite("\tmove.alt\n"); /* ALT = source */ stgwrite("\tpick 4\n"); /* PRI = index */ stgwrite("\tidxaddr\n"); /* PRI = source + index * sizeof(cell) */ stgwrite("\tmove.alt\n"); /* ALT = source + index * sizeof(cell) */ stgwrite("\tload.i\n"); /* PRI = source[index * sizeof(cell)] */ stgwrite("\tadd\n"); /* PRI = source + index * sizeof(cell) + source[index * sizeof(cell)] */ stgwrite("\tpop.alt\n"); /* ALT = source + index * sizeof(cell) + source[index * sizeof(cell)] */ stgwrite("\tmovs "); outval(minordim*sizeof(cell),TRUE,TRUE); stgwrite("\tpop.alt\n"); /* ALT = saved index */ stgwrite("\tinc.alt\n"); /* ALT = index + 1 */ stgwrite("\teq.c.alt "); outval(majordim,TRUE,TRUE); stgwrite("\tjzer "); outval(looplbl,TRUE,TRUE); stgwrite("\tpop.pri\n"); /* restore stack & registers */ stgwrite("\tpop.alt\n"); code_idx+=opcodes(26)+opargs(6); }
void Fl_Type::label(const char *n) { if(storestring(n,label_,1)) { setlabel(label_); widget_browser->redraw(); } }
/* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { Edf *e; machp()->inidle = 1; machp()->proc = nil; ainc(&run.nmach); setlabel(&machp()->sched); Proc *up = externup(); if(infected_with_std()){ print("mach %d got an std from %s (pid %d)!\n", machp()->machno, up ? up->text : "*notext", up ? up->pid : -1 ); disinfect_std(); } if(up) { if((e = up->edf) && (e->flags & Admitted)) edfrecord(up); machp()->qstart = 0; machp()->qexpired = 0; coherence(); machp()->proc = 0; switch(up->state) { case Running: ready(up); break; case Moribund: up->state = Dead; stopac(); edfstop(up); if (up->edf) free(up->edf); up->edf = nil; /* * Holding locks from pexit: * procalloc * pga */ mmurelease(up); unlock(&pga.l); psrelease(up); unlock(&procalloc.l); break; } up->mach = nil; updatecpu(up); machp()->externup = nil; } sched(); }
/* initialization plot struct -------------------------------------------------- * set value to plot struct * args : sdrplt_t *acq I/0 plot struct for acquisition * sdrplt_t *trk I/0 plot struct for tracking * sdrch_t *sdr I sdr channel struct * return : int 0:okay -1:error *-----------------------------------------------------------------------------*/ extern int initpltstruct(sdrplt_t *acq, sdrplt_t *trk, sdrch_t *sdr) { double scale=1.0; /* acquisition */ if (sdrini.pltacq) { setsdrplotprm(acq,PLT_SURFZ,sdr->acq.nfreq,sdr->nsamp,3,OFF,1, PLT_H,PLT_W,PLT_MH,PLT_MW,sdr->no); if (initsdrplot(acq)<0) return -1; settitle(acq,sdr->satstr); setlabel(acq,"Frequency (Hz)","Code Offset (sample)"); } /* tracking */ if (sdrini.plttrk) { setsdrplotprm(trk,PLT_XY,1+2*sdr->trk.corrn,0,0,ON,0.001, PLT_H,PLT_W,PLT_MH,PLT_MW,sdr->no); if(initsdrplot(trk)<0) return -1; settitle(trk,sdr->satstr); setlabel(trk,"Code Offset (sample)","Correlation Output"); switch (sdrini.fend) { case FEND_GN3SV2: case FEND_GN3SV3: case FEND_FGN3SV2: case FEND_FGN3SV3: scale=1.5; break; case FEND_BLADERF: case FEND_FBLADERF: scale=5.0; break; case FEND_RTLSDR: case FEND_FRTLSDR: scale=3.5; break; } setyrange(trk,0,sdr->trk.loop*sdr->nsamp/4000*scale); } if (sdrini.fend==FEND_FILE||sdrini.fend==FEND_FSTEREO|| sdrini.fend==FEND_FGN3SV2||sdrini.fend==FEND_FGN3SV2|| sdrini.fend==FEND_FRTLSDR||sdrini.fend==FEND_FBLADERF) { trk->pltms=PLT_MS_FILE; } else { trk->pltms=PLT_MS; } return 0; }
void error(char *err) { spllo(); assert(up->nerrlab < NERR); kstrcpy(up->errstr, err, ERRMAX); setlabel(&up->errlab[NERR-1]); nexterror(); }
void MainWindow::on_pushButton_clicked() { gobj.init(); setlabel(); flag = 1; gobj.score = 0; step = 0; ui->lcdNumber->display(gobj.score); ui->lcdNumber_2->display(step); }
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); gobj.init(); setlabel(); flag = 1; step = 0; resWin = new Result; }
void error(char *err) { Mach *m = machp(); spllo(); assert(m->externup->nerrlab < NERR); kstrcpy(m->externup->errstr, err, ERRMAX); setlabel(&m->externup->errlab[NERR-1]); nexterror(); }
void error(char *err) { if(up == nil) panic("error(%s) not in a process", err); spllo(); if(up->nerrlab > NERR) panic("error stack too deep"); if(err != up->env->errstr) kstrcpy(up->env->errstr, err, ERRMAX); setlabel(&up->errlab[NERR-1]); nexterror(); }
/* * Open an information (display) window. */ struct ww * openiwin(int nrow, const char *label) { struct ww *w; if ((w = wwopen(WWT_INTERNAL, 0, nrow, wwncol, 2, 0, 0)) == 0) return 0; SET(w->ww_wflags, WWW_MAPNL | WWW_NOINTR | WWW_NOUPDATE | WWW_UNCTRL); SET(w->ww_uflags, WWU_HASFRAME | WWU_CENTER); w->ww_id = -1; (void) setlabel(w, label); addwin(w, 1); reframe(); return w; }
/* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { Mach *m = machp(); Edf *e; m->inidle = 1; m->proc = nil; ainc(&run.nmach); setlabel(&m->sched); if(m->externup) { if((e = m->externup->edf) && (e->flags & Admitted)) edfrecord(m->externup); m->qstart = 0; m->qexpired = 0; coherence(); m->proc = 0; switch(m->externup->state) { case Running: ready(m->externup); break; case Moribund: m->externup->state = Dead; stopac(); edfstop(m->externup); if (m->externup->edf) free(m->externup->edf); m->externup->edf = nil; /* * Holding locks from pexit: * procalloc * pga */ mmurelease(m->externup); unlock(&pga); psrelease(m->externup); unlock(&procalloc); break; } m->externup->mach = nil; updatecpu(m->externup); m->externup = nil; } sched(); }
/* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { Edf *e; setlabel(&m->sched); if(up != nil) { if((e = up->edf) != nil && (e->flags & Admitted)) edfrecord(up); m->proc = nil; switch(up->state) { case Running: ready(up); break; case Moribund: up->state = Dead; edfstop(up); if(up->edf != nil) free(up->edf); up->edf = nil; /* * Holding locks from pexit: * procalloc * palloc */ mmurelease(up); unlock(&palloc); up->mach = nil; updatecpu(up); up->qnext = procalloc.free; procalloc.free = up; /* proc is free now, make sure unlock() wont touch it */ up = procalloc.Lock.p = nil; unlock(&procalloc); sched(); } up->mach = nil; updatecpu(up); up = nil; } sched(); }
void sched(void) { if(up) { splhi(); procsave(up); if(setlabel(&up->sched)) { /* procrestore(up); */ spllo(); return; } gotolabel(&m->sched); } up = runproc(); up->state = Running; up->mach = MACHP(m->machno); /* m might be a fixed address; use MACHP */ m->proc = up; gotolabel(&up->sched); }
/* * Open a user window. */ struct ww * openwin(int id, int row, int col, int nrow, int ncol, int nline, char *label, int type, int uflags, char *shf, char **sh) { struct ww *w; if (id < 0 && (id = findid()) < 0) return 0; if (row + nrow <= 0 || row > wwnrow - 1 || col + ncol <= 0 || col > wwncol - 1) { error("Illegal window position."); return 0; } w = wwopen(type, 0, nrow, ncol, row, col, nline); if (w == 0) { error("Can't open window: %s.", wwerror()); return 0; } w->ww_id = id; window[id] = w; CLR(w->ww_uflags, WWU_ALLFLAGS); SET(w->ww_uflags, uflags); w->ww_alt = w->ww_w; if (label != 0 && setlabel(w, label) < 0) error("No memory for label."); wwcursor(w, 1); /* * We have to do this little maneuver to make sure * addwin() puts w at the top, so we don't waste an * insert and delete operation. */ setselwin((struct ww *)0); addwin(w, 0); setselwin(w); if (wwspawn(w, shf, sh) < 0) { error("Can't execute %s: %s.", shf, wwerror()); closewin(w); return 0; } return w; }
/* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { setlabel(&m->sched); if(up) { /* if((e = up->edf) && (e->flags & Admitted)) edfrecord(up); */ m->proc = nil; switch(up->state) { case Running: ready(up); break; case Moribund: up->state = Dead; /* edfstop(up); if(up->edf){ free(up->edf); up->edf = nil; } */ /* * Holding locks from pexit: * procalloc */ up->qnext = procalloc.free; procalloc.free = up; unlock(&procalloc); break; } up->mach = nil; up = nil; } sched(); }
/* writestatetables * Creates and dumps the state tables. Every function with states has a state * table that contains jump addresses (or overlay indices) the branch to the * appropriate function using the (hidden) state variable as the criterion. * Technically, this happens in a "switch" (or an "iswitch") instruction. * This function also creates the hidden state variables (one for each * automaton) in the data segment. */ SC_FUNC void writestatetables(symbol *root,int lbl_nostate,int lbl_ignorestate) { int lbl_default,lbl_table,lbl_defnostate; int statecount; symbol *sym; constvalue *fsa, *state; statelist *stlist; int fsa_id,listid; assert(code_idx>0); /* leader must already have been written */ /* check whether there are any functions that have states */ for (sym=root->next; sym!=NULL; sym=sym->next) if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) break; if (sym==NULL) return; /* no function has states, nothing to do next */ assert(pc_ovl0size[ovlNO_STATE][0]>0); /* state exit point must already have been created */ assert(pc_ovl0size[ovlNO_STATE][1]>0); /* write the "state-selectors" table with all automatons (update the * automatons structure too, as we are now assigning the address to * each automaton state-selector variable) */ assert(glb_declared==0); begdseg(); for (fsa=sc_automaton_tab.next; fsa!=NULL; fsa=fsa->next) { defstorage(); stgwrite("0\t; automaton "); if (strlen(fsa->name)==0) stgwrite("(anonymous)"); else stgwrite(fsa->name); stgwrite("\n"); fsa->value=glb_declared*sizeof(cell); glb_declared++; } /* for */ /* write stubs and jump tables for all state functions */ begcseg(); for (sym=root->next; sym!=NULL; sym=sym->next) { if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) { stlist=sym->states->next; assert(stlist!=NULL); /* there should be at least one state item */ listid=stlist->id; assert(listid==-1 || listid>0); if (listid==-1 && stlist->next!=NULL) { /* first index is the "fallback", take the next one (if available) */ stlist=stlist->next; listid=stlist->id; } /* if */ if (listid==-1) { /* first index is the fallback, there is no second... */ stlist->label=0; /* insert dummy label number */ /* this is an error, but we postpone adding the error message until the * function definition */ continue; } /* if */ /* generate label numbers for all statelist ids */ for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { if (pc_overlays>0) { /* code overlay indices should already be set, see gen_ovlinfo() */ assert(stlist->label>0); } else { assert(stlist->label==0); stlist->label=getlabel(); } /* if */ } /* for */ if (strcmp(sym->name,uENTRYFUNC)==0) continue; /* do not generate stubs for this special function */ sym->addr=code_idx; /* fix the function address now */ /* get automaton id for this function */ assert(listid>0); fsa_id=state_getfsa(listid); assert(fsa_id>=0); /* automaton 0 exists */ fsa=automaton_findid(fsa_id); /* count the number of states actually used; at the same time, check * whether there is a default (i.e. "fallback") state function */ statecount=0; if (strcmp(sym->name,uEXITFUNC)==0) { lbl_default= (pc_overlays>0) ? ovlEXITSTATE : lbl_ignorestate; } else { lbl_defnostate= (pc_overlays>0) ? ovlNO_STATE : lbl_nostate; lbl_default=lbl_defnostate; } /* if */ for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { if (stlist->id==-1) { lbl_default=stlist->label; } else { statecount+=state_count(stlist->id); } /* if */ } /* for */ /* generate a stub entry for the functions */ stgwrite("\tload.pri "); outval(fsa->value,TRUE,FALSE); stgwrite("\t; "); stgwrite(sym->name); if (pc_overlays>0) { /* add overlay index */ stgwrite("/"); outval(sym->index,FALSE,FALSE); } /* if */ stgwrite("\n"); code_idx+=opcodes(1)+opargs(1); /* calculate code length */ lbl_table=getlabel(); ffswitch(lbl_table,(pc_overlays>0)); /* generate the jump table */ setlabel(lbl_table); ffcase(statecount,lbl_default,TRUE,(pc_overlays>0)); for (state=sc_state_tab.next; state!=NULL; state=state->next) { if (state->index==fsa_id) { /* find the label for this list id */ for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { if (stlist->id!=-1 && state_inlist(stlist->id,(int)state->value)) { /* when overlays are used, the jump-label for the case statement * are overlay indices instead of code labels */ ffcase(state->value,stlist->label,FALSE,(pc_overlays>0)); break; } /* if */ } /* for */ if (stlist==NULL && lbl_default==lbl_defnostate) error(230,state->name,sym->name); /* unimplemented state, no fallback */ } /* if (state belongs to automaton of function) */ } /* for (state) */ stgwrite("\n"); /* the jump table gets its own overlay index, and the size of the jump * table must therefore be known (i.e. update the codeaddr field of the * function with the address where the jump table ends) */ sym->codeaddr=code_idx; } /* if (is function, used & having states) */ } /* for (sym) */ }
/* * sleep if a condition is not true. Another process will * awaken us after it sets the condition. When we awaken * the condition may no longer be true. * * we lock both the process and the rendezvous to keep r->p * and p->r synchronized. */ void sleep(Rendez *r, int (*f)(void*), void *arg) { int s; void (*pt)(Proc*, int, vlong); s = splhi(); if(up->nlocks) print("process %lud sleeps with %d locks held, last lock %#p locked at pc %#p, sleep called from %#p\n", up->pid, up->nlocks, up->lastlock, up->lastlock->pc, getcallerpc(&r)); lock(r); lock(&up->rlock); if(r->p != nil){ print("double sleep called from %#p, %lud %lud\n", getcallerpc(&r), r->p->pid, up->pid); dumpstack(); } /* * Wakeup only knows there may be something to do by testing * r->p in order to get something to lock on. * Flush that information out to memory in case the sleep is * committed. */ r->p = up; if((*f)(arg) || up->notepending){ /* * if condition happened or a note is pending * never mind */ r->p = nil; unlock(&up->rlock); unlock(r); } else { /* * now we are committed to * change state and call scheduler */ pt = proctrace; if(pt != nil) pt(up, SSleep, 0); up->state = Wakeme; up->r = r; /* statistics */ m->cs++; procsave(up); if(setlabel(&up->sched)) { /* * here when the process is awakened */ procrestore(up); spllo(); } else { /* * here to go to sleep (i.e. stop Running) */ unlock(&up->rlock); unlock(r); gotolabel(&m->sched); } } if(up->notepending) { up->notepending = 0; splx(s); interrupted(); } splx(s); }
void viewer(Document *dd) { int i, fd, n, oldpage; int nxt; Menu menu, midmenu; Mouse m; Event e; Point dxy, oxy, xy0; Image *tmp; static char *fwditems[] = { "this page", "next page", "exit", 0 }; static char *miditems[] = { "orig size", "zoom in", "fit window", "rotate 90", "upside down", "", "next", "prev", "zerox", "", "reverse", "discard", "write", "", "quit", 0 }; char *s; enum { Eplumb = 4 }; Plumbmsg *pm; doc = dd; /* save global for menuhit */ ul = screen->r.min; einit(Emouse|Ekeyboard); if(doc->addpage != nil) eplumb(Eplumb, "image"); esetcursor(&reading); /* * im is a global pointer to the current image. * eventually, i think we will have a layer between * the display routines and the ps/pdf/whatever routines * to perhaps cache and handle images of different * sizes, etc. */ im = 0; page = reverse ? doc->npage-1 : 0; if(doc->fwdonly) { menu.item = fwditems; menu.gen = 0; menu.lasthit = 0; } else { menu.item = 0; menu.gen = menugen; menu.lasthit = 0; } midmenu.item = miditems; midmenu.gen = 0; midmenu.lasthit = Next; if(doc->docname != nil) setlabel(doc->docname); showpage(page, &menu); esetcursor(nil); nxt = 0; for(;;) { /* * throughout, if doc->fwdonly is set, we restrict the functionality * a fair amount. we don't care about doc->npage anymore, and * all that can be done is select the next page. */ unlockdisplay(display); i = eread(Emouse|Ekeyboard|Eplumb, &e); lockdisplay(display); switch(i){ case Ekeyboard: if(e.kbdc <= 0xFF && isdigit(e.kbdc)) { nxt = nxt*10+e.kbdc-'0'; break; } else if(e.kbdc != '\n') nxt = 0; switch(e.kbdc) { case 'r': /* reverse page order */ if(doc->fwdonly) break; reverse = !reverse; menu.lasthit = doc->npage-1-menu.lasthit; /* * the theory is that if we are reversing the * document order and are on the first or last * page then we're just starting and really want * to view the other end. maybe the if * should be dropped and this should happen always. */ if(page == 0 || page == doc->npage-1) { page = doc->npage-1-page; showpage(page, &menu); } break; case 'w': /* write bitmap of current screen */ esetcursor(&reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); esetcursor(nil); flushimage(display, 1); break; case 'd': /* remove image from working set */ if(doc->rmpage && page < doc->npage) { if(doc->rmpage(doc, page) >= 0) { if(doc->npage < 0) wexits(0); if(page >= doc->npage) page = doc->npage-1; showpage(page, &menu); } } break; case 'q': case 0x04: /* ctrl-d */ wexits(0); case 'u': if(im==nil) break; angle = (angle+180) % 360; showpage(page, &menu); break; case '-': case '\b': case Kleft: if(page > 0 && !doc->fwdonly) { --page; showpage(page, &menu); } break; case '\n': if(nxt) { nxt--; if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly) showpage(page=nxt, &menu); nxt = 0; break; } goto Gotonext; case Kright: case ' ': Gotonext: if(doc->npage && ++page >= doc->npage && !doc->fwdonly) wexits(0); showpage(page, &menu); break; /* * The upper y coordinate of the image is at ul.y in screen->r. * Panning up means moving the upper left corner down. If the * upper left corner is currently visible, we need to go back a page. */ case Kup: if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){ if(page > 0 && !doc->fwdonly){ --page; showbottom = 1; showpage(page, &menu); } } else { i = Dy(screen->r)/2; if(i > 10) i -= 10; if(i+ul.y > screen->r.min.y) i = screen->r.min.y - ul.y; translate(Pt(0, i)); } break; /* * If the lower y coordinate is on the screen, we go to the next page. * The lower y coordinate is at ul.y + Dy(im->r). */ case Kdown: i = ul.y + Dy(im->r); if(screen->r.min.y <= i && i <= screen->r.max.y){ ul.y = screen->r.min.y; goto Gotonext; } else { i = -Dy(screen->r)/2; if(i < -10) i += 10; if(i+ul.y+Dy(im->r) <= screen->r.max.y) i = screen->r.max.y - Dy(im->r) - ul.y - 1; translate(Pt(0, i)); } break; default: esetcursor(&query); sleep(1000); esetcursor(nil); break; } break; case Emouse: m = e.mouse; switch(m.buttons){ case Left: oxy = m.xy; xy0 = oxy; do { dxy = subpt(m.xy, oxy); oxy = m.xy; translate(dxy); unlockdisplay(display); m = emouse(); lockdisplay(display); } while(m.buttons == Left); if(m.buttons) { dxy = subpt(xy0, oxy); translate(dxy); } break; case Middle: if(doc->npage == 0) break; unlockdisplay(display); n = emenuhit(Middle, &m, &midmenu); lockdisplay(display); if(n == -1) break; switch(n){ case Next: /* next */ if(reverse) page--; else page++; if(page < 0) { if(reverse) return; else page = 0; } if((page >= doc->npage) && !doc->fwdonly) return; showpage(page, &menu); nxt = 0; break; case Prev: /* prev */ if(reverse) page++; else page--; if(page < 0) { if(reverse) return; else page = 0; } if((page >= doc->npage) && !doc->fwdonly && !reverse) return; showpage(page, &menu); nxt = 0; break; case Zerox: /* prev */ zerox(); break; case Zin: /* zoom in */ { double delta; Rectangle r; r = egetrect(Middle, &m); if((rectclip(&r, rectaddpt(im->r, ul)) == 0) || Dx(r) == 0 || Dy(r) == 0) break; /* use the smaller side to expand */ if(Dx(r) < Dy(r)) delta = (double)Dx(im->r)/(double)Dx(r); else delta = (double)Dy(im->r)/(double)Dy(r); esetcursor(&reading); tmp = xallocimage(display, Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)), im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during zoom: %r\n"); wexits("memory"); } resample(im, tmp); im = tmp; delayfreeimage(tmp); esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Fit: /* fit */ { double delta; Rectangle r; delta = (double)Dx(screen->r)/(double)Dx(im->r); if((double)Dy(im->r)*delta > Dy(screen->r)) delta = (double)Dy(screen->r)/(double)Dy(im->r); r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)); esetcursor(&reading); tmp = xallocimage(display, r, im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during fit: %r\n"); wexits("memory"); } resample(im, tmp); im = tmp; delayfreeimage(tmp); esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Rot: /* rotate 90 */ angle = (angle+90) % 360; showpage(page, &menu); break; case Upside: /* upside-down */ angle = (angle+180) % 360; showpage(page, &menu); break; case Restore: /* restore */ showpage(page, &menu); break; case Reverse: /* reverse */ if(doc->fwdonly) break; reverse = !reverse; menu.lasthit = doc->npage-1-menu.lasthit; if(page == 0 || page == doc->npage-1) { page = doc->npage-1-page; showpage(page, &menu); } break; case Write: /* write */ esetcursor(&reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); esetcursor(nil); flushimage(display, 1); break; case Del: /* delete */ if(doc->rmpage && page < doc->npage) { if(doc->rmpage(doc, page) >= 0) { if(doc->npage < 0) wexits(0); if(page >= doc->npage) page = doc->npage-1; showpage(page, &menu); } } break; case Exit: /* exit */ return; case Empty1: case Empty2: case Empty3: break; }; case Right: if(doc->npage == 0) break; oldpage = page; unlockdisplay(display); n = emenuhit(RMenu, &m, &menu); lockdisplay(display); if(n == -1) break; if(doc->fwdonly) { switch(n){ case 0: /* this page */ break; case 1: /* next page */ showpage(++page, &menu); break; case 2: /* exit */ return; } break; } if(n == doc->npage) return; else page = reverse ? doc->npage-1-n : n; if(oldpage != page) showpage(page, &menu); nxt = 0; break; } break; case Eplumb: pm = e.v; if(pm->ndata <= 0){ plumbfree(pm); break; } if(plumbquit(pm)) exits(nil); if(showdata(pm)) { s = estrdup("/tmp/pageplumbXXXXXXX"); fd = opentemp(s); write(fd, pm->data, pm->ndata); /* lose fd reference on purpose; the file is open ORCLOSE */ } else if(pm->data[0] == '/') { s = estrdup(pm->data); } else { s = emalloc(strlen(pm->wdir)+1+pm->ndata+1); sprint(s, "%s/%s", pm->wdir, pm->data); cleanname(s); } if((i = doc->addpage(doc, s)) >= 0) { page = i; unhide(); showpage(page, &menu); } free(s); plumbfree(pm); break; } } }
/* * If changing this routine, look also at sleep(). It * contains a copy of the guts of sched(). */ void sched(void) { Proc *p; if(m->ilockdepth) panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p", m->machno, m->ilockdepth, up != nil ? up->lastilock: nil, (up != nil && up->lastilock != nil) ? up->lastilock->pc: 0, getcallerpc(&p+2)); if(up != nil) { /* * Delay the sched until the process gives up the locks * it is holding. This avoids dumb lock loops. * Don't delay if the process is Moribund. * It called sched to die. * But do sched eventually. This avoids a missing unlock * from hanging the entire kernel. * But don't reschedule procs holding palloc or procalloc. * Those are far too important to be holding while asleep. * * This test is not exact. There can still be a few instructions * in the middle of taslock when a process holds a lock * but Lock.p has not yet been initialized. */ if(up->nlocks) if(up->state != Moribund) if(up->delaysched < 20 || palloc.Lock.p == up || procalloc.Lock.p == up){ up->delaysched++; delayedscheds++; return; } up->delaysched = 0; splhi(); /* statistics */ m->cs++; procsave(up); if(setlabel(&up->sched)){ procrestore(up); spllo(); return; } gotolabel(&m->sched); } p = runproc(); if(p->edf == nil){ updatecpu(p); p->priority = reprioritize(p); } if(p != m->readied) m->schedticks = m->ticks + HZ/10; m->readied = nil; up = p; up->state = Running; up->mach = MACHP(m->machno); m->proc = up; mmuswitch(up); gotolabel(&up->sched); }
/* * If changing this routine, look also at sleep(). It * contains a copy of the guts of sched(). */ void sched(void) { Mach *m = machp(); Proc *p; if(m->ilockdepth) panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p", m->machno, m->ilockdepth, m->externup? m->externup->lastilock: nil, (m->externup && m->externup->lastilock)? m->externup->lastilock->_pc: 0, getcallerpc(&p+2)); kstackok(); if(m->externup){ /* * Delay the sched until the process gives up the locks * it is holding. This avoids dumb lock loops. * Don't delay if the process is Moribund. * It called sched to die. * But do sched eventually. This avoids a missing unlock * from hanging the entire kernel. * But don't reschedule procs holding palloc or procalloc. * Those are far too important to be holding while asleep. * * This test is not exact. There can still be a few * instructions in the middle of taslock when a process * holds a lock but Lock.p has not yet been initialized. */ if(m->externup->nlocks) if(m->externup->state != Moribund) if(m->externup->delaysched < 20 || pga.Lock.p == m->externup || procalloc.Lock.p == m->externup){ m->externup->delaysched++; run.delayedscheds++; return; } m->externup->delaysched = 0; splhi(); /* statistics */ if(m->externup->nqtrap == 0 && m->externup->nqsyscall == 0) m->externup->nfullq++; m->cs++; procsave(m->externup); mmuflushtlb(m->pml4->pa); if(setlabel(&m->externup->sched)){ procrestore(m->externup); spllo(); return; } /*debug*/gotolabel(&m->sched); } m->inidle = 1; p = runproc(); /* core 0 never returns */ m->inidle = 0; if(!p->edf){ updatecpu(p); p->priority = reprioritize(p); } if(nosmp){ if(p != m->readied) m->schedticks = m->ticks + HZ/10; m->readied = 0; } m->externup = p; m->qstart = m->ticks; m->externup->nqtrap = 0; m->externup->nqsyscall = 0; m->externup->state = Running; //m->externup->mach = m; m->externup->mach = sys->machptr[m->machno]; m->proc = m->externup; // iprint("m->externup->sched.sp %p * %p\n", up->sched.sp, // *(void **) m->externup->sched.sp); mmuswitch(m->externup); assert(!m->externup->wired || m->externup->wired == m); if (0) hi("gotolabel\n"); /*debug*/gotolabel(&m->externup->sched); }
/* * sleep if a condition is not true. Another process will * awaken us after it sets the condition. When we awaken * the condition may no longer be true. * * we lock both the process and the rendezvous to keep r->p * and p->r synchronized. */ void sleep(Rendez *r, int (*f)(void*), void *arg) { Mach *m = machp(); Mpl pl; pl = splhi(); if(m->externup->nlocks) print("process %d sleeps with %d locks held, last lock %#p locked at pc %#p, sleep called from %#p\n", m->externup->pid, m->externup->nlocks, m->externup->lastlock, m->externup->lastlock->_pc, getcallerpc(&r)); lock(r); lock(&m->externup->rlock); if(r->_p){ print("double sleep called from %#p, %d %d\n", getcallerpc(&r), r->_p->pid, m->externup->pid); dumpstack(); } /* * Wakeup only knows there may be something to do by testing * r->p in order to get something to lock on. * Flush that information out to memory in case the sleep is * committed. */ r->_p = m->externup; if((*f)(arg) || m->externup->notepending){ /* * if condition happened or a note is pending * never mind */ r->_p = nil; unlock(&m->externup->rlock); unlock(r); } else { /* * now we are committed to * change state and call scheduler */ if(m->externup->trace) proctrace(m->externup, SSleep, 0); m->externup->state = Wakeme; m->externup->r = r; /* statistics */ m->cs++; procsave(m->externup); mmuflushtlb(m->pml4->pa); if(setlabel(&m->externup->sched)) { /* * here when the process is awakened */ procrestore(m->externup); spllo(); } else { /* * here to go to sleep (i.e. stop Running) */ unlock(&m->externup->rlock); unlock(r); /*debug*/gotolabel(&m->sched); } } if(m->externup->notepending) { m->externup->notepending = 0; splx(pl); if(m->externup->procctl == Proc_exitme && m->externup->closingfgrp) forceclosefgrp(); error(Eintr); } splx(pl); }
/* When a subroutine returns to address 0, the AMX must halt. In earlier * releases, the RET and RETN opcodes checked for the special case 0 address. * Today, the compiler simply generates a HALT instruction at address 0. So * a subroutine can savely return to 0, and then encounter a HALT. */ SC_FUNC void writeleader(symbol *root,int *lbl_nostate,int *lbl_ignorestate) { symbol *sym; assert(code_idx==0); assert(lbl_nostate!=NULL); assert(lbl_ignorestate!=NULL); *lbl_nostate=0; *lbl_ignorestate=0; begcseg(); pc_ovl0size[ovlEXIT][0]=code_idx; /* store offset to the special overlay */ stgwrite(";program exit point\n"); #if !defined AMX_NO_PACKED_OPC if (pc_optimize>sOPTIMIZE_NOMACRO) { stgwrite("\thalt.p 0\n\n"); code_idx+=opcodes(1); } else { #endif stgwrite("\thalt 0\n\n"); code_idx+=opcodes(1)+opargs(1); /* calculate code length */ #if !defined AMX_NO_PACKED_OPC } /* if */ #endif pc_ovl0size[ovlEXIT][1]=code_idx-pc_ovl0size[ovlEXIT][0]; /* store overlay code size */ /* check whether there are any functions that have states */ for (sym=root->next; sym!=NULL; sym=sym->next) if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) break; if (sym==NULL) return; /* no function has states, nothing to do next */ /* generate an error function that is called for an undefined state */ pc_ovl0size[ovlNO_STATE][0]=code_idx; stgwrite(";exit point for functions called from the wrong state\n"); assert(lbl_nostate!=NULL); *lbl_nostate=getlabel(); setlabel(*lbl_nostate); #if !defined AMX_NO_PACKED_OPC if (pc_optimize>sOPTIMIZE_NOMACRO) { assert(AMX_ERR_INVSTATE<(1<<sizeof(cell)*4)); stgwrite("\thalt.p "); outval(AMX_ERR_INVSTATE,TRUE,TRUE); code_idx+=opcodes(1); } else { #endif stgwrite("\thalt "); outval(AMX_ERR_INVSTATE,TRUE,TRUE); code_idx+=opcodes(1)+opargs(1); /* calculate code length */ #if !defined AMX_NO_PACKED_OPC } /* if */ #endif stgwrite("\n"); pc_ovl0size[ovlNO_STATE][1]=code_idx-pc_ovl0size[ovlNO_STATE][0]; /* check whether there are "exit state" functions */ for (sym=root->next; sym!=NULL; sym=sym->next) if (strcmp(sym->name,uEXITFUNC)==0) break; if (sym!=NULL) { /* generate a stub function that is called for an undefined exit state and * that returns immediately to the caller (no error) */ pc_ovl0size[ovlEXITSTATE][0]=code_idx; stgwrite(";catch-all for undefined exit states\n"); assert(lbl_ignorestate!=NULL); *lbl_ignorestate=getlabel(); setlabel(*lbl_ignorestate); /* the RET and IRETN instructions pop off the FRM register from the stack, * because they assume that a stack frame was set up; for this catch-all * routine (for exit states) we therefore need to set up a stack frame */ stgwrite("\tproc\n"); if (pc_overlays>0) stgwrite("\tiretn\n"); else stgwrite("\tret\n"); code_idx+=opcodes(2); pc_ovl0size[ovlEXITSTATE][1]=code_idx-pc_ovl0size[ovlEXITSTATE][0]; } /* if */ }
/* When a subroutine returns to address 0, the AMX must halt. In earlier * releases, the RET and RETN opcodes checked for the special case 0 address. * Today, the compiler simply generates a HALT instruction at address 0. So * a subroutine can savely return to 0, and then encounter a HALT. */ SC_FUNC void writeleader(symbol *root) { int lbl_nostate,lbl_table; int statecount; symbol *sym; constvalue *fsa, *state, *stlist; int fsa_id,listid; char lbl_default[sNAMEMAX+1]; assert(code_idx==0); begcseg(); stgwrite(";program exit point\n"); stgwrite("\thalt 0\n\n"); code_idx+=opcodes(1)+opargs(1); /* calculate code length */ /* check whether there are any functions that have states */ for (sym=root->next; sym!=NULL; sym=sym->next) if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) break; if (sym==NULL) return; /* no function has states, nothing to do next */ /* generate an error function that is called for an undefined state */ stgwrite("\n;exit point for functions called from the wrong state\n"); lbl_nostate=getlabel(); setlabel(lbl_nostate); stgwrite("\thalt "); outval(AMX_ERR_INVSTATE,TRUE); code_idx+=opcodes(1)+opargs(1); /* calculate code length */ /* write the "state-selectors" table with all automatons (update the * automatons structure too, as we are now assigning the address to * each automaton state-selector variable) */ assert(glb_declared==0); begdseg(); for (fsa=sc_automaton_tab.next; fsa!=NULL; fsa=fsa->next) { defstorage(); stgwrite("0\t; automaton "); if (strlen(fsa->name)==0) stgwrite("(anonymous)"); else stgwrite(fsa->name); stgwrite("\n"); fsa->value=glb_declared*sizeof(cell); glb_declared++; } /* for */ /* write stubs and jump tables for all state functions */ begcseg(); for (sym=root->next; sym!=NULL; sym=sym->next) { if (sym->ident==iFUNCTN && (sym->usage & (uPUBLIC | uREAD))!=0 && sym->states!=NULL) { stlist=sym->states->next; assert(stlist!=NULL); /* there should be at least one state item */ listid=stlist->index; assert(listid==-1 || listid>0); if (listid==-1 && stlist->next!=NULL) { /* first index is the "fallback", take the next one (if available) */ stlist=stlist->next; listid=stlist->index; } /* if */ if (listid==-1) { /* first index is the fallback, there is no second... */ strcpy(stlist->name,"0"); /* insert dummy label number */ /* this is an error, but we postpone adding the error message until the * function definition */ continue; } /* if */ /* generate label numbers for all statelist ids */ for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { assert(strlen(stlist->name)==0); strcpy(stlist->name,itoh(getlabel())); } /* for */ if (strcmp(sym->name,uENTRYFUNC)==0) continue; /* do not generate stubs for this special function */ sym->addr=code_idx; /* fix the function address now */ /* get automaton id for this function */ assert(listid>0); fsa_id=state_getfsa(listid); assert(fsa_id>=0); /* automaton 0 exists */ fsa=automaton_findid(fsa_id); /* count the number of states actually used; at the sane time, check * whether there is a default state function */ statecount=0; strcpy(lbl_default,itoh(lbl_nostate)); for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { if (stlist->index==-1) { assert(strlen(stlist->name)<sizeof lbl_default); strcpy(lbl_default,stlist->name); } else { statecount+=state_count(stlist->index); } /* if */ } /* for */ /* generate a stub entry for the functions */ stgwrite("\tload.pri "); outval(fsa->value,FALSE); stgwrite("\t; "); stgwrite(sym->name); stgwrite("\n"); code_idx+=opcodes(1)+opargs(1); /* calculate code length */ lbl_table=getlabel(); ffswitch(lbl_table); /* generate the jump table */ setlabel(lbl_table); ffcase(statecount,lbl_default,TRUE); for (state=sc_state_tab.next; state!=NULL; state=state->next) { if (state->index==fsa_id) { /* find the label for this list id */ for (stlist=sym->states->next; stlist!=NULL; stlist=stlist->next) { if (stlist->index!=-1 && state_inlist(stlist->index,(int)state->value)) { ffcase(state->value,stlist->name,FALSE); break; } /* if */ } /* for */ if (stlist==NULL && strtol(lbl_default,NULL,16)==lbl_nostate) error(230,state->name,sym->name); /* unimplemented state, no fallback */ } /* if (state belongs to automaton of function) */ } /* for (state) */ stgwrite("\n"); } /* if (is function, used & having states) */ } /* for (sym) */ }
/* Address of the source must already have been loaded in PRI, the * destination address in ALT. * This routine makes a loop that copies the minor dimension vector * by vector. */ SC_FUNC void copyarray2d(int majordim,int minordim) { int cellshift=(pc_cellsize==8) ? 3 : (pc_cellsize==4) ? 2 : 1; int looplbl=getlabel(); stgwrite("\tpush.alt\n"); stgwrite("\tpush.pri\n"); code_idx+=opcodes(2); if (pc_optimize>=sOPTIMIZE_MACRO) { stgwrite("\tzero.alt\n");/* ALT = index = 0 */ code_idx+=opcodes(1); } else { stgwrite("\tconst.alt 0\n");/* ALT = index = 0 */ code_idx+=opcodes(1)+opargs(1); } /* if */ setlabel(looplbl); stgwrite("\tpush.alt\n"); /* save index */ stgwrite("\tpick 8\n"); /* PRI = dest */ code_idx+=opcodes(2)+opargs(1); if (pc_optimize>=sOPTIMIZE_MACRO) { stgwrite("\txchg\n"); /* ALT = dest, PRI = index */ stgwrite("\tidxaddr\n");/* PRI = dest + index * sizeof(cell) */ code_idx+=opcodes(2); } else { stgwrite("\tshl.c.alt "); outval(cellshift,TRUE,TRUE); /* ALT = index * sizeof(cell) */ stgwrite("\tadd\n"); /* PRI = dest + index * sizeof(cell) */ code_idx+=opcodes(2)+opargs(1); } /* if */ stgwrite("\tpush.pri\n"); stgwrite("\tload.i\n"); /* PRI = dest[index * sizeof(cell)] */ stgwrite("\tpop.alt\n"); /* ALT = dest + index * sizeof(cell) */ stgwrite("\tadd\n"); /* PRI = dest + index * sizeof(cell) + dest[index * sizeof(cell)] */ stgwrite("\tpush.pri\n"); code_idx+=opcodes(5); if (pc_optimize>=sOPTIMIZE_MACRO) { stgwrite("\tpick 8\n"); /* PRI = source */ stgwrite("\txchg\n"); /* ALT = source */ stgwrite("\tpick 4\n"); /* PRI = index */ stgwrite("\tidxaddr\n");/* PRI = source + index * sizeof(cell) */ code_idx+=opcodes(4)+opargs(2); } else { stgwrite("\tpick 4\n"); /* PRI = index */ stgwrite("\txchg\n"); /* ALT = index */ stgwrite("\tshl.c.alt "); outval(cellshift,TRUE,TRUE); /* ALT = index * sizeof(cell) */ stgwrite("\tpick 8\n"); /* PRI = source */ stgwrite("\tadd\n"); /* PRI = source + index * sizeof(cell) */ code_idx+=opcodes(5)+opargs(3); } /* if */ stgwrite("\tpush.pri\n"); stgwrite("\tload.i\n"); /* PRI = source[index * sizeof(cell)] */ stgwrite("\tpop.alt\n"); /* ALT = source + index * sizeof(cell) */ stgwrite("\tadd\n"); /* PRI = source + index * sizeof(cell) + source[index * sizeof(cell)] */ stgwrite("\tpop.alt\n"); /* ALT = dest + index * sizeof(cell) + dest[index * sizeof(cell)] */ stgwrite("\tmovs "); outval(minordim*pc_cellsize,TRUE,TRUE); stgwrite("\tpop.alt\n"); /* ALT = saved index */ stgwrite("\tinc.alt\n"); /* ALT = index + 1 */ code_idx+=opcodes(8)+opargs(1); if (pc_optimize>=sOPTIMIZE_MACRO) { stgwrite("\teq.c.alt "); outval(majordim,TRUE,TRUE); code_idx+=opcodes(1)+opargs(1); } else { stgwrite("\tconst.pri "); outval(majordim,TRUE,TRUE); stgwrite("\teq\n"); /* compare ALT with majordim */ code_idx+=opcodes(2)+opargs(1); } /* if */ stgwrite("\tjzer "); outval(looplbl,TRUE,TRUE); stgwrite("\tpop.pri\n"); /* restore stack & registers */ stgwrite("\tpop.alt\n"); code_idx+=opcodes(3)+opargs(1); }
int main(int argc, char **argv) { int sd, ch, changed; char name[MAXPATHLEN]; int force; /* force label update */ int raw; /* update on-disk label as well */ int verbose; /* verbose output */ int write_it; /* update in-core label if changed */ force = 0; raw = 0; verbose = 1; write_it = 0; while ((ch = getopt(argc, argv, "fqrw")) != -1) { switch (ch) { case 'f': force = 1; break; case 'q': verbose = 0; break; case 'r': raw = 1; break; case 'w': write_it = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); rawpart = getrawpartition(); if (rawpart < 0) err(EXIT_FAILURE, "getrawpartition"); if ((sd = opendisk(argv[0], write_it ? O_RDWR : O_RDONLY, name, (size_t)MAXPATHLEN, 1)) < 0) { perror(argv[0]); exit(1); } getlabel(sd); changed = getparts(sd, verbose); if (verbose) { putchar('\n'); showpartitions(stdout, &label, 0); putchar('\n'); } if (write_it) { if (! changed && ! force) printf("No change; not updating disk label.\n"); else { if (verbose) printf("Updating in-core %sdisk label.\n", raw ? "and on-disk " : ""); raw = 0; /* XXX */ setlabel(sd, raw); } } else { printf("Not updating disk label.\n"); } close(sd); return (0); }