IMD 1.17: 17/11/2010 7:08:54 /usr/sys/sys (file system - process manager) (systems sources)  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  \DCBA@?+  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYtQ`2Q`2G+wQ\2Q\2klmnQV2QV2 defghijQR2QR2Z[\]^_`abcdel*CQ1abcQP2QP2\]^_`QM2QM20 UVWXYZ[QJ2QJ2MNOPQRSTQF2QF2 Qc2Qc2 HIJKLQC2QC2' BCDEFGQ?2Q?2 ;<=>?@AQ;2Q;2H3456789:Q82Q82+,-./012Q42Q42%Q12Q12[Q-2Q-2 Q)2Q)2     Q%2Q%2Q#2Q#2Q 2Q 2Q2Q2 Q2Q2Q2Q2BQ2Qd2?Q2Q2?Q2Q2Q2Q2 Q2Q2 Q 2Q 2 Q 2Q 28Q2Q2BQ2Q2Q2Q2Q2Q2Q2Q2Q1Q1C Q1Q1Q1Q1HQ1Q1Q1Q1 Q1Q10Q1Q1qQ1Q1Q1Q1Q1Q1 {|}~Q1Q1 uvwxyzQ1Q1mnopqrstQ1Q1hijklQ1Q1`abcdefgQ1Q1s'SQ1Q1IJQ1Q1EFGHQ1Q1 ?@ABCDlClC=Q1Q1!+Q1Q1 !"Q1Q1Q1Q1 sually because of an IO error. */ iinit() { register *cp, *bp; bp = bread(rootdev, 1); cp = getblk(NODEV); if(u.u_error) >s_nfree; bcopy(fp->s_free, ip, 100); fp->s_nfree = 0; bwrite(bp); fp->s_flock = 0; wakeup(&fp->s_flock); } fp->s_fr panic(); bcopy(bp->b_addr, cp->b_addr, 256); brelse(bp); mount[0].m_bufp = cp; mount[0].m_dev = rootdev; cp = cp->b_addr; ee[fp->s_nfree++] = bno; fp->s_fmod = 1; } /* * Check that a block number is in the * range between the I list and the size  cp->s_flock = 0; cp->s_ilock = 0; cp->s_ronly = 0; time[0] = cp->s_time[0]; time[1] = cp->s_time[1]; } /* * alloc will ob * of the device. * This is used mainly to check that a * garbage file system has not been mounted. * * bad block on dev x/ytain the next available * free disk block from the free list of * the specified device. * The super block has up to 100 remem -- not in range */ badblock(afp, abn, dev) { register struct filsys *fp; register char *bn; fp = afp; bn = abn; if (bn <bered * free blocks; the last of these is read to * obtain 100 more . . . * * no space on dev x/y -- when * the free list i fp->s_isize+2 || bn >= fp->s_fsize) { panic(); return(1); } return(0); } /* * Allocate an unused I node * on the specis exhausted. */ alloc(dev) { int bno; register *bp, *ip, *fp; fp = getfs(dev); while(fp->s_flock) sleep(&fp->s_flock, PIfied device. * Used with file creation. * The algorithm keeps up to * 100 spare I nodes in the * super block. When this runs...ealloc.cdalloc.ocbio.cbbio.oaclock.c`clock.oNOD); do { if(fp->s_nfree <= 0) goto nospace; bno = fp->s_free[--fp->s_nfree]; if(bno == 0) goto nospace; } while _conf.c^emul.s]fio.c\fio.o[iget.cZiget.oYlow.sXmain.c(badblock(fp, bno, dev)); if(fp->s_nfree <= 0) { fp->s_flock++; bp = bread(dev, bno); ip = bp->b_addr; fp->s_nfree = *iWmain.oVmalloc.cUmalloc.oTmch.oSmch.sRmem.cQmem.oPnami.cp++; bcopy(ip, fp->s_free, 100); brelse(bp); fp->s_flock = 0; wakeup(&fp->s_flock); } bp = getblk(dev, bno); clrbuf(bOnami.oNobiocMpartab.cLpartab.oKprfcJprfoIqxeml.sHrdwri.cp); fp->s_fmod = 1; return(bp); nospace: fp->s_nfree = 0; u.u_error = ENOSPC; return(NULL); } /* * place the specified d# #include "../param.h" #include "../systm.h" #include "../filsys.h" #include "../conf.h" #include "../buf.h" #include "../inodeisk block * back on the free list of the * specified device. */ free(dev, bno) { register *fp, *bp, *ip; fp = getfs(dev); .h" #include "../user.h" /* * iinit is called once (from main) * very early in initialization. * It reads the root's super b while(fp->s_flock) sleep(&fp->s_flock, PINOD); if (badblock(fp, bno, dev)) return; if(fp->s_nfree <= 0) { fp->s_nfree =lock * and initializes the current date * from the last modified date. * * panic: iinit -- cannot read the super * block. U 1; fp->s_free[0] = 0; } if(fp->s_nfree >= 100) { fp->s_flock++; bp = getblk(dev, bno); ip = bp->b_addr; *ip++ = fp- k some more. */ iput(ip); goto loop; } fp->s_ilock++; ino = 0; for(i=0; is_isize; i++) { bp = bread(dev, i+2);unt * check failed. At this point, all * the counts are zeroed which will * almost certainly lead to "no space" * diagnostic ip = bp->b_addr; for(j=0; j<256; j=+16) { ino++; if(ip[j] != 0) continue; for(k=0; ks_inode[fp->s_ninode++] = ino; if(fp->s_ninode >= 100) brer *n1, *n2; for(p = &mount[0]; p < &mount[NMOUNT]; p++) if(p->m_bufp != NULL && p->m_dev == dev) { p = p->m_bufp->b_addr; ak; cont:; } brelse(bp); if(fp->s_ninode >= 100) break; } fp->s_ilock = 0; wakeup(&fp->s_ilock); if (fp->s_ninode n1 = p->s_nfree; n2 = p->s_ninode; if(n1 > 100 || n2 > 100) { p->s_nfree = 0; p->s_ninode = 0; } return(p); } p > 0) goto loop; u.u_error = ENOSPC; return(NULL); } /* * Free the specified I node * on the specified device. * The alganic(); } /* * update is the internal name of * 'sync'. It goes through the disk * queues to initiate sandbagged IO; * goesorithm stores up * to 100 I nodes in the super * block and throws away any more. */ ifree(dev, ino) { register *fp; fp = g through the I nodes to write * modified nodes; and it goes through * the mount table to initiate modified * super blocks. */ update() { register struct inode *ip; register struct mount *mp; register *bp; if(updlock) return; updlock++; for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if(mp->m_bufp != NULL) { ip = mp->m_bufp->b_addr; if(ip->s_fmod==0 || ip->s_ilock!=0 || ip->s_flock!=0 || ip->s_ronly!=0) continue; bp = getblk(mp->m_dev, 1); ip->s_fmod = 0; ip->s_time[0]  out, * a linear search through the * I list is instituted to pick * up 100 more. */ ialloc(dev) { register *fp, *bp, *ip;  int i, j, k, ino; fp = getfs(dev); while(fp->s_ilock) sleep(&fp->s_ilock, PINOD); loop: if(fp->s_ninode > 0) { ino = fpetfs(dev); if(fp->s_ilock) return; if(fp->s_ninode >= 100) return; fp->s_inode[fp->s_ninode++] = ino; fp->s_fmod = 1; } ->s_inode[--fp->s_ninode]; ip = iget(dev, ino); if (ip==NULL) return(NULL); if(ip->i_mode == 0) { for(bp = &ip->i_mo /* * getfs maps a device number into * a pointer to the incore super * block. * The algorithm is a linear * search throughde; bp < &ip->i_addr[8];) *bp++ = 0; fp->s_fmod = 1; return(ip); } /* * Inode was allocated after all. * Loo the mount table. * A consistency check of the * in core free-block and i-node * counts. * * bad count on dev x/y -- the co ]; ip++) if((ip->i_flag&ILOCK) == 0) { ip->i_flag =| ILOCK; iupdat(ip); prele(ip); } updlock = 0; bflush(NODEV); II)} (8)i(Hw    & % 744477ww ))N e  I  `5?Nf %  !Nf de )% 2e Nf  w2  w N &e Nf& % XX(; 4 %d#Nf d&e %4  4e  apww i)xDCe - w w N &e *  a5Nf  ex)xII e wt  5 5 KNef 5 @ ` %5 AWpq-AxX8HXX)_canonb _swapmap _rootdir _lbolt _time _tout Wpq- %2 ap%de% %d 5#4e w N _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _bdevsw _nblkdev%d  apwdw ` L-%d%d4 4 e% ww   _cdevsw _nchrdev _buf X_bfreeli _inode _u &_iinit"~iinitcpbpcsvN  *#  4& % e%΂̵ _bread _getblk L2(_panic _bcopy _brelse cret _alloc"j~allocjbp= time[0]; ip->s_time[1] = time[1]; bcopy(ip, bp->b_addr, 256); bwrite(bp); } for(ip = &inode[0]; ip < &inode[NINODE  e%7 x wliyy /proc.h" /* * This is the set of buffers proper, whose heads * were declared in buf.h. There can exist buffer * headers notlag&B_DELWRI)==0) geterror(rbp); } /* * Release the buffer, marking it so that if it is grabbed * for another purpose it wi pointing here that are used purely * as arguments to the I/O routines to describe * I/O to be done-- e.g. swbuf, just below, ll be written out before being * given up (e.g. when writing a partial block where it is * assumed that another write for the fpipdevbno_getfs"L4L20001|_sleep L8L9*_badblocfor * swapping. */ char buffers[NBUF][512]; struct buf swbuf; /* * The following several routines allocate and free * buffe"L10_wakeup _clrbuf L3&_free"8~free8bpfpipdevbnors with various side effects. In general the * arguments to an allocate routine are a device and * a block number, and the vaL12XL20003HL11L14L15_bwrite ~badblocbnfpabnlue is a pointer to * to the buffer header; the buffer is marked "busy" * so that no on else can touch it. If the block was afpdevL10000L17L16_ialloc"~iallocbpfpipi* already in core, no I/O need be done; if it is * already busy, the process waits until it becomes free. * The following routjkdevinoL19<L20005,L21L20011D_iget L23L200ines allocate a buffer: * getblk * bread * Eventually the buffer must be released, possibly with the * side effect of writin18hL18L20009lL25vL20007t_iput L27BL20017L20015L32"L20013g it out, by using one of * bwrite * bdwrite * bawrite * brelse */ /* * Read in (if necessary) the block and return a bufL35L310L28H_ifree"d~ifreedfpdevinoL37~getfspfer pointer. */ bread(dev, blkno) { register struct buf *rbp; rbp = getblk(dev, blkno); if (rbp->b_flags&B_DONE) return(rdevn1n2L20020L41L10002L43L38_update"~updatebpbp); rbp->b_flags =| B_READ; rbp->b_wcount = -256; (*bdevsw[dev.d_major].d_strategy)(rbp); iowait(rbp); return(rbp); } /* ipmpL44L20022L47VL20024dL51z_iupdat _prele _bflush  * Write the buffer, waiting for completion. * Then release the buffer. */ bwrite(bp) struct buf *bp; { register struct buf *rbp; register flag; rbp = bp; flag = rbp->b_flags; rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI); rbp->b_wcount # /* */ #include "../param.h" #include "../user.h" #include "../buf.h" #include "../conf.h" #include "../systm.h" #include "..= -256; (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp); if ((flag&B_ASYNC) == 0) { iowait(rbp); brelse(rbp); } else if ((f /* * Assign a buffer for the given block. If the appropriate * block is already associated, return it; otherwise search * foB_BUSY | B_RELOC; bp->b_back->b_forw = bp->b_forw; bp->b_forw->b_back = bp->b_back; bp->b_forw = dp->b_forw; bp->b_back = dpr the oldest non-busy buffer and reassign it. * When a 512-byte area is wanted for some random reason * (e.g. during exec, for; dp->b_forw->b_back = bp; dp->b_forw = bp; bp->b_dev = dev; bp->b_blkno = blkno; return(bp); } /* * Wait for I/O complet the user arglist) getblk can be called * with device NODEV to avoid unwanted associativity. */ getblk(dev, blkno) { registerion on the buffer; return errors * to the user. */ iowait(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; spl6() struct buf *bp; register struct devtab *dp; if(dev.d_major >= nblkdev) panic(); loop: if (dev < 0) dp = &bfreelist; while ((rbp->b_flags&B_DONE)==0) sleep(rbp, PRIBIO); spl0(); geterror(rbp); } /* * Unlink a buffer from the available l; else { dp = bdevsw[dev.d_major].d_tab; if(dp == NULL) panic(); for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) { iist and mark it busy. * (internal interface) */ notavail(bp) struct buf *bp; { register struct buf *rbp; register int sps; same block will soon follow). */ bdwrite(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; rbp->b_flags =| B_DELWRIf (bp->b_blkno!=blkno || bp->b_dev!=dev) continue; spl6(); if (bp->b_flags&B_BUSY) { bp->b_flags =| B_WANTED;  | B_DONE; brelse(rbp); } /* * Release the buffer, start I/O on it, but don't wait for completion. */ bawrite(bp) struct bufsleep(bp, PRIBIO); spl0(); goto loop; } spl0(); notavail(bp); return(bp); } } spl6(); if (bfreelist.av_ *bp; { register struct buf *rbp; rbp = bp; rbp->b_flags =| B_ASYNC; bwrite(rbp); } /* * release the buffer, with no I/O forw == &bfreelist) { bfreelist.b_flags =| B_WANTED; sleep(&bfreelist, PRIBIO); spl0(); goto loop; } spl0(); notavailimplied. */ brelse(bp) struct buf *bp; { register struct buf *rbp, **backp; register int sps; rbp = bp; if (rbp->b_flags&B#$%&'()*,-./01234_WANTED) wakeup(rbp); if (bfreelist.b_flags&B_WANTED) { bfreelist.b_flags =& ~B_WANTED; wakeup(&bfreelist); } if (rbp->b_flags&B_ERROR) rbp->b_dev.d_minor = -1; /* no assoc. on error */ backp = &bfreelist.av_back; #ifdef QX sps = getps(); #endif #ifndef QX sps = PS->integ; #endif spl6(); rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC); (*backp)->av_forw = rbp; rbp->av_back = *backp; *backp = rbp; rbp->av_forw = &bfreelist; #ifdef QX putps(sps); #endif #ifndef QX PS->integ = sps; #endif } (bp = bfreelist.av_forw); if (bp->b_flags & B_DELWRI) { bp->b_flags =| B_ASYNC; bwrite(bp); goto loop; } bp->b_flags =   register *p; register c; p = bp->b_addr; c = 256; do *p++ = 0; while (--c); } /* * Initialize the buffer I/O system br; #endif #ifndef VSWAP swbuf.b_blkno = SWPLO + rp->p_pid*SWPSIZ; #endif swbuf.b_addr = &u; /* 64 b/block */ (*bdevsw[swapdevy freeing * all buffers and setting all device buffer lists to empty. */ binit() { register struct buf *bp; register struct >>8].d_strategy)(&swbuf); spl6(); while((swbuf.b_flags&B_DONE)==0) idle(); spl0(); if(rdflg == B_READ) { p1 = TOPUSR; devtab *dp; register int i; struct bdevsw *bdp; bfreelist.b_forw = bfreelist.b_back = bfreelist.av_forw = bfreelist.av_p2 = (pp->p_size<<6) + TOPSYS - (USIZE<<6); if(p2 <= p1) while(p1 >= USTACK->integ.intp) *--p1 = *--p2; #ifdef VSWAP back = &bfreelist; for (i=0; ib_dev = -1; bp->b_addr = buffers[i]; bp->b_back = &bfreelmfree(swapmap,(pp->p_size + 7)/8,pp->p_addr); #endif } swbuf.b_flags =& ~(B_BUSY|B_WANTED); return(swbuf.b_flags&B_ERROR); } ist; bp->b_forw = bfreelist.b_forw; bfreelist.b_forw->b_back = bp; bfreelist.b_forw = bp; bp->b_flags = B_BUSY; brelse /* * make sure all write-behind blocks * on dev (or NODEV for all) * are flushed out. * (from umount and update) */ bflush(bp); } i = 0; for (bdp = bdevsw; bdp->d_open; bdp++) { dp = bdp->d_tab; if(dp) { dp->b_forw = dp; dp->b_back = dp;(dev) { register struct buf *bp; loop: spl6(); for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { if (bp-> } i++; } nblkdev = i; } /* * swap I/O */ #define USTACK (TOPSYS-12) struct { int *intp;}; struct {char *chrp;}; swapb_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { bp->b_flags =| B_ASYNC; notavail(bp); bwrite(bp); goto loop; (rp, rdflg) struct proc *rp; { register *pp, *p1, *p2; pp = rp; if(rdflg == B_WRITE) { p1 = USTACK->integ; p2 = TOPSYS + } } spl0(); } /* * Pick up the device's error number and pass it to the user; * if there is an error but the number is 0 s rbp = bp; #ifdef QX sps = getps(); #endif #ifndef QX sps = PS->integ; #endif spl6(); rbp->av_back->av_forw = rbp->av_forw;  (u.u_dsize<<6) + (p1.integ&077); if(p2 <= p1) { pp->p_size = u.u_dsize + USIZE + ((TOPUSR>>6)&01777) - ((p1.integ>> rbp->av_forw->av_back = rbp->av_back; rbp->b_flags =| B_BUSY; #ifdef QX putps(sps); #endif #ifndef QX PS->integ = sps; #endi6)&01777); while(p1.chrp < TOPUSR) *p2++ = *p1++; } else pp->p_size = SWPSIZ<<3; #ifdef VSWAP pp->p_addr = mallocf } /* * Mark I/O complete on a buffer, release it if I/O is asynchronous, * and wake up anyone waiting for it. */ iodone(bp(swapmap,(pp->p_size+7)/8); if(pp->p_addr == NULL) panic(); #endif } #ifdef DEBUG printf("Swap (%d) id %d size %d addr ) struct buf *bp; { register struct buf *rbp; rbp = bp; rbp->b_flags =| B_DONE; if (rbp->b_flags&B_ASYNC) brelse(rbp); e%d\n", rdflg, pp->p_pid, (((pp->p_size+7)& ~07)<<5) >> 7, pp->p_addr); #endif spl6(); swbuf.b_flags = B_BUSY | rdflg; swbuflse { rbp->b_flags =& ~B_WANTED; wakeup(rbp); } } /* * Zero the core associated with a buffer. */ clrbuf(bp) int *bp; { .b_dev = swapdev; swbuf.b_wcount = -(((pp->p_size+7)&~07)<<5); /* 32 words per block */ #ifdef VSWAP swbuf.b_blkno = pp->p_add  .u_error = EIO; } ))))((()Iy(())(8yw Nf  5wU &@t   w DE & t  5 )) 5 wvw rDU w`w \DU BwJw FD5@ 5@0E@( 5 ))  EH0  ww @-  %:U@ @t ))())))x())) t-t-  v5U@& ` <wT JL <5U B008I) 03t tw D & 5  ww D  00U wy998w DU5 E@ whw d@ ~wPw L 7J7D7>78 WpDe t e4)x) 07 %  @ e ww D 6_vtE@`e`)() )_u &_buf X_bfreeli _bdevsw \eWtE@4%et 4  > :@U7.*2eEt 77 _nblkdev _cdevsw _nchrdev _canonb _swapmap _rootdir _lbolt _time _tout _callout _moutt   5 %te\  _et& %EHnt _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _proc _buffers _swbuf et a generalized * code. Actually the latter is always true because devices * don't yet return specific errors. */ geterror(Eww %5- U < B \^5% Bw>w :D57aYwabp) struct buf *abp; { register struct buf *bp; bp = abp; if (bp->b_flags&B_ERROR) if ((u.u_error = bp->b_error)==0) u)88)   if((ps&0340) != 0) goto out; /* * callout */ spl5(); if(callout[0].c_time <= 0) { p1 = &callout[0]; while(p1->c__bread"~breaddevblknorbpcsv _getblk"L2 L20000cret _iowait"_bwrite"B~bwriteBbpflagrbpL4z_brelse"L3_geterro"_bdwrite"~bdwhL55FL54LL20016D_mfree _bflush"z~bflushzbpdevL58L20018L100ritebprbp_bawrite"~bawritebprbp~brelsebpbackprbp00L61L59L20020~geterrobpabpL63spsL10_wakeup L11L12_getps _spl6 _putps ~getblkbpdpdevblknoL15V_panic L20002.L172L23L20005L_sleep _spl0 L18nL19rL21L22_notavai"<L20006L24~iowaitbprbpL26(# #include "../param.h" #include "../systm.h" #include "../user.h" #include "../proc.h" /* * clock is called straight from * L20008~notavai<bprbpsps_iodone"p~iodonepbprbpL30L29the real time clock interrupt. * * Functions: * reprime clock * implement callouts * maintain user/system times * maintain_clrbuf"~clrbufbpcpL35_binit"~binitbpdpi date * profile * tout wakeup (sys sleep) * lightning bolt wakeup (every 4 sec) * alarm clock signals * jab the scheduler bdpL20010L40:L20012 L432_swap"H~swapHrppprdflg*/ clock(dev, sp, r1, nps, r0, pc, ps) char *pc; { register struct callo *p1, *p2; register struct proc *pp; int a; #ifdefp1p2L45L46L47L49_malloc L51L20014_idle L53 QX #ifndef SA /* * update graphics screen */ lkint(); #endif #endif /* * restart clock */ #ifndef QX *lks = 0115;56789:;<> #endif /* * callouts * if none, just return * else update first non-zero time */ if(callout[0].c_func == 0) goto out; p2 = &callout[0]; while(p2->c_time<=0 && p2->c_func!=0) p2++; p2->c_time--; /* * if ps is high, just return */  has the effect of * updating all entries. */ timeout(fun, arg, tim) { register struct callo *p1, *p2; register t; int s; y_canonb _swapmap _rootdir _lbolt _time t = tim; #ifdef QX s = getps(); #endif #ifndef QX s = PS->integ; #endif p1 = &callout[0]; spl7(); while(p1->c_func != 0 && _tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _up1->c_time <= t) { t =- p1->c_time; p1++; } p1->c_time =- t; p2 = p1; while(p2->c_func != 0) p2++; while(p2 >= p1) {  &_proc _clock"~clockpcsppsppadevnps r1 (p2+1)->c_time = p2->c_time; (p2+1)->c_func = p2->c_func; (p2+1)->c_arg = p2->c_arg; p2--; } p1->c_time = t; p1->c_fur0 p1p2csv _lkint L2tL3 L20001L4$_spl5 func != 0 && p1->c_time <= 0) { (*p1->c_func)(p1->c_arg); p1++; } p2 = &callout[0]; while(p2->c_func = p1->c_func) {nc = fun; p1->c_arg = arg; #ifdef QX putps(s); #endif #ifndef QX PS->integ = s; #endif }  p2->c_time = p1->c_time; p2->c_arg = p1->c_arg; p1++; p2++; } } /* * lightning bolt time-out * and time of day */ out: if(pc > TOPSYS) u.u_utime++; else u.u_stime++; pp = u.u_procp; if(++lbolt >= HZ) { if((ps&0340) != 0)  return; if((time[1]&03)==0) wakeup(&lbolt); lbolt =- HZ; if(++time[1] == 0) ++time[0]; spl1(); if(time[1]==tow 2 e  5#   &  e  3ee3ut[1] && time[0]==tout[0]) wakeup(tout); #ifdef QX if((time[1]&07) == 0) { #endif #ifndef QX if((time[1]&01) == 0) { #end%`   r%<lH5D5^ <L J B >-<:-20 ʋ    if runrun++; } for(pp = &proc[0]; pp < &proc[NPROC]; pp++) if (pp->p_stat) { if(pp->p_clktim) if(--pp->p_clktim  e%%` @e 7  ww B 5  e e  == 0) psignal(pp, SIGCLK); } if(pc > TOPSYS) { u.u_ar0 = &r0; if(issig()) psig(); } } } /* * timeout is  !ttN wfihIihcalled to arrange that * fun(arg) is called in tim/HZ seconds. * An entry is sorted into the callout * structure. The time inh99I89II YIYIX each structure * entry is the number of HZ's more * than the previous entry. * In this way, decrementing the * first entry HYiyh)  # #include "../param.h" /* */ int (*bdevsw[])() { #ifdef QX &nulldev, &nulldev, &qxstrategy, &qxtab, #endif #ifdef SA &nul11/10 / / / This program is designed to allow the use / of the PDP 11/40 instruction set on the PDP 11/10 / in an environmldev, &nulldev, &sastrategy, &satab, #endif #ifndef QX &nulldev, &nulldev, &rkstrategy, &rktab, /* &nulldev, &tcclose, &tcstraent which handles traps in the / same manner as the UNIX operating system. / This program returns the same results / and tegy, &tctab, */ /* &tmopen, &tmclose, &tmstrategy, &tmtab, */ #endif 0, }; int (*cdevsw[])() { &klopen, &klclose, &klread,condition codes that the internal DEC / instruction does on the PDP 11/40. This allows / programs which run under UNIX on a &klwrite, &klsgtty, &nulldev, &nulldev, &mmread, &mmwrite, &nodev, /* &lpopen, &lpclose, &nodev, &lpwrite, &nodev, */ 0, };n 11/40 to / be run on an 11/10 with a UNIX-like system. / The functions implimented are listed below: / multiply (MUL) / d ivide (DIV) / arithmetic shift (ASH) / arithmetic shift combined (ASHC) / exclusive OR (XOR) / subtract one and branch (SOB) / / / / / Upon entry to this program the stack is assumed / to look as follows: / / < bottom portion of stack > / UPS -- user's program status word at time of trap / UPC -- user's program counter at time of trap / UR0 -- user's r0 at time of trap / ---L6PL20003>L7VL8lL20005\L10L11L1&L13_wakeup L14_spl1 L15L20007L18_psignal _issig _psig cret _timeout"*~timeout*arg.globl nofault,emtrap,trapem rti = 2 PS = 177776 / / trapem: mov *$PS,-4(sp) / trap type mov r0,-(sp) tst -(sp) mov r1,-(sstfuntimp1p2_getps _spl7 L25PL20009Fp) mov $12.,-(sp) add sp,*sp mov 4(sp),-(sp) bic $!17,*sp jsr pc,trapems tst (sp)+ mov (sp)+,r0 / return stack pointer mL26VL27`L20011\L29|L20013h_putps ov (sp)+,r1 tst (sp)+ add $6,sp cmp sp,r0 blos 0f sub $6,sp sub $6,r0 mov (sp)+,(r0)+ mov (sp)+,(r0)+ mov -12.(sp),(r0) / copy in PS word mov r0,sp sub $4,sp br 1f 0: mov -14.(sp),-2(sp) / copy in PS word mov -(sp),-(r0) mov -(sp),-(r0) mov -(sp),-(r0) mov r0,sp 1: mov (sp)+,r0 rti / return from emulation / / / / / EXTENDED INSTRUCTION SET EMULATOR FOR PDP  / This causes the stack to look as follows: / / < bottom portion of stack > / UPS / UPC / UR0 / --- / UR1 / USP / DEV / RPC /  to be performed mov (sp),r4 bic $170777,r4 swab r4 jmp *fcntbl(r4) fcntbl: smul / multiply sdiv / divide sash / arithmetUR5 : user's r5 <--- register 5 points here / UR4 : user's r4 / UR3 : user's r3 / UR2 : user's r2 / nfaddr : used to hold olic shift sashc / arithmetic shift combined sxor / exclusive OR errrtn / unimplimented errrtn / unimplimented ssob / subtracd nofault address / PCFLG : used to hold value to increment UPC by / DSTN : used to hold address of destination field / MODMAP t one and branch / / / / this routine performs the multiply function / smul: jsr pc,getsrc / set up flags for proper sign manag: used to hold interim condition codes / INST: used to hold instruction being emulated <--- stack pointer / < top of stack > / /ement mov r0,r1 bge 1f neg r1 inc r3 1: clr r0 tst r2 bge 1f neg r2 dec r3 1: / set counter for 17 cycles mov $21,-(sp / / / UPC =16 UPS =20 MODMAP =2 INST =0 DSTN =4 PCFLG =6 nfaddr =10 / / / .text / / .globl csv, cret / / / emul2.o = . / trapKLMNOPQRTUVWXYZ[\]^_ems: jsr r5,csv sub $12,sp / set up to catch traps which occur during emululation mov nofault,nfaddr(sp) mov $errrtn,nofault / find instruction which caused trap mov UPC(r5),r0 mov UPS(r5),UPS-12.(r5) / put PS in safe place mov -(r0),(sp) / is it one to be emululated? cmp (sp),$070000 / 170000 for 40 testing / 070000 for 10 use bgt 1f / bhis for 40 testing / bgt for 10 use mov (sp),r0 bic $77,r0 cmp r0,$6700 beq ssxt jmp errrtn ssxt: jsr pc,getsrc bis $4,(r4) /set z-bit clr *DSTN(s) 2: / use shift and add algorithm clc ror r0 ror r1 bcc 1f add r2,r0 1: dec (sp) bne 2b / were signs the same? cmp r3,(p) bit $10,UPS-12.(r5) / n-bit on? beq 0f dec *DSTN(sp) bic $4,(r4) /clear z-bit 0: mov $4,r2 jmp setcc 1: / / / / / thissp)+ beq 1f / no, negate the product neg r0 neg r1 sbc r0 1: / was product greater than 15 bits long? tst r1 bpl 1f cmp $ -- not used by this program / UR1 -- user's r1 / USP -- user's stack pointer / DEV -- trap type / RPC -- return address to routine gets the even-odd register pair / specified in the instruction and moves / them into r0 and r1 / / find register nu trap routine / < top of stack > / / / / / After it is determined that the trap is an illegal / instruction trap ( DEV = 1 )mber = n mov (sp),r4 bic $177077,r4 asl r4 asl r4 swab r4 / move register(n) into r0 movb regs(r4),r3 add r5,r3 mov (r3), a register save routine / is used which saves the other user registers and / allocates temporary space for variables. / ,r0 / move register(n ORed with 1) into r1 bis $1,r4 movb regs(r4),r3 add r5,r3 mov (r3),r1 / / / find out which function is -1,r0 bne 2f br 3f 1: tst r0 beq 3f 2: / if so, set the C bit bis $1,*r4 3: / was the register odd? bit $100,(sp) beq 1f beq div37 neg r0 jmp div26 div29: neg r0 div37: mov r1,r3 neg r1 com r3 jmi div26 clr *r4 tst r1 beq 2f bpl 1f bis $/ if so, move product to r0 mov r1,r0 1: / set up flags and quit mov $1,r3 mov $17,r2 jmp strreg / / / / / this routine perf10,*r4 br div42 2: bis $4,*r4 1: bis $2,*r4 div42: / exit procedure mov (sp)+,r5 mov r0,r3 mov r1,r0 mov r3,r1 mov $1,r3orms the division function / the algorithm used is taken directly / from the DEC microcode flow in order / to make all con mov $-17,r2 jmp strreg / / / / / this routine performs the arithmetic shift function / sash: jsr pc,getsrc br 1f / / / / / dition codes and results / agree in all cases. / sdiv: / if an odd register instruction, error bit (sp),$100 beq 1f jmp errthis routine performs the arithmetic shift combined function / sashc: jsr pc,getsrc inc r3 1: / get shift distance bic $17770rtn 1: jsr pc,getsrc mov r5,-(sp) mov r1,r5 / is divisor 0? tst r2 bne div5 / if so, quit bis $7,*r4 br div12 div5: / is 0,r2 bit $40,r2 beq 1f bis $177700,r2 2: / right shift tst r3 beq 3f / for ashc asr r0 ror r1 br 4f 3: / for ash asr r0dividend negative? tst r0 bge div16 / yes bis $17,*r4 neg r0 clr r1 sub r5,r1 sbc r0 bpl div16 div12: / error exit bis  4: bic $1,*r4 bcc 5f bis $1,*r4 5: inc r2 bne 2b br 9f 1: / left shift tst r2 beq 9f 1: tst r3 beq 3f / for ashc asl$2,*r4 mov (sp)+,r5 mov $17,r2 jmp setcc div16: / first step of algorithm mov r2,r3 neg r3 clc rol r1 rol r0 tst r2 bm r1 rol r0 br 4f 3: / for ash asl r0 4: bvc 2f bis $2,*r4 2: bic $1,*r4 bcc 5f bis $1,*r4 5: dec r2 bgt 1b 9: tst r3 i 1f add r3,r0 br 2f 1: add r2,r0 2: adc r1 bic $1,*r4 / test for overflow condition bit $1,r1 beq 1f tst r0 jne div12  bne 7f / for ash mov r0,r1 br 8f 7: bit $100,(sp) beq 8f / for ashc mov r1,r0 8: / exit mov $17,r2 jmp strreg / / / / /  clr r5 tst r2 bge 3f inc r5 3: bit $10,*r4 beq 3f inc r5 3: ror r5 jcc div12 1: / if no overflow, interate algorithm 15this routine performs the exclusive OR function / using A xor B = A and NOT B or B and NOT A / sxor: jsr pc,getsrc mov r0,r1 times mov $17,-(sp) div19: clc rol r1 rol r0 clr r5 tst r2 bpl 1f inc r5 1: bit $2,r1 beq 1f inc r5 1: ror r5 bcc  bic r2,r0 / A AND NOT B bic r1,r2 / B AND NOT A bis r0,r2 / A XOR B mov r2,*DSTN(sp) bvc 1f bis $2,*r4 1: mov r2,r0 clr1f add r3,r0 br 2f 1: add r2,r0 2: adc r1 dec (sp) bne div19 / branch to appropriate cleanup and condition code routines  r1 mov $16,r2 jmp setnz / / / / / this routine performs the subtract one and / branch function / ( untested ) / ssob: movcmp r2,(sp)+ bgt 1f bit $1,r1 beq div31 bne div33 1: bit $1,r1 bne div23 div27: add r2,r0 div23: bit $10,*r4 bne div29  (sp),r2 bic $177700,r2 / subtract 1 dec r0 beq 1f / modify PC asl r2 sub r2,UPC(r5) 1: /exit clr r3 clr r2 jmp strreg /div26: clr *r4 tst r1 beq 2f bpl 1f bis $10,*r4 br 1f 2: bis $4,*r4 1: jmp div42 div31: sub r2,r0 div33: bit $10,*r4  / / / / this routine performs the decoding and / fetching of the source operand and / places it in register 2 / getsrc:  n mov (sp),r4 bic $177077,r4 asl r4 asl r4 swab r4 / single (r0) or double (r0-r1) register store tst r3 beq 1f /store r1file[rf]; if(fp != NULL) return(fp); bad: u.u_error = EBADF; return(NULL); } /* * Internal form of close. * Decrement re in r(n ORed with 1) mov r4,r3 bis $1,r3 movb regs(r3),r3 add r5,r3 mov r1,(r3) 1: / store r0 in r(n) movb regs(r4),r3 adference count on * file structure and call closei * on last closef. * Also make sure the pipe protocol * does not constipated r5,r3 mov r0,(r3) / branch to next routine by flag tst r2 bge setnz neg r2 br setcc / / / / / this routine cause a return. */ closef(fp) int *fp; { register *rfp, *ip; rfp = fp; if(rfp->f_count <= 1) closei(rfp->f_inode, rfp->f_flag&FWRITE); mov INST+2(sp),r4 mov r4,r3 bic $177770,r4 / register bic $177707,r3 / mode asr r3 asr r3 clr PCFLG+2(sp) / if PC addressi to the regular / trap handler if an error is found so a normal / illegal instruction trap can be signalled / errrtn: mov nng cmp r4,$7 bne 1f mov $2,PCFLG+2(sp) / then modes 1,4 and 5 are errors cmp r3,$2 jeq errrtn cmp r3,$10 jeq errrtn cmp faddr(sp),nofault sub $6,r5 mov r5,sp mov (sp)+,r2 mov (sp)+,r3 mov (sp)+,r4 mov (sp)+,r5 add $6,sp mov (sp)+,r1 tst (sr3,$12 jeq errrtn 1: asr r3 bic $1,r3 movb regs(r4),r4 add r5,r4 jmp *mods(r3) mods: 0f / modes 0,1 1f / 2,3 2f /p)+ mov (sp)+,r0 jmp emtrap / / / / / this routine sets the condition codes for / the n and z bits / setnz: tst r0 bgt set 4,5 3f / 6,7 0: / contents of register mov r4,r2 br 4f 1: / autoincrementing mov (r4),r2 add $2,(r4) br 4f 2:cc blt 1f tst r1 bne setcc bis $4,MODMAP(sp) br setcc 1: bis $10,MODMAP(sp) / / / / / this routine sets the proper conditi / autodecrementing sub $2,(r4) mov (r4),r2 br 4f 3: / indexed mov (r4),r2 mov UPC(r5),r3 add $2,UPC(r5) add PCFLG+2(sp),on codes / in the user's PS and jumps to cret which / cleans up the stack and causes the / return to the user / setcc: br2 add (r3),r2 4: / address of location in r2 / is mode indirect? bit $10,INST+2(sp) beq 5f / if so, new address to r2 mov (ic r2,UPS-12.(r5) com r2 bic r2,MODMAP(sp) bis MODMAP(sp),UPS-12.(r5) mov nfaddr(sp),nofault jmp cret / / / / r2),r2 5: / effective address to DSTN mov r2,DSTN+2(sp) / contents to r2 mov (r2),r2 clr r3 mov $MODMAP+2,r4 add sp,r4 clr *r4 rts pc / / / / / this table contains the offset in bytes of the / user's registers in the stack based at r5 / .data r# #include "../param.h" #include "../user.h" #include "../filsys.h" #include "../file.h" #include "../conf.h" #include "../inodeegs: .byte 14 / r0 .byte 10 / r1 .byte -6 / r2 .byte -4 / r3 .byte -2 / r4 .byte 0 / r5 .byte 6 / r6 .byte 16 / r7 .t.h" #include "../reg.h" /* * Convert a user supplied * file descriptor into a pointer * to a file structure. * Only task isext / / / / / this routine stores the results of the operation / into the proper registers / strreg: / find register number =  to check range * of the descriptor. */ getf(f) { register *fp, rf; rf = f; if(rf<0 || rf>=NOFILE) goto bad; fp = u.u_o switch(rip->i_mode&IFMT) { case IFCHR: if(maj >= nchrdev) goto bad; (*cdevsw[maj].d_open)(dev, rw); break; case IFBcture. * Initialize the descriptor * to point at the file structure. * * no file -- if there are no available * file strucLK: if(maj >= nblkdev) goto bad; (*bdevsw[maj].d_open)(dev, rw); } return; bad: u.u_error = ENXIO; } /* * Check modtures. */ falloc() { register struct file *fp; register i; if ((i = ufalloc()) < 0) return(NULL); for (fp = &file[0]; fpe permission on inode pointer. * Mode is READ, WRITE or EXEC. * In the case of WRITE, the * read-only status of the file * s < &file[NFILE]; fp++) if (fp->f_count==0) { u.u_ofile[i] = fp; fp->f_count++; fp->f_offset[0] = 0; fp->f_offset[1ystem is checked. * Also in WRITE, prototype text * segments cannot be written. * The mode is shifted to select * the owner/] = 0; return(fp); } u.u_error = ENFILE; return(NULL); } group/other fields. * The super user is granted all * permissions. */ access(aip, mode) int *aip; { register *ip, m; ip = aip; m = mode; if(m == IWRITE) { if(getfs(ip->i_dev)->s_ronly != 0) { u.u_error = EROFS; return(1); } } if(u.u_uid rfp->f_count--; } /* * Decrement reference count on an * inode due to the removal of a * referencing file structure. * On  == 0) return(0); if(u.u_uid != ip->i_uid) { m =>> 6; } if((ip->i_mode&m) != 0) return(0); bad: u.u_error = EACCES; the last closei, switchout * to the close entry point of special * device handler. * Note that the handler gets called * on return(1); } /* * Look up a pathname and test if * the resultant inode is owned by the * current user. * If not, try for suevery open and only on the last * close. */ closei(ip, rw) int *ip; { register *rip; register dev, maj; rip = ip; dev = rper-user. * If permission is granted, * return inode pointer. */ owner() { register struct inode *ip; if ((ip = namei(0)) ip->i_addr[0]; maj = rip->i_addr[0].d_major; if(rip->i_count <= 1) switch(rip->i_mode&IFMT) { case IFCHR: (*cdevsw[maj].d== NULL) return(NULL); if(u.u_uid == ip->i_uid) return(ip); if (suser()) return(ip); iput(ip); return(NULL); } /* * _close)(dev, rw); break; case IFBLK: (*bdevsw[maj].d_close)(dev, rw); } iput(rip); } /* * openi called to allow handleTest if the current user is the * super user. */ suser() { if(u.u_uid == 0) return(1); u.u_error = EPERM; return(0); } r * of special files to initialize and * validate before actual IO. * Called on all sorts of opens * and also on mount. */ /* * Allocate a user file descriptor. */ ufalloc() { register i; for (i=0; ii_addr[0]; maj = rip->i_addr[0].d_major; u.u_ar0[R0] = i; return(i); } u.u_error = EMFILE; return(-1); } /* * Allocate a user file descriptor * and a file stru  04 4 we% ` ` "~fallocfpiL37L20020L36L20017L20019 HH(YH(9  X H # #include "../param.h" #include "../systm.h" #include "../user.h" #include "../inode.h" #include "../filsys.h" #include "../con  f.h" #include "../buf.h" /* * Look up an inode by device,inumber. * If it is in core (in the inode structure), * honor the l_u &_file _bdevsw _nblkdev _cdevsw _nchrdev _inode _getf"~getffpocking protocol. * If it is not in core, read it in from the * specified device. * If the inode is mounted on, perform * therffcsv L2 L1cret _closef"*~closef*fpiprfp indicated indirection. * In all cases, a pointer to a locked * inode structure is returned. * * panic: no imt -- if the mouL5J_closei"RL10001$L10002(L10L11L7~closeiRiprwmajnted file * system is not in the mount table. * "cannot happen" */ iget(dev, ino) { register struct inode *p; register *ip2devripL10003xL20000_iput _openi"L100050L100064L15L17; int *ip1; register struct mount *ip; loop: ip = NULL; for(p = &inode[0]; p < &inode[NINODE]; p++) { if(dev==p->i_dev &&$\w C % w  w D E& R ww DEL12~openiiprwmajdevripL10007L16L20001L20003$7 yfWp % wdft w NDE07f y-&fWp f_access"~accessipmodemaipL19>_getfs L20008\L20007:L200t %-)ww DC%   7 t0 ww  05:L18`L22P_owner"d~ownerdip_namei L26xL20013L20010tL25  7    wlw hwZ w L  ?Rw6 %_w   _suser"~suserL30L29_ufalloc"~ufallociL20015L34L31_falloc i_flag&IMOUNT) != 0) { for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++) if(ip->m_inodp == p) { dev = ip->m_dev;  { *ip1++ = time[0]; *ip1++ = time[1]; } bwrite(bp); } } /* * Free all the disk blocks associated * with the speciino = ROOTINO; goto loop; } panic(); } p->i_count++; p->i_flag =| ILOCK; return(p); } if(ip==NULL &fied inode structure. * The blocks of the file are removed * in reverse order. This FILO * algorithm will tend to maintain *& p->i_count==0) ip = p; } if((p=ip) == NULL) { u.u_error = ENFILE; return(NULL); } p->i_dev = dev; p->i_number = in a contiguous free list much longer * than FIFO. */ itrunc(ip) int *ip; { register *rp, *bp, *cp; int *dp, *ep; rp = ip; o; p->i_flag = ILOCK; p->i_count++; ip = bread(dev, ldiv(ino+31,16)); /* * Check I/O errors */ if (ip->b_flags&B_ERROR)if((rp->i_mode&(IFCHR&IFBLK)) != 0) return; for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--) if(*ip) { if((rp->i_mode& { brelse(ip); iput(p); return(NULL); } ip1 = ip->b_addr + 32*lrem(ino+31, 16); ip2 = &p->i_mode; while(ip2 < &p->i_adILARG) != 0) { bp = bread(rp->i_dev, *ip); for(cp = bp->b_addr+510; cp >= bp->b_addr; cp--) if(*cp) free(rp->i_dev,dr[8]) *ip2++ = *ip1++; brelse(ip); return(p); } /* * Decrement reference count of * an inode structure. * On the last r *cp); brelse(bp); } free(rp->i_dev, *ip); *ip = 0; } rp->i_mode =& ~ILARG; rp->i_size0 = 0; rp->i_size1 = 0; rp->eference, * write the inode out and if necessary, * truncate and deallocate the file. */ iput(p) struct inode *p; { registeri_flag =| IUPD; } /* * Make a new file. */ maknode(mode) { register *ip; ip = ialloc(u.u_pdir->i_dev); if (ip==NULL) re *rp; rp = p; if(rp->i_count == 1) { rp->i_flag =| ILOCK; if(rp->i_nlink <= 0) { itrunc(rp); rp->i_mode = 0; ifrturn(NULL); ip->i_flag =| IUPD; ip->i_mode = mode|IALLOC; ip->i_nlink = 1; ip->i_uid = u.u_uid; wdir(ip); return(ip); } /ee(rp->i_dev, rp->i_number); } iupdat(rp); prele(rp); rp->i_flag = 0; rp->i_number = 0; } rp->i_count--; prele(rp);* * Write a directory entry with * parameters left as side effects * to a call to namei. */ wdir(ip) int *ip; { register ch } /* * Check accessed and update flags on * an inode structure. * If either is on, update the inode * with the correspondiar *cp1, *cp2; u.u_dent.u_ino = ip->i_number; cp1 = &u.u_dent.u_name[0]; for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];) ng dates * set to the argument tm. */ iupdat(p) int *p; { register *ip1, *ip2, *rp; int *bp, i; rp = p; if((rp->i_flag&IU *cp1++ = *cp2++; u.u_count = DIRSIZ+2; u.u_base = &u.u_dent; writei(u.u_pdir); iput(u.u_pdir); } prele(ip) int *ip; { regPD) != 0) { if(getfs(rp->i_dev)->s_ronly) return; i = rp->i_number+31; bp = bread(rp->i_dev, ldiv(i,16)); ip1 = bp->bister *rp; rp = ip; rp->i_flag =& ~ILOCK; if(rp->i_flag&IWANT) { rp->i_flag =& ~IWANT; wakeup(rp); } }  ino==p->i_number) { if((p->i_flag&ILOCK) != 0) { p->i_flag =| IWANT; sleep(p, PINOD); goto loop; } if((p->_addr + 32*lrem(i, 16); ip2 = &rp->i_mode; while(ip2 < &rp->i_addr[8]) *ip1++ = *ip2++; ip1 =+ 2; if(rp->i_flag&IUPD) (/ low core / parameters to be set to include various drivers / as well as eis and dump capability. eis = 1 dump = 0 rk = 0 rp = 0 qx = 1 qxeml = 1 sa = 0 hp = 0 tc = 0 tm = 0 lp = 0 fltvect = 0 dl = 0 halt = 0 reset = 5 br4 = 200 br5 = 240 br6 = 300 bB@w &  5-"5-̵̵ 2!e% _canonb _swapmap _rootdir _lbolt _time _tout _callout _mount _mpid  w e%ςtt̕fe f 5  fe tl_runrun _curpri _rootdev _swapdev _updlock _regloc _u &_inode _bdevsw _nblkdev _cdevsw5eSee  w D  4 &  j " 4  "ww  _nchrdev _buf X_bfreeli _iget"~igetipip2ip1pdevinoBʵA :e5f  5f tA@lee eʵcsv L2$L20001_sleep L20013L20005*L6vL8^L20003J_panic  N ww D5 Ee50 *5N& e  & , N&L20011fL1rL20007jL20008pcret L5_ldiv _bread L15_brelse _iput = e@-ʆE4 4 w\w X  wB@U4`  w @7"_lrem L16L20010~iputrppL19\L20J_itrunc"_ifree _iupfZHԔ%V8X0V N ww D̵ w(dat"j_prele""~iupdatjbpip1ip2rpipL21_getfs xxL23L20015L25_bwrite ~itruncbpcpdpepiprp(H(L26L27L20019"L29|L31jL32^L20017JL34Z_free _maknode"~maknodeipmode_ialloc L37L36_wdir"~wdiripcp1cp2HIIL20021_writei ~prele"iprpL41>_wakeup  ////////////////////////////////////////////// .globl call, trap .globl _clock kwlp: jsr r0,call; _clock .if qxeml .globl _emlint emlou: jsr r0,call; _emlint; .endif .if lp .globl _lpint lpou: jsr r0,call; _lpint .endif .if rk .globl _rkintr rkio: # #include "../param.h" #include "../user.h" #include "../systm.h" #include "../proc.h" #include "../inode.h" #define CLOCK1 01jsr r0,call; _rkintr .endif .if rp .globl _rpintr rpio: jsr r0,call; _rpintr .endif .if qx .globl _qxintr qxio: jsr r0,call;77546 #define CLOCK2 0172540 /* * Icode is the octal bootstrap * program executed in user mode * to bring up the system. * _qxintr .endif .if sa .globl _saintr saio: jsr r0,call; _saintr .endif .if hp .globl _hpintr hpio: jsr r0,call; _hpintr .en/ int icode[] { 0104413, /* sys exec; init; initp */ TOPSYS+014, TOPSYS+010, 0000777, /* br . */ TOPSYS+014, /* initp: initdif .if tc .globl _tcintr tcio: jsr r0,call; _tcintr .endif .if tm .globl _tmintr tmio: jsr r0,call; _tmintr .endif .globl ; 0 */ 0000000, 0062457, /* init: */ 0061564, 0064457, 0064556, 0000164, }; /* * Initialization code. * Cr7 = 340 . = 0^. br 1f 4 / trap vectors trap; br7+0 / bus error .if eis trap; br7+1 / illegal instruction .endif .if eis_klrint klin: jsr r0,call; _klrint .globl _klxint klou: jsr r0,call; _klxint / save registers and dump memory _panic: _du-1 .globl trapem trapem; br7+1 / emulate illegal instruction .endif trap; br7+2 / bpt-trace trap trap; br7+3 / iot trap mp: .if dump reset mov r0,*$4 mov $6,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov r5,(r0)+ mov sp,(r0)+ rtrap; br7+4 / power fail trap; br7+5 / emulator trap trap; br7+6 / system entry . = 040^. .globl start, _dump, _panic 1: jkda = 177412 rkcs = 177404 1: tstb *$rkcs bge 1b mov $rkda+2,r1 mov $[396.\<4]+8.,-(r1) clr -(r1) mov $-28.*1024.,-(r1) mmp start jmp _dump . = 060^. klin; br5 klou; br5 . = 100^. kwlp; br6 kwlp; br6 .if qxeml . = 164^. emlou; br6 .endif ov $3,-(r1) 1: tstb (r1) bge 1b jmp *$173010 .endif .if dump-1 halt br . .endif .if rk .globl _rkaddr _rkaddr: mov r2,-(.if lp . = 200^. lpou; br4 .endif .if tc . = 214^. tcio; br6 .endif .if rk . = 220^. rkio; br5 .endif .if tm . = 224^. tmsp) mov $dvtab,r2 mov 4(sp),r0 bic $!7,r0 swab r0 asl r0 mov 6(sp),r1 0: sub (r2),r1 bmi 1f add 2(r2),r0 br 0b 1: addio; br5 .endif .if qx . = 250^. qxio; br5 .endif .if rp . = 254^. rpio; br5 .endif .if hp . = 254^. hpio; br5 .endif / f (r2),r1 cmp (r2)+,(r2)+ cmp r2,$dvtab+12. blo 0b asl r0 asl r0 asl r0 asl r0 bis r1,r0 mov (sp)+,r2 rts pc dvtab: 1loating vectors go here .if fltvect . = 300^. .endif .if dl klin; br5+1 klou; br5+1 .endif .if sa . = 360^. saio; br5 saio200. 100. 120. 10. 12. 1. .endif ; br5+1 / error interrupt thru 364 .endif ////////////////////////////////////////////////////// / interface code to C //////// lag =| SLOAD; u.u_procp = &proc[0]; /* * set up 'known' i-nodes */ /* *lks = 0115; */ cinit(); binit(); iinit(); rootdir = iget(rootdev, ROOTINO); rootdir->i_flag =& ~ILOCK; u.u_cdir = iget(rootdev, ROOTINO); u.u_cdir->i_flag =& ~ILOCK; /* * make init process */ copyout(icode, TOPSYS, sizeof icode); /* * Return goes to loc. 0 of user init * code just c# /* */ /* * Structure of the coremap and swapmap * arrays. Consists of non-zero count * and base address of that many * copied out. */ } ontiguous units. * (The coremap unit is 64 bytes, * the swapmap unit is 512 bytes) * The addresses are increasing and * the list is terminated with the * first zero count. */ struct map { char *m_size; char *m_addr; }; /* * Allocate size units from the given * map. Return the base of the allocated * space. * Algorithm is first fit. */ malloc(mp, size) struct map *mp; { register int a; register struct map *bp; for (bp = mp; bp->m_size; bp++) { if (bp->m_size >= size) { a = bp->m_addr; ~tw 7 T %  7 7` bp->m_addr =+ size; if ((bp->m_size =- size) == 0) do { bp++; (bp-1)->m_addr = bp->m_addr; } while ((bp-alled from mch.s as * soon as a stack * has been established. * Functions: * find which clock is configured * hand craft 0t~ %w `` `/etc/inity(   99h process * call all initialization routines * fork - process 0 to schedule * - process 1 execute bootstrap * * panic: _u &_canonb _swapmap _rootdir _lbolt _time  no clock -- neither clock responds * loop at loc 6 in user mode -- /etc/init * cannot be executed. */ main() { extern schar_tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _proc; register i, *p; updlock = 0; /* * determine clock */ #ifndef QX if(fuword(lks = CLOCK1) == -1) lks = CLOCK2; #end _inode _icode#~_main"~mainipcsv _mfree _cinit _binit _iinif #ifdef VSWAP mfree(swapmap, NSWAP, SWPLO); #endif /* * set up system process */ proc[0].p_stat = SRUN; proc[0].p_fit _iget _copyout cret  { register struct map *bp; register int t; register int a; a = aa; for (bp = mp; bp->m_addr<=a && bp->m_size!=0; bp++); ieeDbpmpsizeataaL11ZL20003RL12`L14f (bp>mp && (bp-1)->m_addr+(bp-1)->m_size == a) { (bp-1)->m_size =+ size; if (a+size == bp->m_addr) { (bp-1)->m_size =+ bL10L16L19L24p->m_size; while (bp->m_size) { bp++; (bp-1)->m_addr = bp->m_addr; (bp-1)->m_size = bp->m_size; } } } else { if (a+size == bp->m_addr && bp->m_size) { bp->m_addr =- size; bp->m_size =+ size; } else if (size) do { t = bp->mz r7f Effe E- ``fffffff UE _addr; bp->m_addr = a; a = t; t = bp->m_size; bp->m_size = size; bp++; } while (size = t); } }  -`  F 捦UE@BE   5 e E1 捦UE@B   5   E Bv EE (&v  4  U@ U   ~n `&  2JDEUPEIUhw CK-smK ewe  w BD e D-m EIEU EUE@UE UmH   W tm@m-*4c &e44@m- tLm  Lew$iW @  `[X & ` 6r 6r@@A6v@@& ADCBFi61)->m_size = bp->m_size); return(a); } } return(0); } /* * Free the previously allocated space aa * of size units into_malloc"~mallocbpmpsize the specified map. * Sort aa into map and combine on * one or both ends if possible. */ mfree(mp, size, aa) struct map *mp; acsv L2<L20001 L48L62L9"L14cret _mfree"D~mfr / machine language assist / non-UNIX instructions halt = 0 wait = 1 rti = 2 reset = 5 / flag to enable LSI PS r/w instructionsut .globl _getc, _putc .globl _cfreelist _getc: mov 2(sp),r1 .if lsi mfps -(sp) .endif .if lsi-1 mov PS,-(sp) .endif mov r99: mfps, mtps lsi = 1 .if lsi mtps = 106400^tst mfps = 106700^tst .endif .globl trap, call, emtrap .globl _trap trap: .if lsi m9999fps -4(sp) .endif .if lsi-1 mov PS,-4(sp) .endif tst nofault bne 1f emtrap: jsr r0,call1; _trap / no return 1: mov nofault,(sp) rti .globl _runrun, _swtch call1: tst -(sp) .if lsi mfps -(sp) bic $340,(sp) mtps (sp)+ .endif .if lsi-1 bic $340,PS .endif br 1f call: .if lsi mfps -(sp) .endif .if lsi-1 mov PS,-(sp) .endif 1: mov r1,-(sp) mov sp,r1 /get stack pointer at trap mov r1,-(sp) add $10.,(sp) mov 4(sp),-(sp) bic $!37,(sp) / trap type cmp 10.(sp),$_u+[usize*64.] blo 1f / trap fro)m system mov 2(sp),r1 / trap from user, get user stack mov $_u+[usize*64.],sp mov -(r1),-(sp) / copy user stack to system stahaltrtiresetlsimtps mfps trap"call""emtrap" _trap PSck mov -(r1),-(sp) mov -(r1),-(sp) mov -(r1),-(sp) mov -(r1),-(sp) mov -(r1),-(sp) mov -(r1),-(sp) jsr pc,*(r0)+ 2: .if lnofault$zcall1_runrun _swtch _u!\usize_getc"_putc"_cfreeli _fubyte"`si mfps -(sp) bis $340,(sp) mtps (sp)+ .endif .if lsi-1 bis $340,PS .endif tstb _runrun beq 2f .if lsi mfps -(sp) bic $3_subyte"z_fuibyte"`_suibyte"z_fuword"_suword"_fuiword"_suiword"gwordpwordfuworderr40,(sp) mtps (sp)+ .endif .if lsi-1 bic $340,PS .endif jsr pc,_swtch br 2b 1: jsr pc,*(r0)+ 2: tst (sp)+ mov (sp)+,r1 / nsuword_copyin"_copyout"copsu_idle">_savu"N_retu"h_spl0"_spl1"_spl4"_splew user stack pointer cmp 6(sp),$_u+[usize*64.] blo 1f / return from system trap sub $10.,r1 / begin. of system stack to be c5"_spl6"_spl7"_dpadd"_dpcmp"start"_end _edata _main _ldiv"(_lrem"4opied to user stack mov (sp)+,(r1)+ / copy system stack to user stack mov (sp)+,(r1)+ mov (sp)+,(r1)+ mov (sp)+,(r1)+ mov (_lshift"Bcsv"Rcret"^_getps"l_putps"p_haltins"vsp)+,(r1)+ sub $10.,r1 mov r1,sp / switch to user stack 1: mov (sp)+,r1 tst (sp)+ mov (sp)+,r0 rti / Character list get/p ov (sp)+,r3 mov (sp)+,r2 .if lsi mtps (sp)+ .endif .if lsi-1 mov (sp)+,PS .endif rts pc 9: mov pc,r0 mov (sp)+,r3 mov (spsp)+,PS .endif rts pc err: mov (sp)+,nofault .if lsi mtps (sp)+ .endif .if lsi-1 mov (sp)+,PS .endif tst (sp)+ mov $-1,r0)+,r2 .if lsi mtps (sp)+ .endif .if lsi-1 mov (sp)+,PS .endif rts pc .globl _fubyte, _subyte .globl _fuibyte, _suibyte .glob rts pc .globl _copyin, _copyout _copyin: _copyout: jsr pc,copsu 1: mov (r0)+,(r1)+ sob r2,1b 2: mov (sp)+,nofault mov (sl _fuword, _suword .globl _fuiword, _suiword _fuibyte: _fubyte: mov 2(sp),r1 bic $1,r1 jsr pc,gword cmp r1,2(sp) beq 1f swp)+,r2 clr r0 rts pc copsu: mov (sp)+,r0 mov r2,-(sp) mov nofault,-(sp) mov r0,-(sp) mov 10(sp),r0 mov 12(sp),r1 mov 1ab r0 1: bic $!377,r0 rts pc _suibyte: _subyte: mov 2(sp),r1 bic $1,r1 jsr pc,gword mov r0,-(sp) cmp r1,4(sp) beq 1f m4(sp),r2 asr r2 mov $1f,nofault rts pc 1: mov (sp)+,nofault mov (sp)+,r2 mov $-1,r0 rts pc .globl _idle _idle: .if lsi 2,-(sp) .if lsi mfps -(sp) bis $340,(sp) bic $100,(sp) mtps (sp)+ / spl 5 .endif .if lsi-1 bis $340,PS bic $100,PS .endifovb 6(sp),1(sp) br 2f 1: movb 6(sp),(sp) 2: mov (sp)+,r0 jsr pc,pword clr r0 rts pc _fuiword: _fuword: mov 2(sp),r1 fuwo mov 2(r1),r2 / first ptr beq 9f / empty movb (r2)+,r0 / character bic $!377,r0 mov r2,2(r1) dec (r1)+ / count bne 1f rd: jsr pc,gword rts pc gword: .if lsi mfps -(sp) mfps -(sp) bis $340,(sp) mtps (sp)+ .endif .if lsi-1 mov PS,-(sp) bisclr (r1)+ clr (r1)+ / last block br 2f 1: bit $7,r2 bne 3f mov -10(r2),(r1) / next block add $2,(r1) 2: dec r2 bic $7,r $340,PS .endif mov nofault,-(sp) mov $err,nofault mov (r1),r0 br 1f _suiword: _suword: mov 2(sp),r1 mov 4(sp),r0 suword:2 mov _cfreelist,(r2) mov r2,_cfreelist 3: mov (sp)+,r2 .if lsi mtps (sp)+ .endif .if lsi-1 mov (sp)+,PS .endif rts pc 9:  jsr pc,pword rts pc pword: .if lsi mfps -(sp) mfps -(sp) bis $340,(sp) mtps (sp)+ .endif .if lsi-1 mov PS,-(sp) bis $3 clr 4(r1) mov $-1,r0 mov (sp)+,r2 .if lsi mtps (sp)+ .endif .if lsi-1 mov (sp)+,PS .endif rts pc _putc: mov 2(sp),r0 mo40,PS .endif mov nofault,-(sp) mov $err,nofault mov r0,(r1) 1: mov (sp)+,nofault .if lsi mtps (sp)+ .endif .if lsi-1 mov (v 4(sp),r1 .if lsi mfps -(sp) .endif .if lsi-1 mov PS,-(sp) .endif mov r2,-(sp) mov r3,-(sp) .if lsi mfps -(sp) bis $340,(sp) bic $100,(sp) mtps (sp)+ / spl 5 .endif .if lsi-1 bis $340,PS bic $100,PS .endif mov 4(r1),r2 / last ptr bne 1f mov _cfreelist,r2 beq 9f mov (r2),_cfreelist clr (r2)+ mov r2,2(r1) / first ptr br 2f 1: bit $7,r2 bne 2f mov _cfreelist,r3  beq 9f mov (r3),_cfreelist mov r3,-10(r2) mov r3,r2 clr (r2)+ 2: movb r0,(r2)+ mov r2,4(r1) inc (r1) / count clr r0 m mtps (sp)+ .endif .if lsi-1 bic $340,PS .endif rts pc _spl1: .if lsi mfps -(sp) bis $40,(sp) bic $300,(sp) mtps (sp)+ .en -(r1),r2 mov r5,sp mov (sp)+,r5 rts pc .if lsi .globl _getps _getps: mfps r0 rts pc .globl _putps _putps: mtps 2(sp) dif .if lsi-1 bis $40,PS bic $300,PS .endif rts pc _spl4: _spl5: .if lsi mfps -(sp) bis $340,(sp) bic $100,(sp) mtps (sp)rts pc .endif / halt instruction / used with "halt" system call / for bringing system down gracefully .globl _haltins _haltins:+ .endif .if lsi-1 bis $340,PS bic $100,PS .endif rts pc _spl6: .if lsi mfps -(sp) bis $340,(sp) bic $40,(sp) mtps (sp)+  halt br . / hang .globl _u _u = 56000 usize = 16. PS = 177776 .bss .globl nofault nofault:.=.+2 .endif .if lsi-1 bis $340,PS bic $40,PS .endif rts pc _spl7: .if lsi mfps -(sp) bis $340,(sp) mtps (sp)+ .endif .if lsi-1  bis $340,PS .endif rts pc .globl _dpadd _dpadd: mov 2(sp),r0 add 4(sp),2(r0) adc (r0) rts pc .globl _dpcmp _dpcmp: mov 2(sp),r0 mov 4(sp),r1 sub 6(sp),r0 sub 8(sp),r1 sbc r0 bge 1f cmp r0,$-1 bne 2f cmp r1,$-512. bhi 3f 2: mov $-512.,r0 # /* */ /* * Memory special file * minor device 0 is physical memory * minor device 1 is kernel memory * minor device 2 is rts pc 1: bne 2f cmp r1,$512. blo 3f 2: mov $512.,r1 3: mov r1,r0 rts pc .globl start, _end, _edata, _main start: / cle EOF/RATHOLE */ #include "../param.h" #include "../user.h" #include "../conf.h" mmread(dev) { register c; if(dev.d_minor = mfps -(sp) mfps -(sp) bic $340,(sp) mtps (sp)+ .endif .if lsi-1 mov PS,-(sp) bic $340,PS .endif wait .if lsi mtps (sp)+ ar bss and user block mov $_edata,r0 1: clr (r0)+ cmp r0,$_u+[usize*64.] blo 1b / set up stack pointer mov r0,sp / and .endif .if lsi-1 mov (sp)+,PS .endif rts pc .globl _savu, _retu _savu: .if lsi mfps -(sp) bis $340,(sp) mtps (sp)+ .endif pointer to system stack mov $_u-2,_u / set up previous mode and call main / on return, enter user mode at 060000 jsr pc,_m.if lsi-1 bis $340,PS .endif mov (sp)+,r1 mov (sp),r0 mov sp,(r0)+ mov r5,(r0)+ .if lsi mfps -(sp) bic $340,(sp) mtps (sain mov $_u+[usize*64.]+8192.,sp / set stack at first 4K of user space clr -(sp) mov $_u+[usize*64.],-(sp) rti .globl _ldivp)+ .endif .if lsi-1 bic $340,PS .endif jmp (r1) _retu: .if lsi mfps -(sp) bis $340,(sp) mtps (sp)+ .endif .if lsi-1 bis  _ldiv: clr r0 mov 2(sp),r1 div 4(sp),r0 rts pc .globl _lrem _lrem: clr r0 mov 2(sp),r1 div 4(sp),r0 mov r1,r0 rts pc $340,PS .endif mov (sp)+,r1 mov (sp),r0 mov (r0)+,sp mov (r0)+,r5 .if lsi mfps -(sp) bic $340,(sp) mtps (sp)+ .endif .if  .globl _lshift _lshift: mov 2(sp),r1 mov (r1)+,r0 mov (r1),r1 ashc 4(sp),r0 mov r1,r0 rts pc .globl csv csv: mov r5,r0 lsi-1 bic $340,PS .endif jmp (r1) .globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7 _spl0: .if lsi mfps -(sp) bic $340,(sp)  mov sp,r5 mov r4,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,(r0) .globl cret cret: mov r5,r1 mov -(r1),r4 mov -(r1),r3 mov ted * 2 if name is to be deleted */ namei(flag) { register struct inode *dp; register c; register char *cp; int eo, *bp;  /* * If name starts with '/' start from * root; otherwise start from current dir. */ dp = u.u_cdir; if((c=uchar()) == '/') dp = rootdir; iget(dp->i_dev, dp->i_number); while(c == '/') c = uchar(); if(c == '\0' && flag != 0) { u.u_error =p w  4  ww 7 7aB w   ENOENT; goto out; } cloop: /* * Here dp contains pointer * to last component matched. */ if(u.u_error) goto out; Hi x_u &_bde if(c == '\0') return(dp); /* * If there is another component, * dp must be a directory and * must have x permission.vsw _nblkdev _cdevsw _nchrdev _mmread"~mmreadcdevcsv L1&L4  */ if((dp->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto out; } if(access(dp, IEXEC)) goto out; /* * Gathe_fuibyte _passc cret _mmwrite"*~mmwrite*cdevL7R_dpadd L5N_cpassr up name into * users' dir buffer. */ cp = &u.u_dbuf[0]; while(c!='/' && c!='\0' && u.u_error==0) { if(cp < &u.u_dbuf[ _suibyte DIRSIZ]) *cp++ = c; c = uchar(); } while(cp < &u.u_dbuf[DIRSIZ]) *cp++ = '\0'; while(c == '/') c = uchar(); if(u.u_error) goto out; /* * Set up to search a directory. */ u.u_offset[1] = 0; u.u_offset[0] = 0; eo = 0; u.u_count = ldiv(dp->i_size1, DIRSIZ+2); bp = NULL; eloop: /* * If at the end of the directory, * the search failed. Report what * i= 2) return; do { c = fuibyte(u.u_offset[1]); } while(u.u_error==0 && passc(c)>=0); } mmwrite(dev) { register c; if(dev.d_minor == 2) { c = u.u_count; u.u_count = 0; u.u_base =+ c; dpadd(u.u_offset, c); return; } for(;;) { if ((c=cp# #include "../param.h" #include "../inode.h" #include "../user.h" #include "../systm.h" #include "../buf.h" /* * Convert a paass())<0 || u.u_error!=0) break; suibyte(u.u_offset[1]-1, c); } } thname into a pointer to * an inode. Note that the inode is locked. * * flag = 0 if name is sought * 1 if name is to be crea s appropriate as per flag. */ if(u.u_count == 0) { if(bp != NULL) brelse(bp); if(flag==1 && c=='\0') { if(access(dp, IWRITE)) goto out; u.u_pdir = dp; if(eo) u.u_offset[1] = eo-DIRSIZ-2; else dp->i_flag =| IUPD; return(NULL); } u.u_error = ENOENT; goto out; } /* * If offset is on a block boundary, * read the next directory block. * Release previous if it exists. */ if((u.u_offset[1]&0777) == 0) { if(bp != NULL) brelse(bp); bp = bread(dp->i_dev, N<w : %/&  %/    _ _E bmap(dp, ldiv(u.u_offset[1], 512))); } /* * Note first empty directory slot * in eo for possible creat. * String compa%@@& H   %VҐ %/%V n%/o7 v7 p5 & 7X5 Pre the directory entry * and the current component. * If they do not match, go back to eloop. */ bcopy(bp->b_addr+(u.u_o$ N % & 7H @e75 N  & & ffset[1]&0777), &u.u_dent, (DIRSIZ+2)/2); u.u_offset[1] =+ DIRSIZ+2; u.u_count--; if(u.u_dent.u_ino == 0) { if(eo == 0)  5X@&E` %e  HZH` %V N % &eo = u.u_offset[1]; goto eloop; } for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++) if(*cp != cp[u.u_dent.u_name - u.u_ _Pw5 Df _\_Vw $ %jwIdbuf]) goto eloop; /* * Here a component matched in a directory. * If there is more pathname, go back to * cloop, othXerwise return. */ if(bp != NULL) brelse(bp); if(flag==2 && c=='\0') { if(access(dp, IWRITE)) goto out; return(dp);X } bp = dp->i_dev; iput(dp); dp = iget(bp, u.u_dent.u_ino); if(dp == NULL) return(NULL); goto cloop; out: iput(dp); rXeturn(NULL); } /* * Return the next character from the * user string pointed at by dirp. */ uchar() { register c; c = fuX Xbyte(u.u_dirp++); if(c == -1) u.u_error = EFAULT; return(c); } 8 _inode _u &_canonb _swapmap _rootdir _lbolt _time  de effects. In general the * arguments to an allocate routine are a device and * a block number, and the value is a pointer t(rbp); } /* * Release the buffer, start I/O on it, but don't wait for completion. */ bawrite(bp) struct buf *bp; { register o * to the buffer header; the buffer is marked "busy" * so that no on else can touch it. If the block was * already in core,struct buf *rbp; rbp = bp; rbp->b_flags =| B_ASYNC; bwrite(rbp); } /* * release the buffer, with no I/O implied. */ brels no I/O need be done; if it is * already busy, the process waits until it becomes free. * The following routines allocate a bue(bp) struct buf *bp; { register struct buf *rbp, **backp; register int sps; rbp = bp; if (rbp->b_flags&B_WANTED) wakeup(_tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _bufffer: * getblk * bread * Eventually the buffer must be released, possibly with the * side effect of writing it out, by using X_bfreeli _namei"~nameiflagdpcpeobpccsv _uch one of * bwrite * bdwrite * bawrite * brelse */ /* * Read in (if necessary) the block and return a buffer pointer. */ bar"*L2_iget L32L20001,L7\L20010BL6PL20014J_iput L20015Vread(dev, blkno) { register struct buf *rbp; rbp = getblk(dev, blkno); if (rbp->b_flags&B_DONE) return(rbp); rbp->b_flagsL1L20003_access L10L20005L13L12L20007L15L20009_ldiv =| B_READ; rbp->b_wcount = -256; (*bdevsw[dev.d_major].d_strategy)(rbp); iowait(rbp); return(rbp); } /* * Write the buffe L17L18:L19_brelse L214L23xL24P_bmap _bread _bcopy L25r, waiting for completion. * Then release the buffer. */ bwrite(bp) struct buf *bp; { register struct buf *rbp; register flaL20012L30L31cret ~uchar*c_fubyte L34Hg; rbp = bp; flag = rbp->b_flags; rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI); rbp->b_wcount = -256; (*bdevsw[# /* */ #include "param.h" #include "user.h" #include "buf.h" #include "conf.h" #include "systm.h" #include "proc.h" /* * Thrbp->b_dev.d_major].d_strategy)(rbp); if ((flag&B_ASYNC) == 0) { iowait(rbp); brelse(rbp); } else if ((flag&B_DELWRI)==0) is is the set of buffers proper, whose heads * were declared in buf.h. There can exist buffer * headers not pointing here tha geterror(rbp); } /* * Release the buffer, marking it so that if it is grabbed * for another purpose it will be written out t are used purely * as arguments to the I/O routines to describe * I/O to be done-- e.g. swbuf, just below, for * swapping. before being * given up (e.g. when writing a partial block where it is * assumed that another write for the same block will so*/ char buffers[NBUF][512]; struct buf swbuf; /* * The following several routines allocate and free * buffers with various sion follow). */ bdwrite(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; rbp->b_flags =| B_DELWRI | B_DONE; brelse  &bfreelist; else { dp = bdevsw[dev.d_major].d_tab; if(dp == NULL) panic(); for (bp=dp->b_forw; bp != dp; bp = bp->b_favailable list and mark it busy. * (internal interface) */ notavail(bp) struct buf *bp; { register struct buf *rbp; registerorw) { if (bp->b_blkno!=blkno || bp->b_dev!=dev) continue; spl6(); if (bp->b_flags&B_BUSY) { bp->b_flags =| B_W int sps; rbp = bp; sps = PS->integ; spl6(); rbp->av_back->av_forw = rbp->av_forw; rbp->av_forw->av_back = rbp->av_back; ANTED; sleep(bp, PRIBIO); spl0(); goto loop; } spl0(); notavail(bp); return(bp); } } spl6(); if (bfrbp->b_flags =| B_BUSY; PS->integ = sps; } /* * Mark I/O complete on a buffer, release it if I/O is asynchronous, * and wakereelist.av_forw == &bfreelist) { bfreelist.b_flags =| B_WANTED; sleep(&bfreelist, PRIBIO); spl0(); goto loop; } spl0() up anyone waiting for it. */ iodone(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; rbp->b_flags =| B_DONE; if ; notavail(bp = bfreelist.av_forw); if (bp->b_flags & B_DELWRI) { bp->b_flags =| B_ASYNC; bwrite(bp); goto loop; } bp-(rbp->b_flags&B_ASYNC) brelse(rbp); else { rbp->b_flags =& ~B_WANTED; wakeup(rbp); } } /* * Zero the core associated with a buffer. */ clrbuf(bp) int *bp; { register *p; register c; p = bp->b_addr; c = 256; do *p++ = 0; while (--c); } rbp); if (bfreelist.b_flags&B_WANTED) { bfreelist.b_flags =& ~B_WANTED; wakeup(&bfreelist); } if (rbp->b_flags&B_ERROR)  rbp->b_dev.d_minor = -1; /* no assoc. on error */ backp = &bfreelist.av_back; sps = PS->integ; spl6(); rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC); (*backp)->av_forw = rbp; rbp->av_back = *backp; *backp = rbp; rbp->av_forw = &bfreelist; PS->integ = sps; } /* * Assign a buffer for the given block. If the appropriate * block is already associated, return it; otherwise s>b_flags = B_BUSY | B_RELOC; bp->b_back->b_forw = bp->b_forw; bp->b_forw->b_back = bp->b_back; bp->b_forw = dp->b_forw; bp->earch * for the oldest non-busy buffer and reassign it. * When a 512-byte area is wanted for some random reason * (e.g. durinb_back = dp; dp->b_forw->b_back = bp; dp->b_forw = bp; bp->b_dev = dev; bp->b_blkno = blkno; return(bp); } /* * Wait for g exec, for the user arglist) getblk can be called * with device NODEV to avoid unwanted associativity. */ getblk(dev, blkno) I/O completion on the buffer; return errors * to the user. */ iowait(bp) struct buf *bp; { register struct buf *rbp; rbp = { register struct buf *bp; register struct devtab *dp; if(dev.d_major >= nblkdev) panic(); loop: if (dev < 0) dp =bp; spl6(); while ((rbp->b_flags&B_DONE)==0) sleep(rbp, PRIBIO); spl0(); geterror(rbp); } /* * Unlink a buffer from the  w = bp; bp->b_flags = B_BUSY; brelse(bp); } i = 0; for (bdp = bdevsw; bdp->d_open; bdp++) { dp = bdp->d_tab; if(dp) { dp->b_forw = dp; dp->b_back = dp; } i++; } nblkdev = i; } /* * swap I/O */ swap(rp, rdflg) struct proc *rp; { r/* */ char partab[] { 0001,0201,0201,0001,0201,0001,0001,0201, 0202,0004,0003,0205,0005,0206,0201,0001, 0201,0001,0001,0201egister int *fp; fp = &swbuf.b_flags; spl6(); *fp = B_BUSY | rdflg; swbuf.b_dev = swapdev; swbuf.b_wcount = - SWPSIZ*256; ,0001,0201,0201,0001, 0001,0201,0201,0001,0201,0001,0001,0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0/* 32 w/block */ swbuf.b_blkno = SWPLO+rp->p_pid*SWPSIZ; swbuf.b_addr = &u; /* 64 b/block */ (*bdevsw[swapdev>>8].d_strategy)200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,000(&swbuf); spl6(); while((*fp&B_DONE)==0) idle(); spl0(); *fp =& ~(B_BUSY|B_WANTED); return(*fp&B_ERROR); } /* * make su0,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,re all write-behind blocks * on dev (or NODEV for all) * are flushed out. * (from umount and update) */ bflush(dev) { regis0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,02ter struct buf *bp; loop: spl6(); for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { if (bp->b_flags&B_DELW00,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0201 }; RI && (dev == NODEV||dev==bp->b_dev)) { bp->b_flags =| B_ASYNC; notavail(bp); bwrite(bp); goto loop; } } spl0(); } /* * Pick up the device's error number and pass it to the user; * if there is an error but the number is 0 set a generaliz/* * Initialize the buffer I/O system by freeing * all buffers and setting all device buffer lists to empty. */ binit() { reed * code. Actually the latter is always true because devices * don't yet return specific errors. */ geterror(abp) struct bugister struct buf *bp; register struct devtab *dp; register int i; struct bdevsw *bdp; bfreelist.b_forw = bfreelist.b_back f *abp; { register struct buf *bp; bp = abp; if (bp->b_flags&B_ERROR) if ((u.u_error = bp->b_error)==0) u.u_error = EIO= bfreelist.av_forw = bfreelist.av_back = &bfreelist; for (i=0; ib_dev = -1; bp->b_a; } ddr = buffers[i]; bp->b_back = &bfreelist; bp->b_forw = bfreelist.b_forw; bfreelist.b_forw->b_back = bp; bfreelist.b_for  putchar(0177); putchar(0177); } putchar(0); KL->xsr = s; } _partab#(w Ce 1 @ %%B %d%l%o %o  v %s e# /* */ /* * Address and structure of the * KL-11 console device registers. */ #define KL 0177560 struct { int rsr; inww Nf N& v Nf e0 wLw HD5t t tv%    t rbr; int xsr; int xbr; }; /* * Scaled down version of C Library printf. * Only %s %l %d (==%l) %o are recognized. * Used  tw)to print diagnostic information * directly on console tty. * Since it is not interrupt driven, * all system activities are pr)Hh)etty much * suspended. * Printf should not be used for chit-chat. */ printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc) char fmt_printf"~printfxaxbxccsadxfmtx1[]; { register char *s; register *adx, c; adx = &x1; loop: while((c = *fmt++) != '%') { if(c == '\0') return; putchax2x3 x4 x5x6x7x8x9csv L3r(c); } c = *fmt++; if(c == 'd' || c == 'l' || c == 'o') printn(*adx, c=='o'? 8: 10); if(c == 's') { s = *adx; while(cL20001 L1r_putchar"L10000@L5XL10001LL10002P_printn"vL6lL7hL20003 = *s++) putchar(c); } adx++; goto loop; } /* * Print an unsigned integer in base b. */ printn(n, b) { register a; ibcret ~printnvabn_ldiv L10_lrem ~putcharrccf(a = ldiv(n, b)) printn(a, b); putchar(lrem(n, b) + '0'); } /* * Print a character on console. * Attempts to save and ressL12L11L14tore device * status. * If the switches are 0, all * printing is inhibited. */ putchar(c) { register rc, s; rc = c; whil e((KL->xsr&0200) == 0) ; if(rc == 0) return; s = KL->xsr; KL->xsr = 0; KL->xbr = rc; if(rc == '\n') { putchar('\r');  play (page buffer) /to ascii spaces, set the cursor to be on column 0, line 23, /blank all graphics zones, and unblank the charatlput / \\ cmpb r0, $lf / \\ beq ctlput / \\ accept only cmpb r0, $bs / // ,,, beq ctlput / // ccter page. / /whenever the page buffer is referenced, "snow" will /be generated on the screen unless all such data transfers /ampb r0, $ff / // bne emldun /// ctlput: com r0 /neg byte in buf flags control character br put / --common char. buffer bufre synchronous with the line clock (start the vertical retrace). /the peak data rate from the emulator hardware is throttled by /a hardware delay of 500us for the interrupt thru vector 64. /thus, the driver buffer of 34. bytes covers the peak data /that ca ////////////////////////////////////// /// terak terminal emulator driver /// ////////////////////////////////////// / This n be received in 16.6 ms. however, since and /transfer blocks of spaces (80. and 1920. resp.), one entire /line clock Terak terminal emulator driver was borrowed from the / corresponding DEC RT-11 source (MACRO-11). / Slightly modified to backspaevent is dedicated to the or . /timing is critical: the lkint portion of driver, which runs as /a co-routine with emlice upon char. / Apologies for the assembly code. / addresses vtbase = 160000 esr = 177564 edb = 177566 vir = 177742 vcr = nt, must finish data transfer in < 1.2 ms. / .globl _emlint, _lkint _emlint: /vector from 164/166...data in edb cmp putpt177744 / control, status bits gbenbl = 200 belbit = 4000 syncbit = 4000 / ascii char. codes bel = 7 bs = 10 lf = 12 ff = 14 crr, (pc)+ /at end of buffer ??? endptr: bufend /must be relocate by ***boot*** blos emlsus /suspend by leaving data in edb mo = 15 space = 40 crs = 177 /emulator handler to accept characters from the hrdwr emulator /data buffer and place them into the v r0, -(sp) mov r1, -(sp) movb *$edb, r0 /get the byte bicb $!177, r0 ble emldun /ignore null and 200 + cmpb r0, $space page buffer in a manner /similar to a glass teletype. a cursor is displayed as ascii /code 177 (normally a solid block) placed iblo chrtst /test for specials cmpb r0, $177 /also, 177 is reserved for cursor beq emldun put: mov (pc)+, r1 /pick up buffernto the page buffer. / /driver will always clear bit 7 (selects page buf) and set bit 1 /(unblank lower character display zone)  pointer putptr: emlbuf - 1 /must be relocated by ***boot*** movb r0, (r1) /put character into buffer clrb -(r1) /maintain of the vcr, with each /character printed, only ascii codes 40 thru 176 are displayed. /ascii code 177 is reserved for driver to delimiter mov r1,putptr /put back pointer emldun: mov (sp)+, r1 mov (sp)+, r0 emlsus: rts pc / by not reading edb, done bit display the cursor. /all control codes are ignored except: , , and . /a will clear the entire character diis left * 0 chrtst: cmpb r0, $bel / b e l l ??? bne 1f inc belflg /turn on the beeper br emldun 1: cmpb r0, $cr /\\ beq c! $-1*200-120, r1 /next line, column zero 5: movb r0, (r1)+ /clear out new line movb r0, (r1)+ /the quadruple movb movb r0, (r1)+ /results in a transfer movb r0, (r1)+ /rate increase of 35% sob r2, 5b /and ()+ is 10% faster than -() bit $37*200, r1 /at line zero yet ??? bne 1b clr *$vir /reset index mov $vtbase+5600, r1 /reset cursor br xcskip /toss out ff compress buffer xlf: mov r0, -(sp) /set up for gear mov $25.*400, r0 /save-a-word mov *$vir, r2 /set vir image clrb r2 /always remor right now, all char zone off!!! mov (pc)+, r1 /pick up cursor address cursor: vtbase+5600 /address of page buffer movb (pc)ve scan lines add $400, r2 /bump index...scroll cmp r2, r0 /cmp w $25.*400...wrap around??? blo 1f /no clr r2 /yes 1: end: .byte 0 /\\ 16.666 ms - (1.08 (refresh)) .byte 0,0,0,0,0 .byte 0,0,0,0,0 .byte 0,0,0,0,0 .byte 0,0,0,0,0 .byte 0,0,0,+, (r1) /restore old contents * cursor oldcrs: space cmpb r2, $!lf /first = lf ? beq xlf cmpb r2, $!ff /or a ff ?? beq xff0,0 .byte 0,0,0,0,0 .byte 0 .byte 0 /// (max rate thru edb) => 33. req'd emlbuf: .byte !ff /initial form feed in buffer  xxfr: mov $80., r2 /figure the 80.'s-complement sub r1, r2 /out of column number bic $!177, r2 /=bytes to end of line xfr:_lkint: mov r0, -(sp) /line clock interrupt mov r1, -(sp) /rons as co-routine with mov r2, -(sp) /emlint clock service mov tstb -(r0) /end of buffer ??? bgt 2f /not end of buf, nor cntl char if gt 0 cmpb (r0), $!bs /bs? bne 4f /no cmp $80., $vcr, r1 /save-a-word bic $belbit, *r1 /clear bell bit asl (pc)+ /beep-in-progress ??? belflg: 0 beq 1f bis $belbit, *r1 r2 /at column 0? beq xfr /yes...next movb $space, -(r1) /blank out old char., dec. cursor pos. br xxfr /next 4: cmpb (r /set bell bit 1: mov (pc)+, r0 /point to start of buffer bufhdr: emlbuf /must be relocated by ***boot*** movb (r0)+, r2 /0), $!cr /cr? bne xcntrl /no br xcr /yes 2: movb (r0),(r1)+ /into the buffer with it sob r2, xfr /count bytes to end of anything to xfr ??? jeq done /buffer's empty! / note the use of "jeq"..."jump if equal". / Unix assembler feature...muline movb $!lf, (r0)+ /put a lf into buffer xcr: bic $177, r1 /move cursor to column zero br xxfr xff: mov $7, (sp) /when vcst change if porting bit $syncbit, *$esr /is clock latency o.k.??? jeq done /0-> too late !!! mov *r1, -(sp) /put copy of r is restored..... / ...blank all graphics zones, display all character zones mov r0, -(sp) /use r0 to hold a blank mov $spacvcr into stack bic $gbenbl+1, (sp) /turn off generator buffer inc (sp) /turn on at least bottom zone bic $gbenbl+7, *r1 /foe, r0 /(georgia overdrive for ff loop) mov $vtbase+6200+120, r1 /-> end of 26th line 1: mov $20., r2 /count 80. columns add " , r1 xcskip: mov (sp)+, r0 cmpb -(r0), -(r0) /skip first byte (lf/ff) /fall into xcntrl xcntrl: movb (r1), oldcrs /save old co== 0) return; if((ip->i_mode&IFMT) == IFCHR) { (*cdevsw[ip->i_addr[0].d_major].d_read)(ip->i_addr[0]); return; } do { ntents movb $crs, (r1) /light up the cursot mov (sp)+, *$vcr /restore vcr...unblank display mov r1, cursor /save cursor loc lbn = bn = lshift(u.u_offset, -9); on = u.u_offset[1] & 0777; n = min(512-on, u.u_count); if((ip->i_mode&IFMT) != IFBLK)ation mov bufhdr, r2 /point to buf cmpb (r0)+, (r2)+ /include this byte 1: movb -(r0), -(r2) /compress this buffer bne 1b  { dn = dpcmp(ip->i_size0&0377, ip->i_size1, u.u_offset[0], u.u_offset[1]); if(dn <= 0) return; n = min(n, dn);/note...when done, (r0)=0 mov r2, putptr tstb *$esr /is there data in edb ??? bmi done /done bit = 1 says empty bisb (r0), if ((bn = bmap(ip, lbn)) == 0) return; dn = ip->i_dev; } else dn = ip->i_addr[0]; bp = bread(dn, bn); iomove *$edb /read-modify-write the edb..... / .....will cause fresh interrupt thru 164 done: mov (sp)+, r2 mov (sp)+, r1 mov (sp(bp, on, n, B_READ); brelse(bp); } while(u.u_error==0 && u.u_count!=0); } /* * Write the file corresponding to * the inode)+, r0 rts pc  pointed at by the argument. * The actual write arguments are found * in the variables: * u_base core address for source * u_offset byte offset in file * u_count number of bytes to write */ writei(aip) struct inode *aip; { int *bp; int n, on; register dn, bn; register struct inode *ip; ip = aip; ip->i_flag =| IUPD; if((ip->i_mode&IFMT) == IFCHR) { (*cdevsw[ip->i_amov r2, *$vir /load the new index!!! asl r1 /adjust cursor to byte split bic $377*400, r1 /remove line bits bis r2, r1 /set to index add $23.*400, r1 /always set cursor on line 23 cmp r1, r0 /wrap around??? blo 3f sub r0, r1 /adjust 3: asr r1 # #include "../param.h" #include "../inode.h" #include "../user.h" #include "../buf.h" #include "../conf.h" #include "../systm.h bis $vtbase, r1 /the new cursor !!! mov r1, -(sp) /preserve cursor bic $177, r1 /set to column zero mov $20., r2 /count " /* * Read the file corresponding to * the inode pointed at by the argument. * The actual read arguments are found * in theighty columns mov $space, r0 /stuff spaces 5: movb r0, (r1)+ /clear out new line movb r0, (r1)+ /the quadruple movb movb e variables: * u_base core address for destination * u_offset byte offset in file * u_count number of bytes to read */ rear0, (r1)+ /results in a transfer movb r0, (r1)+ /rate increase of 35% sob r2, 5b /and ()+ is 10% faster than -() mov (sp)+di(aip) struct inode *aip; { int *bp; int lbn, bn, on; register dn, n; register struct inode *ip; ip = aip; if(u.u_count # turn; dn = ip->i_dev; } else dn = ip->i_addr[0]; if(n == 512) bp = getblk(dn, bn); else bp = bread(dn, bn); isc(*cp++) < 0) return; } omove(bp, on, n, B_WRITE); if(u.u_error != 0) brelse(bp); else if ((u.u_offset[1]&0777)==0) bawrite(bp); else bdwriGrdwri.oFshlib1EshlowcoreDshrshsBshs2Asig.c@sig.ote(bp); if(dpcmp(ip->i_size0&0377, ip->i_size1, u.u_offset[0], u.u_offset[1]) < 0 && (ip->i_mode&(IFBLK&IFCHR)) == 0) ?slp.c>slp.o=subr.c<subr.o;sys1.c:sys1.i9sys1.o8sys2.c{ ip->i_size0 = u.u_offset[0]; ip->i_size1 = u.u_offset[1]; } ip->i_flag =| IUPD; } while(u.u_error==0 && u.u_count!=7sys2.o6sys3.c5sys3.o4sys4.c3sys4.o2sysent.c1sysent.o0trap.c0); } /* * Return the logical maximum * of the 2 arguments. */ max(a, b) char *a, *b; { if(a > b) return(a); return(b);/trap.o.tty.c-tty.oCrun } /* * Return the logical minimum * of the 2 arguments. */ min(a, b) char *a, *b; { if(a < b) return(a); return(b); } w B 0_E% Wp  dB 55E5N ^  /* * Move 'an' bytes at byte location * &bp->b_addr[o] to/from (flag) the * user/kernel area starting at u.base. * Update E%`# &E e1 ^ N 5"N& 5ff xeNall the arguments by the number * of bytes moved. * * There are 2 algorithms, * if source address, dest address and count * ? Bww BE% Wp  _@ _@B E5N ^  are all even in a user copy, * then the machine language copyin/copyout * is called. * If not, its done byte-by-byte with *5E%`  X%& & 5 fff xecN 5^N  cpass and passc. */ iomove(bp, o, an, flag) struct buf *bp; { register char *cp; register int n, t; n = an; cp = bp->b_adN F@ &E e 5    ww u-@w@w u-@wdr + o; if(((n | cp | u.u_base)&01)==0) { if (flag==B_WRITE) cp = copyin(u.u_base, cp, n); else cp = copyout(cp, u.u_@w C@DmQ]5# & & %jqw6`pB b   ddr[0].d_major].d_write)(ip->i_addr[0]); return; } if (u.u_count == 0) return; do { bn = lshift(u.u_offset, -9); on base, n); if (cp) { u.u_error = EFAULT; return; } u.u_base =+ n; dpadd(u.u_offset, n); u.u_count =- n; return;= u.u_offset[1] & 0777; n = min(512-on, u.u_count); if((ip->i_mode&IFMT) != IFBLK) { if ((bn = bmap(ip, bn)) == 0) re } if (flag==B_WRITE) { while(n--) { if ((t = cpass()) < 0) return; *cp++ = t; } } else while (n--) if(pas$ L15_getblk L20001L17L18L19_bawrite _bdwrite L210_max"D~max  hHDabL23XL22T~min^abL25rL24n~iomovexanxbpflag cpnotL27L28_copyin L20003hH_copyout L30L26_dpadd L35L32_cpass _passc (8xcc -c -O *.c mv conf.o ../conf.o as emul.s; mv a.out emul.o ar r ../lib1 alloc.o iget.o rdwri.o slp.o subr.o trap.o sig.o ar r )8_inode _u &_buf X_bfreeli _bdevsw _nblkdev _cdevsw../lib1 clock.o sysent.o fio.o malloc.o nami.o sys1.o sys2.o sys3.o sys4.o ar r ../lib1 bio.o mem.o tty.o partab.o emul.o  _nchrdev _canonb _swapmap _rootdir _lbolt _time _tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _readi"~readibnbpdniponnaiplbncsv L1L58_lshift _min"^L6as low.s;mv a.out ../low.o cc -c -O conf.c;mv conf.o ../conf.o _dpcmp _bmap L7_bread _iomove"x_brelse cret _writei"~writeibnbpdniponnaipL98L8@L12BL13L14% sual sequence is: * if(issig()) * psig(); */ psig() { register n, p; register *rp; rp = u.u_procp; n = rp->p_sig; rp->p_sig = 0; if((p=u.u_signal[n]) != 0) { u.u_error = 0; if(n != SIGINS) u.u_signal[n] = 0; n = u.u_ar0[R6] - 4; suword(n+2, u.u_ar0[RPS]); suword(n, u.u_ar0[R7]); u.u_ar0[R6] = n; u.u_ar0[R7] = p; return; } switch(n) { case SIGQIT: # #include "../param.h" #include "../systm.h" #include "../user.h" #include "../proc.h" #include "../inode.h" #include "../reg.hcase SIGINS: case SIGTRC: case SIGIOT: case SIGEMT: case SIGFPT: case SIGBUS: case SIGSEG: case SIGSYS: u.u_arg[0] = n;as low.s;mv a.out ../low.o cc -c -O conf.c;mv conf.o ../conf.o " /* * Structure to access an array of integers. */ struct { int inta[]; }; /* * Send the specified signal to * all processes with 'pgrp' as * process group. * Called by tty.c for quits and * interrupts. */ signal(apgrp, sig) { register struct proc *p; int pgrp; if ((pgrp = apgrp)==0) return; for(p = &proc[0]; p < &proc[NPROC]; p++) if(p->p_pgrp == pgrp) psignal(p, sig); } /* * Send the specified signal to * the specified process. */ psignal(p, sig) int *p; char *sig; { register if $1x != x goto link cc -c -O *.c echo Done compiling... mv conf.o ../conf.o as low.s;mv a.out ../low.o as mch.s;mv a.out mch.o*rp; if(sig >= NSIG) return; rp = p; if(rp->p_sig != SIGKIL) rp->p_sig = sig; if(rp->p_stat == SSLEEP && rp->p_pri>0)  as qxeml.s; mv a.out ../qxeml.o echo Done assembling... : link echo Begin linking sys... ld -a -x -r *.o mv a.out syso echo Don setrun(rp); } /* * Returns true if the current * process has a signal to process. * This is asked at least once * each time linking sys... ar r ../lib1 syso echo Done archiving... rm syso e a process enters the * system. * A signal does not do anything * directly to a process; it sets * a flag that asks the process to * do something to itself. */ issig() { register n; register struct proc *p; p = u.u_procp; if(n = p->p_sig) { icc -O -c main.c bio.c sys1.c f((u.u_signal[n]&1) == 0) return(n); } return(0); } /* * Perform the action specified by * the current signal. * The u& rror==0); } _signal"~signalpgrppsigapgrpcsv L10L20001L4&_psignal"4cret ~psignal4rppsigL6dL7R_setrun _issig"h~issighnpL10L9_psig"L10001L25L15~psigrpnpL13L14_suword L12*_core"._exit ~core.ipsL28`w ut-N& 4 e%ww %D t̥ ww _namei L29ZL20005_maknode _access L32_itrunc _writei _iput L10002L27Ĝ  5wx w p2 (7% 0 Ze&e >& .0& x7  etQ7 ww 7  , & 5` if(core()) n =+ 0200; } u.u_arg[0] = (u.u_ar0[R0]<<8) | n; exit(); } /* * Create a core image on the file "core" * I 7 7    wTcoref you are looking for protection glitches, * there are probably a wealth of them here * when this occurs to a suid command. *H * It writes USIZE block of the * user.h area followed by the entire * data+stack segments. */ core() { register s, *ip; XXu.u_error = 0; u.u_dirp = "core"; ip = namei(1); if(ip == NULL) { if(u.u_error) return(0); ip = maknode(0666); if (i8HXp==NULL) return(0); } if(!access(ip, IWRITE) && (ip->i_mode&IFMT) == 0 && u.u_uid == u.u_ruid) { itrunc(ip); u._canonb _swapmap _rootdir _lbolt _time _tout _callout _mouu_offset[0] = 0; u.u_offset[1] = 0; u.u_base = &u; u.u_count = (USIZE+UCORE)*64; writei(ip); } iput(ip); return(u.u_ent _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _u &_proc _inode ' if pri>0 signals will be processed. * Callers of this routine must be prepared for * premature return, and check that the reasC; if(runrun && swapflag == 0) { do { rp++; if(rp >= &proc[NPROC]) rp = &proc[0]; if(rp->p_stat==SRUN) { p =on for * sleeping has gone away. */ sleep(chan, pri) { register *rp, s; #ifdef QX s = getps(); #endif #ifndef QX s = PS->i rp; n = rp->p_pri; runrun = 0; break; } } while(--i); } else { if(rp->p_stat == SRUN) { p = rp; n = rnteg; #endif rp = u.u_procp; spl6(); rp->p_stat = SSLEEP; rp->p_wchan = chan; rp->p_pri = pri; spl0(); if(pri > 0) { ifp->p_pri; } } /* * If no process is runnable, idle. */ if(p == NULL) { p = rp; idle(); goto loop; } curpri = n;(issig()) goto psig; swtch(); if(issig()) goto psig; } else swtch(); #ifdef QX putps(s); #endif #ifndef QX PS->in n = rp = p; /* if(hp > &hbuf[36]) hp = hbuf; *hp++ = n; *hp++ = u.u_procp; *hp++ = time[1]; */ if(n != u.u_procp && swateg = s; #endif return; /* * If priority was low (>0) and * there has been a signal, * execute non-local goto to * thpflag == 0) { /* * Save stack of current user and * and use system stack. */ swapflag++; savu(u.u_ssav); retu(u.u_re qsav location. * (see trap1/trap.c) */ psig: rp->p_stat = SRUN; retu(u.u_qsav); } /* * Wake up all processes sleeping sav); u.u_procp->p_flag =& ~SLOAD; if(u.u_procp->p_stat != SZOMB) swap(u.u_procp, B_WRITE); swap(rp, B_READ); rp->p_fon chan. */ wakeup(chan) { register struct proc *p; register c, i; c = chan; p = &proc[0]; i = NPROC; do { if(p->p_wchlag =| SLOAD; retu(u.u_ssav); swapflag--; } /* * The value returned here has many subtle implications. * See the newpran == c) { setrun(p); } p++; } while(--i); } /* * Set the process running; * arrange for it to be swapped in if necesoc comments. */ return(1); } /* * Create a new process-- the internal version of * sys fork. * It returns 1 in the new prsary. */ setrun(p) { register struct proc *rp; rp = p; rp->p_wchan = 0; rp->p_stat = SRUN; if(rp->p_pri < 0) rp->p_pri ocess. * How this happens is rather hard to understand. * The essential fact is that the new process is created * in such a w= PSLEP; if(rp->p_pri < curpri) runrun++; } /* * This routine is called to reschedule the CPU. * if the calling process isay that appears to have started executing * in the same call to newproc as the parent; * but in fact the code that runs is tha# #include "../param.h" #include "../proc.h" #include "../user.h" #include "../systm.h" #include "../file.h" #include "../inode. not in RUN state, * arrangements for it to restart must have * been made elsewhere, usually by calling via sleep. */ /* inth" #include "../buf.h" /* * Give up the processor till a wakeup occurs * on chan, at which time the process * enters the sch hbuf[40]; int *hp hbuf; */ int swapflag; swtch() { static struct proc *p; register i, n; register struct proc *rp; if(p =eduling queue at priority pri. * The most important effect of pri is that when * pri<=0 a signal cannot disturb the sleep; * = NULL) p = &proc[0]; loop: rp = p; p = NULL; n = 128; /* * Search for highest-priority runnable process */ i = NPRO( t of swtch. * The subtle implication of the returned value of swtch * (see above) is that this is the value that newproc's * nt * of the new process so that when it is actually * created (by copying) it will look right. */ rpp = p; u.u_procp = caller in the new process sees. */ newproc() { int a1, a2; struct proc *p, *up; register struct proc *rpp; register *rip, nrpp; rip = up; rip->p_stat = SIDL; savu(u.u_ssav); swap(rpp, B_WRITE); /* swap out child */ rpp->p_flag =| SSWAP; rip->p_s; p = NULL; /* * First, just locate a slot for a process * and copy the useful info from this process into it. * The patat = SRUN; u.u_procp = rip; return(0); /* return to parent */ } nic "cannot happen" because fork has already * checked for the existence of a slot. */ retry: if(++mpid >= NPROC) mpid = 1; for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { if(rpp->p_stat == NULL && p==NULL) p = rpp; if (rpp->p_pid==mpid)  goto retry; } if ((rpp = p)==NULL) panic(); /* * make proc entry for new proc */ rip = u.u_procp; up = rip; rpp->T8w . ̕tt   v ̕ w Z w C  e~w~w zD4 ̕Z^VwRw N 7 . (e%ʥb7  ʥH @: ,-) &        ~wvw r5 f%`X̋ 5-B e%D *b̕  %,D7C˕  & ˕ wp_stat = SRUN; rpp->p_flag = SLOAD; rpp->p_uid = rip->p_uid; rpp->p_pgrp = rip->p_pgrp; rpp->p_nice = rip->p_nice; rpp->p_p  Hixiid = mpid; rpp->p_ppid = rip->p_pid; /* * make duplicate entries * where needed */ for(rip = &u.u_ofile[0]; rip < &u.iiu_ofile[NOFILE];) if((rpp = *rip++) != NULL) rpp->f_count++; u.u_cdir->i_count++; /* * Partially simulate the environmeIiihHHii)  bdwrite(bp); } else brelse(bp); return(nb); } /* * Pass back c to the user at his location u_base; * update u_base, u_count, and u_offset. Return -1 * on the last character of the user's read. * u_base is in the user address space unless u_s# #include "../param.h" #include "../conf.h" #include "../inode.h" #include "../user.h" #include "../buf.h" #include "../systm.hegflg is set. */ passc(c) char c; { if(subyte(u.u_base, c) < 0) { u.u_error = EFAULT; return(-1); } u.u_count--; if(++y" /* * Bmap defines the structure of file system storage * by returning the physical block number on a device given the * inhi_proc _u &_canonb _swapmap _rootdir _lbolt ode and the logical block number in a file. */ bmap(ip, bn) struct inode *ip; int bn; { register *bp, *bap, nb; int *nbp, d,_time _tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc i; d = ip->i_dev; if(bn & 0174000) { u.u_error = EFBIG; return(0); } if((ip->i_mode&ILARG) == 0) { /* * small f _file _inode _buf X_bfreeli _sleep"~sleepchanrpspricsvile algorithm */ if((bn & ~7) != 0) { /* * convert small to large */ if ((bp = alloc(d)) == NULL) retu _getps _spl6 _spl0 L2P_issig L3@_swtch"L4T_retu L1Lrn(NULL); bap = bp->b_addr; for(i=0; i<8; i++) { *bap++ = ip->i_addr[i]; ip->i_addr[i] = 0; } ip->i_addr[0] cret _putps _wakeup"\~wakeup\chancipL8lL9x_setrun= bp->b_blkno; bdwrite(bp); ip->i_mode =| ILARG; goto large; } nb = ip->i_addr[bn]; if(nb == 0 && (bp = alloc(d))"~setrunrppL11L10_swapfla ~swtchL14Trpin != NULL) { bdwrite(bp); nb = bp->b_blkno; ip->i_addr[bn] = nb; ip->i_flag =| IUPD; } return(nb); } /* * lapTL16L17L20L21L18L23L25 _idle L26rge file algorithm */ large: i = bn>>8; if((nb=ip->i_addr[i]) == 0) { ip->i_flag =| IUPD; if ((bp = alloc(d)) == NU_savu L27f_swap _newproc"~newprocupnpa1a2rppLL) return(NULL); ip->i_addr[i] = bp->b_blkno; } else bp = bread(d, nb); bap = bp->b_addr; /* * normal indirect fetripL29L30L20001L34L35_panic L20003L36ch */ i = bn & 0377; if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) { nb = nbp->b_blkno; bap[i] = nb; bdwrite(nbp);* *a, *b, c; a = from; b = to; c = count; do *b++ = *a++; while(--c); } d _runrun _curpri _rootdev _swapdev _updlock _regloc _bmap"~bmapbnbpnbipdibapnbpcsv L2"L20005L9L4_alloc L20004J_bdwrite L11 L12L1cret L10L13_bread L14w @55J@5/5CN :5 @ @m@ @m0  %^_brelse _passc"f~passcfc_subyte L17L20006L16L18_cpass"@0 @U@t5 @m4N " wD@ @mN  @ @m~cpasscL20L20009L19L20011_fubyte L22_nodev"~nodev_nulldev@ @m0f @E5 `N 5@ `N   w @"~nulldev_bcopy"~bcopytofromabccountL28u.u_offset[1] == 0) u.u_offset[0]++; u.u_base++; return(u.u_count == 0? -1: 0); } /* * Pick up and return the next charact j    wXw T jyz  p p h `Eww er from the user's * write call at location u_base; * update u_base, u_count, and u_offset. Return -1 * when u_count is exhaEw w ww DCB~wYhusted. u_base is in the user's * address space unless u_segflg is set. */ cpass() { register c; if(u.u_count == 0) returhhn(-1); if((c=fubyte(u.u_base)) < 0) { u.u_error = EFAULT; return(-1); } u.u_count--; if(++u.u_offset[1] == 0) u.u_offshet[0]++; u.u_base++; return(c&0377); } /* * Routine which sets a user error; placed in * illegal entries in the bdevsw and YXYYYYYYYYYYYYcdevsw tables. */ nodev() { u.u_error = ENODEV; } /* * Null routine; placed in insignificant entries * in the bdevsw and cYY_bdevsw _nblkdev _cdevsw _nchrdev _inode _udevsw tables. */ nulldev() { } /* * copy count words from from to to. */ bcopy(from, to, count) int *from, *to; { register  &_buf X_bfreeli _canonb _swapmap _rootdir _lbolt _time _tout _callout _mount _mpi+ |(IEXEC>>6))) == 0) { u.u_error = EACCES; goto bad; } /* * pack up arguments into * allocated disk buffer */ cp = = ip->i_uid; } /* * clear sigs, regs and return */ c = ip; for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++)  bp->b_addr; na = 0; nc = 0; while(ap = fuword(u.u_arg[1])) { na++; if(ap == -1) goto bad; u.u_arg[1] =+ 2; for(;;if((*ip & 1) == 0) *ip = 0; for(cp = ®loc[0]; cp < ®loc[6];) u.u_ar0[*cp++] = 0; u.u_ar0[R7] = TOPSYS; for(ip = &u) { c = fubyte(ap++); if(c == -1) goto bad; *cp++ = c; nc++; if(nc > 510) { u.u_error = E2BIG; goto b.u_fsav[0]; ip < &u.u_fsav[25];) *ip++ = 0; ip = c; bad: iput(ip); brelse(bp); } /* * exit system call: * pass back calad; } if(c == 0) break; } } if((nc&1) != 0) { *cp++ = 0; nc++; } /* * read in first 8 bytes * of file fler's r0 */ rexit() { u.u_arg[0] = u.u_ar0[R0] << 8; exit(); } /* * Release resources. * Save u. area for parent to look or segment * sizes: * w0 = 407 * w1 = text size * w2 = data size * w3 = bss size */ u.u_base = &u.u_arg[0]; u.u_cat. * Enter zombie state. * Wake up parent and init processes, * and dispose of children. */ exit() { register int *q, a; ount = 8; u.u_offset[1] = 0; u.u_offset[0] = 0; readi(ip); if(u.u_error) goto bad; if(u.u_arg[0] == 0407) { u.u_arg[2] register struct proc *p; p = u.u_procp; p->p_clktim = 0; for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];) *q++ = 1; for(q =+ u.u_arg[1]; } else { u.u_error = ENOEXEC; goto bad; } /* * find text and data sizes * try them out for possible = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++) if(a = *q) { *q = NULL; closef(a); } iput(u.u_cdir); #ifdef VSWAP a =  * exceed of max sizes */ ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777; if(ds + SSIZE > UCORE) goto bad; /* * allocatmalloc(swapmap, 1); if (a == NULL) panic(); p = getblk(swapdev, a); #endif #ifndef VSWAP p = getblk(swapdev, p->p_pid*SWPSIe and clear core * at this point, committed * to the new image */ cp = TOPSYS; while(cp < TOPUSR) *cp++ = 0; /* *Z + SWPLO); #endif bcopy(&u, p->b_addr, 256); bwrite(p); q = u.u_procp; #ifdef VSWAP q->p_addr = a; #endif q->p_stat = SZOM# #include "../param.h" #include "../systm.h" #include "../user.h" #include "../proc.h" #include "../buf.h" #include "../reg.h"  read in data segment */ u.u_base = TOPSYS; u.u_offset[1] = 020; u.u_count = u.u_arg[2]; u.u_dsize = ds; readi(ip); /*#include "../inode.h" /* * exec system call. */ exec() { int ap, na, nc, *bp; int ds; register c, *ip; register char *cp * initialize stack segment */ u.u_ssize = SSIZE; cp = bp->b_addr; ap = TOPUSR - nc - na*2 - 4; u.u_ar0[R6] = ap; suwo; /* * pick up file names * and check various modes * for execute permission */ ip = namei(0); if(ip == NULL) retrd(ap, na); c = TOPUSR - nc; while(na--) { suword(ap=+2, c); do subyte(c++, *cp); while(*cp++); } suword(ap+2, -1);urn; bp = getblk(NODEV); if(access(ip, IEXEC)) goto bad; if((ip->i_mode & IFMT) != 0 || (ip->i_mode & (IEXEC|(IEXEC>>3) /* * set SUID/SGID protections */ if(ip->i_mode&ISUID) if(u.u_uid != 0) { u.u_uid = ip->i_uid; u.u_procp->p_uid, C]; p++) if(q->p_pid == p->p_ppid) { p->p_ppid = 0; } runrun++; swtch(); /* no return */ } q->p_ppid = 0; goto T); goto loop; } u.u_error = ECHILD; } /* * fork system call. */ fork() { register struct proc *p1, *p2; p1 = u.u_procloop; } /* * Wait system call. * Search for a terminated (zombie) child, * finally lay it to rest, and collect its status. p; for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++) if(p2->p_stat == NULL) goto found; u.u_error = EAGAIN; goto out; found: * Look also for stopped (traced) children, * and pass back status from them. */ wait() { register f, *bp; register struct pr if(newproc()) { u.u_ar0[R0] = p1->p_pid; u.u_cstime[0] = 0; u.u_cstime[1] = 0; u.u_stime = 0; u.u_cutime[0] = 0; u.oc *p; f = 0; loop: for(p = &proc[0]; p < &proc[NPROC]; p++) if(p->p_ppid == u.u_procp->p_pid) { f++; if(p->p_stat == Su_cutime[1] = 0; u.u_utime = 0; return; } u.u_ar0[R0] = p2->p_pid; out: u.u_ar0[R7] =+ 2; } /* * break system call. *ZOMB) { u.u_ar0[R0] = p->p_pid; #ifdef VSWAP bp = bread(swapdev, f = p->p_addr); mfree(swapmap, 1, f); #endif #ifndef V -- bad planning: "break" is a dirty word in C. */ sbreak() { register a, n, d; /* * set n to new data size * set d to new-old * set n to new total size */ n = (((u.u_arg[0]-TOPSYS+63)>>6) & 01777); if(n < 0) n = 0; d = n - u.u_dsize; n =+ USIZE+u.u_ssize; if(n > UCORE) { u.u_error = E2BIG; return; } u.u_dsize =+ d; }  struct { char lobyte; char hibyte; }; struct { int integ; }; SWAP bp = bread(swapdev, p->p_pid*SWPSIZ + SWPLO); #endif p->p_stat = NULL; p->p_pid = 0; p->p_ppid = 0; p->p_sig char canonb[ 256 ]; int swapmap[ 26 ]; int *rootdir; int lbolt; int time[2]; int tout[2]; struc = 0; p->p_pgrp = 0; p->p_flag = 0; p = bp->b_addr; u.u_cstime[0] =+ p->u_cstime[0]; dpadd(u.u_cstime, p->u_cstimt callo { int c_time; int c_arg; int (*c_func)(); } callout[ 4 ]; struct mount { int m_dev; int *m_bufp; int *e[1]); dpadd(u.u_cstime, p->u_stime); u.u_cutime[0] =+ p->u_cutime[0]; dpadd(u.u_cutime, p->u_cutime[1]); dpadd(u.u_m_inodp; } mount[ 4 ]; int mpid; char runrun; char curpri; int rootdev; int swapdev; int updlock; char regloB; loop: for(p = &proc[0]; p < &proc[NPROC]; p++) if(q->p_ppid == p->p_pid) { wakeup(p); for(p = &proc[0]; p < &proc[NPROcutime, p->u_utime); u.u_ar0[R1] = p->u_arg[0]; brelse(bp); return; } } if(f) { runrun++; sleep(u.u_procp, PWAI- actf; struct buf *d_actl; }; struct buf bfreelist; struct inode { char i_flag; char i_coun; do subyte(c++, *cp); while(*cp++); } suword(ap+2, -1); if(ip->i_mode& 04000 ) if(u.u_uid != 0) { u.u_ut; int i_dev; int i_number; int i_mode; char i_nlink; char i_uid; char i_gid; char i_size0; char *i_size1; iid = ip->i_uid; u.u_procp->p_uid = ip->i_uid; } c = ip; for(ip = &u.u_signal[0]; ip < &u.u_signal[ 20 ]; ip++) ic[]; struct user { int u_rsav[2]; int u_fsav[25]; char u_segflg; char u_error; char u_uid; char u_gint i_addr[8]; } inode[ 50 ]; exec() { int ap, na, nc, *bp; int ds; register c, *ip; register chad; char u_ruid; char u_rgid; int u_procp; char *u_base; char *u_count; char *u_offset[2]; int *u_cdir; r *cp; ip = namei(0); if(ip == 0 ) return; bp = getblk( (-1) ); if(access(ip, 0100 )) goto bad; if((ip->i_ char u_dbuf[ 14 ]; char *u_dirp; struct { int u_ino; char u_name[ 14 ]; } u_dent; int *u_pdir; int u_uimode & 060000 ) != 0 || (ip->i_mode & ( 0100 |( 0100 >>3)|( 0100 >>6))) == 0) { u.u_error = 13 ; goto bad; } sa[16]; int u_uisd[16]; int u_ofile[ 15 ]; int u_arg[5]; int u_tsize; int u_dsize; int u_ssize; int u_sep cp = bp->b_addr; na = 0; nc = 0; while(ap = fuword(u.u_arg[1])) { na++; if(ap == -1) goto bad; u.u_arg[1] =+ ; int u_qsav[2]; int u_ssav[2]; int u_signal[ 20 ]; int u_utime; int u_stime; int u_cutime[2]; int u_csti2; for(;;) { c = fubyte(ap++); if(c == -1) goto bad; *cp++ = c; nc++; if(nc > 510) { u.u_error = 7 ; me[2]; int *u_ar0; int u_prof[4]; char u_intflg; int u_ttyp; int u_ttyd; } u;  goto bad; } if(c == 0) break; } } if((nc&1) != 0) { *cp++ = 0; nc++; } u.u_base = &u.u_arg[0 struct proc { char p_stat; char p_flag; char p_pri; char p_sig; char p_uid; char p_time; char p_cpu;]; u.u_count = 8; u.u_offset[1] = 0; u.u_offset[0] = 0; readi(ip); if(u.u_error) goto bad; if(u.u_arg[0] == 0407) { u. char p_nice; int p_pgrp; int p_pid; int p_ppid; int p_wchan; int p_addr; int p_clktim; int p_size; } pru_arg[2] =+ u.u_arg[1]; } else { u.u_error = 8 ; goto bad; } ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777; if(oc[ 13 ]; struct buf { int b_flags; struct buf *b_forw; struct buf *b_back; struct buf *av_forw; ds + 20 > (16*32) ) goto bad; cp = 12*2048 ; while(cp < 28*2048 ) *cp++ = 0; u.u_base = 12*204 struct buf *av_back; int b_dev; int b_wcount; char *b_addr; char *b_blkno; char b_error; char *b_resid; } 8 ; u.u_offset[1] = 020; u.u_count = u.u_arg[2]; u.u_dsize = ds; readi(ip); u.u_ssize = 20 ; cp = bp->b_addr; abuf[ 4 ]; struct devtab { char d_active; char d_errcnt; struct buf *b_forw; struct buf *b_back; struct buf *d_p = 28*2048 - nc - na*2 - 4; u.u_ar0[ (-3) ] = ap; suword(ap, na); c = 28*2048 - nc; while(na--) { suword(ap=+2, c).  { *q = 0 ; closef(a); } iput(u.u_cdir); mfree(swapmap, p->p_size, p->p_addr); a = malloc(swapmap, 1); if (a ==  return; } u.u_ar0[ (0) ] = p2->p_pid; out: u.u_ar0[ (1) ] =+ 2; } sbreak() { register a, n, d; n = (((u.u 0 ) panic(); p = getblk(swapdev, a); bcopy(&u, p->b_addr, 256); bwrite(p); q = u.u_procp; q->p_addr = a; q->p_sta_arg[0]- 12*2048 +63)>>6) & 01777); if(n < 0) n = 0; d = n - u.u_dsize; n =+ 16 +u.u_ssize; if(n > (16*32) ) { u.t = 5 ; loop: for(p = &proc[0]; p < &proc[ 13 ]; p++) if(q->p_ppid == p->p_pid) { wakeup(p); for(p = &proc[0]; p <u_error = 7 ; return; } u.u_dsize =+ d; }  &proc[ 13 ]; p++) if(q->p_pid == p->p_ppid) { p->p_ppid = 0; } runrun++; swtch(); } q->p_ppid = 0; goto loop; } wait() { register f, *bp; register struct proc *p; f = 0; loop: for(p = &proc[0]; p < &proc[ 13 ]; p++) f((*ip & 1) == 0) *ip = 0; for(cp = ®loc[0]; cp < ®loc[6];) u.u_ar0[*cp++] = 0; u.u_ar0[ (1) ] = 12*2048 ; for(if(p->p_ppid == u.u_procp->p_pid) { f++; if(p->p_stat == 5 ) { u.u_ar0[ (0) ] = p->p_pid; bp = bread(swapdev, f ip = &u.u_fsav[0]; ip < &u.u_fsav[25];) *ip++ = 0; ip = c; bad: iput(ip); brelse(bp); } rexit() { u.u_arg[0] = u.u_= p->p_addr); mfree(swapmap, 1, f); p->p_stat = 0 ; p->p_pid = 0; p->p_ppid = 0; p->p_sig = 0; p->p_pgrp !"#$&'()* = 0; p->p_flag = 0; p = bp->b_addr; u.u_cstime[0] =+ p->u_cstime[0]; dpadd(u.u_cstime, p->u_cstime[1]); dpadd(u.u_cstime, p->u_stime); u.u_cutime[0] =+ p->u_cutime[0]; dpadd(u.u_cutime, p->u_cutime[1]); dpadd(u.u_cutime, p->u_utime); u.u_ar0[ (-2) ] = p->u_arg[0]; brelse(bp); return; } } if(f) { runrun++; sleep(u.u_procp, 40 ); goto loop; } u.u_error = 10 ; } fork() { register struct proc *p1, *p2; p1 = u.u_procp; for(p2 = &proc[0]; p2 < &proc[ 13 ar0[ (0) ] << 8; exit(); } exit() { register int *q, a; register struct proc *p; p = u.u_procp; p->p_clktim = 0;  ]; p2++) if(p2->p_stat == 0 ) goto found; u.u_error = 11 ; goto out; found: if(newproc()) { u.u_ar0[ (0) ] = p for(q = &u.u_signal[0]; q < &u.u_signal[ 20 ];) *q++ = 1; for(q = &u.u_ofile[0]; q < &u.u_ofile[ 15 ]; q++) if(a = *q)1->p_pid; u.u_cstime[0] = 0; u.u_cstime[1] = 0; u.u_stime = 0; u.u_cutime[0] = 0; u.u_cutime[1] = 0; u.u_utime = 0; / 2 %   e%   D>  % V̕_canonb,  , 2 e% e%4 w  , P ʥL   _swapmap _rootdir _lbolt _time _tout _callout _mount _mpid _runrun _curpri _roo % 2 2 22 2lz   lT   < e%tdev _swapdev _updlock _regloc _u &_proc _buf X_bfreeli _inode _exec"~exec (:  'ww  ˋ e%  ? 7 7 7 7 7 7  1`naapncbpdsipcpccsv _namei L1ww Le?tE  @>e`%`$wL(N_getblk _access L2@L10000FL3PL4L20009bL6v_fubyte L8_fuword L9_readi L10,L12"L136_suword L14L20001L18_subyte L19L20003L23 L20005L200076_iput _brelse cret _rexit"R~rexitR_exitX"j~exitjaqpL20011zL20013L35_closef _malloc L37_pan|w  _N 5@ _@5`5I _@@5 5 $ %_@eTN %_@ %_@  55 rn7 n7 h S_@%mme?tE5e%_@`%_@`w |@@A I@e5pNf Def & ҋ@ fe 5 N FF 5 e%  m %` %6 N ww t7f ww (0 L54 _sleep _fork"~forkp1p2L20021 L596L60d_newproc L61lse open1(ip, FWRITE, 1); } /* * common code for open and creat. * Check permissions, allocate an open file structure, * a^L55p_sbreak"t~sbreaktadnL63L64L62nd call the device open routine if any. */ open1(ip, mode, trf) int *ip; { register struct file *fp; register *rip, m; int i; rip = ip; m = mode; if(trf != 2) { if(m&FREAD) access(rip, IREAD); if(m&FWRITE) { access(rip, IWRITE); if((rip->i_mode&IFMT) == IFDIR) u.u_error = EISDIR; } } if(u.u_error) goto out; if(trf) itrunc(rip); prele(rip); if ((f# #include "../param.h" #include "../systm.h" #include "../user.h" #include "../reg.h" #include "../file.h" #include "../inode.hp = falloc()) == NULL) goto out; fp->f_flag = m&(FREAD|FWRITE); fp->f_inode = rip; i = u.u_ar0[R0]; openi(rip, m&FWRITE); " /* * read system call */ read() { rdwr(FREAD); } /* * write system call */ write() { rdwr(FWRITE); } /* * common cod if(u.u_error == 0) return; u.u_ofile[i] = NULL; fp->f_count--; out: iput(rip); } /* * close system call */ close() { e for read and write calls: * check permissions, set base, count, and offset, * and switch out to readi, writei, or pipe code.register *fp; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; u.u_ofile[u.u_ar0[R0]] = NULL; closef(fp); } /* * seek sys */ rdwr(mode) { register *fp, m; m = mode; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; if((fp->f_flag&m) == 0) { tem call */ seek() { int n[2]; register *fp, t; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; if(fp->f_flag&FPIPE) { u.u_error = EBADF; return; } u.u_base = u.u_arg[0]; u.u_count = u.u_arg[1]; u.u_offset[1] = fp->f_offset[1]; u.u_offset[0 u.u_error = ESPIPE; return; } t = u.u_arg[1]; if(t > 2) { n[1] = u.u_arg[0]<<9; n[0] = u.u_arg[0]>>7; if(t == 3) ] = fp->f_offset[0]; if(m==FREAD) readi(fp->f_inode); else writei(fp->f_inode); dpadd(fp->f_offset, u.u_arg[1]-u.u_count);n[0] =& 0777; } else { n[1] = u.u_arg[0]; n[0] = 0; if(t!=0 && n[1]<0) n[0] = -1; } switch(t) { case 1: case 4:  u.u_ar0[R0] = u.u_arg[1]-u.u_count; } /* * open system call */ open() { register *ip; ip = namei(0); if(ip == NULL) r n[0] =+ fp->f_offset[0]; dpadd(n, fp->f_offset[1]); break; default: n[0] =+ fp->f_inode->i_size0&0377; dpadd(n, fp->fic _bcopy _bwrite L38L20017L41"_wakeup L20015L45_swtch _wait"2eturn; u.u_arg[1]++; open1(ip, u.u_arg[1], 0); } /* * creat system call */ creat() { register *ip; ip = namei(1); if(ip~wait2bpfpL488L20019<L51_bread _mfree _dpadd L47 == NULL) { if(u.u_error) return; ip = maknode(u.u_arg[1]&07777); if (ip==NULL) return; open1(ip, FWRITE, 2); } e1  |w  ww  ww C .̰ (77%  I HH_inode->i_size1); case 0: case 3: ; } fp->f_offset[1] = n[1]; fp->f_offset[0] = n[0]; } /* * link system call */ linkV&e B?wlw h   $ & %wHw D kE  & () { register *ip, *xp; ip = namei(0); if(ip == NULL) return; if(ip->i_nlink >= 127) { u.u_error = EMLINK; goto out; %ww  CB%5 5 E%@'   E  } if((ip->i_mode&IFMT)==IFDIR && !suser()) goto out; /* * unlock to avoid possibly hanging the namei */ ip->i_flag =& E @ 0  w\w Xj ^ 0  w8w 4B D̵O=%~ILOCK; u.u_dirp = u.u_arg[1]; xp = namei(1); if(xp != NULL) { u.u_error = EEXIST; iput(xp); } if(u.u_error) goto outt 5t5%E 5    x5mfe ttw ; if(u.u_pdir->i_dev != ip->i_dev) { iput(u.u_pdir); u.u_error = EXDEV; goto out; } wdir(ip); ip->i_nlink++; ip->i_flE5` w z >3E%@ N (  e [0- ag =| IUPD; out: iput(ip); } /* * mknod system call */ mknod() { register *ip; if(suser()) { ip = namei(1); if(ip !=A  ww      ww  f NULL) { u.u_error = EEXIST; goto out; } } if(u.u_error) return; ip = maknode(u.u_arg[1]); if (ip==NULL) return;e ~ff e  fwb`ZXR e Nf<6 e w$w Z  ip->i_addr[0] = u.u_arg[2]; out: iput(ip); } /* * sleep system call * not to be confused with the sleep internal routine.XBhXBIiIiI8 */ sslep() { char *d[2]; spl7(); d[0] = time[0]; d[1] = time[1]; dpadd(d, u.u_ar0[R0]); while(dpcmp(d[0], d[1], time[0HiIiI], time[1]) > 0) { if(dpcmp(tout[0], tout[1], time[0], time[1]) <= 0 || dpcmp(tout[0], tout[1], d[0], d[1]) > 0) { touiIt[0] = d[0]; tout[1] = d[1]; } sleep(tout, PSLEP); } spl0(); } (HiIiIHi2 k"L10001L25XL28BL29h~seekfpntL19dL20 0) return; u.u_ofile[i] = fp; fp->f_count++; } /* * the mount system call. */ smount() { int d; register *ip; registeL21L234L20007L_link"~linkipxpL32 L33L34L10002r struct mount *mp, *smp; d = getmdev(); if(u.u_error) return; u.u_dirp = u.u_arg[1]; ip = namei(0); if(ip == NULL) re_suser L35L36_wdir _mknod"~mknodipL380L40HL37N_sslturn; if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) goto out; smp = NULL; for(mp = &mount[0]; mp < &mount[NMOUNT]; mpep"R~sslepRd_spl7 L20008x_dpcmp L20010_spl0 L10003L44_sleep ++) { if(mp->m_bufp != NULL) { if(d == mp->m_dev) goto out; } else if(smp == NULL) smp = mp; } if(smp == NULL)8HiI HiIIIHIIiIIYYYYYYXH# #include "../param.h" #include "../systm.h" #include "../reg.h" #include "../buf.h" #include "../filsys.h" #include "../user.h_canonb _swapmap _rootdir _lbolt _time _tout _callout _mount _mpid _runrun _cur" #include "../inode.h" #include "../file.h" #include "../conf.h" /* * the fstat system call. */ fstat() { register *fp; fpri _rootdev _swapdev _updlock _regloc _u &_file _inode _read"~readcsv p = getf(u.u_ar0[R0]); if(fp == NULL) return; stat1(fp->f_inode, u.u_arg[0]); } /* * the stat system call. */ stat() { r_rdwr" cret _write"~write~rdwr fpmodem_getf L3L4egister ip; ip = namei(0); if(ip == NULL) return; stat1(ip, u.u_arg[1]); iput(ip); } /* * The basic routine for fstat a@L5h_readi L6p_writei _dpadd _open"~openip_namei L7_opend stat: * get the inode and pass appropriate parts back. */ stat1(ip, ub) int *ip; { register i, *bp, *cp; iupdat(ip); bpn1"_creat"~creatipL9L8_maknode L20003~open1fpip = bread(ip->i_dev, ldiv(ip->i_number+31, 16)); cp = bp->b_addr + 32*lrem(ip->i_number+31, 16) + 24; ip = &(ip->i_dev); for(imodeimriptrfL12FL13 _access L16L17X_itrunc=0; i<14; i++) { suword(ub, *ip++); ub =+ 2; } for(i=0; i<4; i++) { suword(ub, *cp++); ub =+ 2; } brelse(bp); } /*  _prele _falloc _openi L11_iput _close"~closefpL18_closef _see * the dup system call. */ dup() { register i, *fp; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; if ((i = ufalloc()) <3 d==ip->i_dev) { u.u_error = EBUSY; return; } ip = mp->m_inodp; ip->i_flag =& ~IMOUNT; iput(ip); ip = mp->m_bufp; mp8->m_bufp = NULL; brelse(ip); } /* * Common code for mount and umount. * Check that the user's argument is a reasonable * th8xXx8ing on which to mount, and return the device number if so. */ getmdev() { register d, *ip; ip = namei(0); if(ip == NULL) 8 xxreturn; if((ip->i_mode&IFMT) != IFBLK) u.u_error = ENOTBLK; d = ip->i_addr[0]; if(ip->i_addr[0].d_major >= nblkdev) u.u_e((X88YXrror = ENXIO; iput(ip); return(d); } _canonb _swapmap _rootdir _lbolt _time _tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _buf X_bfreeli _u &_inode _file _bdevsw \w  & F ww   & F  ww N @&e @&_nblkdev _cdevsw _nchrdev _fstat"~fstatfpcsv _getf L1_stat1"Fcret goto out; mp = bread(d, 1); if(u.u_error) { brelse(mp); goto out1; } smp->m_inodp = ip; smp->m_dev = d; smp->m_bufp @&e tle@e5 Nef e % f e %  = getblk(NODEV); bcopy(mp->b_addr, smp->m_bufp->b_addr, 256); smp = smp->m_bufp->b_addr; smp->s_ilock = 0; smp->s_flock = 0w w     ww R5    5     "  w; smp->s_ronly = u.u_arg[2] & 1; brelse(mp); ip->i_flag =| IMOUNT; prele(ip); return; out: u.u_error = EBUSY; out1: iput e% f  2J 2& %22E2 (ip); } /* * the umount system call. */ sumount() { int d; register struct inode *ip; register struct mount *mp; update( w  p5'1 " e%  5-e% 3 ); d = getmdev(); if(u.u_error) return; for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if(mp->m_bufp!=NULL && d==mp->m_de ww  E%`-Z wF8v) goto found; u.u_error = EINVAL; return; found: for(ip = &inode[0]; ip < &inode[NINODE]; ip++) if(ip->i_number!=0 && X4 _getmdev"xL11lL12`L20005TL16pL15vL20fL19_getblk _bcopy _pre: iput(pp); } chdir() { register *ip; ip = namei(0); if(ip == NULL) return; if((ip->i_mode&IFMT) != IFDIR) { u.u_errole _sumount"~sumountipmpd_update L21tL20007L24"L254r = ENOTDIR; bad: iput(ip); return; } if(access(ip, IEXEC)) goto bad; iput(u.u_cdir); u.u_cdir = ip; prele(ip); } cL200098L28N~getmdevxipdL30L31L32hmod() { register *ip; if ((ip = owner()) == NULL) return; ip->i_mode =& ~07777; ip->i_mode =| u.u_arg[1]&07777; ip->i_f# /* * Everything in this file is a routine implementing a system call. */ #include "../param.h" #include "../user.h" #includlag =| IUPD; iput(ip); } chown() { register *ip; if (!suser() || (ip = owner()) == NULL) return; ip->i_uid = u.u_arg[1].e "../reg.h" #include "../inode.h" #include "../systm.h" #include "../proc.h" getswit() { u.u_ar0[R0] = 0177300; } gtime() {lobyte; ip->i_gid = u.u_arg[1].hibyte; ip->i_flag =| IUPD; iput(ip); } ssig() { register a; a = u.u_arg[0]; if(a<=0 || a u.u_ar0[R0] = time[0]; u.u_ar0[R1] = time[1]; } stime() { if(suser()) { time[0] = u.u_ar0[R0]; time[1] = u.u_ar0[R1];>=NSIG || a==SIGKIL) { u.u_error = EINVAL; return; } u.u_ar0[R0] = u.u_signal[a]; u.u_signal[a] = u.u_arg[1]; if(u.u_pro wakeup(tout); } } setuid() { register uid; uid = u.u_ar0[R0].lobyte; if(u.u_ruid == uid.lobyte || suser()) { u.u_uid cp->p_sig == a) u.u_procp->p_sig = 0; } kill() { register struct proc *p, *q; register a; int f; f = 0; a = u.u_ar0[R0]= uid; u.u_procp->p_uid = uid; u.u_ruid = uid; } } getuid() { u.u_ar0[R0].lobyte = u.u_ruid; u.u_ar0[R0].hibyte = u.u_u; q = u.u_procp; for(p = &proc[0]; p < &proc[NPROC]; p++) { if(p == q) continue; if(a != 0 && p->p_pid != a) continuid; } getpid() { u.u_ar0[R0] = u.u_procp->p_pid; } sync() { update(); } nice() { register n; n = u.u_ar0[R0]; if(n > 2e; if(a == 0 && (p->p_pgrp != q->p_pgrp || p <= &proc[1])) continue; if(u.u_uid != 0 && u.u_uid != p->p_uid) continue;0) n = 20; if(n < 0 && !suser()) n = 0; u.u_procp->p_nice = n; } /* * Unlink system call. * panic: unlink -- "cannot ha f++; psignal(p, u.u_arg[0]); } if(f == 0) u.u_error = ESRCH; } times() { register *p; for(p = &u.u_utime; p < &u.u _stat""~stat"ip_namei L2B_iput ~stat1Fbpcpipubppen" */ unlink() { register *ip, *pp; pp = namei(2); if(pp == NULL) return; prele(pp); ip = iget(pp->i_dev, u.u_dent.ui_iupdat _ldiv _bread _lrem L20001_suword L20003_brelse _dup"_ino); if(ip == NULL) goto out1; if((ip->i_mode&IFMT)==IFDIR && !suser()) goto out; u.u_offset[1] =- DIRSIZ+2; u.u_base ~dupfpiL10_ufalloc _smount"~smountipmpdsmp= &u.u_dent; u.u_count = DIRSIZ+2; u.u_dent.u_ino = 0; writei(pp); ip->i_nlink--; ip->i_flag =| IUPD; out: iput(ip); out15 _utime+6;) { suword(u.u_arg[0], *p++); u.u_arg[0] =+ 2; } } /* * alarm clock signal */ alarm() { register c, *p; p = 7ww wpw l? xw^w Z VwRw N`%  8  j0w&w " / u.u_procp; c = p->p_clktim; p->p_clktim = u.u_ar0[R0]; u.u_ar0[R0] = c; } /* * indefinite wait. * no one should wakeup(&u)d  E%@ &X7 *   ww  E%@ */ pause() { for(;;) sleep(&u, PSLEP); } /* * Implement the halt system call; bring down the system gracefully. * mg @&  7 wdw ` \EE4P w8w 4 0  (   s 1/80 */ halt() { register struct proc *p, *procs; register done; extern wakeup(); if (!suser()) return; /* caller mustw w %% % ? !0ww 5     , be super user */ spl7(); /* wait for update completion */ for (;;) { if (updlock==0) break; idle(); } updloc%7 <& e%܂ wRw N  e%w.w *b4?.ww k++; procs = u.u_procp; for (p= &proc[0]; p<&proc[NPROC]; p++) if (p!=procs) psignal(p,SIGKIL); spl0(); u.u_ar0[R0] = 2; Z w C     & e%   ̋   @0  do { /* wait for everything done */ sslep(); done = 0; for (p= &proc[0]; p<&proc[NPROC]; p++) if (p->p_stat!=NULL &e%%7 v r nwjI YIi iYI i ixYI & p->p_stat&SZOMB==0) done++; u.u_ar0[R0] = 1; } while(done > 1); updlock = 0; update(); /* printf("\7"); printf("Halted YI YI YIYI  Y[IDbin5en& I(H X  YI(tn____   HYIY YIY_(Y YI   YI   YI ( YI w  ww ww 7 ww ğ7 70 YIII y 6 p_pause"~pauseL34_sleep _halt"~haltdonepprocsL36ullsys, /* 30 = smdate; inoperative */ 1, &stty, /* 31 = stty */ 1, >ty, /* 32 = gtty */ 2, &nosys, /* 33 = access _spl7 L37L20005_idle L20007(L418_spl0 L45L_sslep L20009V*/ 0, &nice, /* 34 = nice */ 0, &sslep, /* 35 = sleep */ 0, &sync, /* 36 = sync */ 1, &kill, /* 37 = kill */ 0, &geL48pL10006fL10007j_haltins tswit, /* 38 = switch */ 0, &nosys, /* 39 = x */ 0, &nosys, /* 40 = x */ 0, &dup, /* 41 = dup */ 0, &nosys, /* 42  Y_u &_inode _canonb _swapmap _rootdir _lbolt _time _tout _callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _reg# /* * This table is the switch used to transfer * to the appropriate routine for processing a system call. * Each row contailoc _proc _getswit"~getswitcsv cret _gtime"~gtime_stime"&~stime&_suser ns the number of arguments expected * and a pointer to the routine. */ int sysent[] { 0, &nullsys, /* 0 = indir */ 0, &reL3J_wakeup _setuid"N~setuidNuidL10000dL5t_getuid"x~getuidx_getpid"~getpidxit, /* 1 = exit */ 0, &fork, /* 2 = fork */ 2, &read, /* 3 = read */ 2, &write, /* 4 = write */ 2, &open, /* _sync"~sync_update _nice"~nicenL11L12_unlink"~unlinkip 5 = open */ 0, &close, /* 6 = close */ 0, &wait, /* 7 = wait */ 2, &creat, /* 8 = creat */ 2, &link, /* 9 = linpp_namei L13H_prele _iget L14BL10001L15<_writei _iput k */ 1, &unlink, /* 10 = unlink */ 2, &exec, /* 11 = exec */ 1, &chdir, /* 12 = chdir */ 0, >ime, /* 13 = time */ _chdir"L~chdirLipL16L17vL18n_access _chmod"~chmodip_owner 3, &mknod, /* 14 = mknod */ 2, &chmod, /* 15 = chmod */ 2, &chown, /* 16 = chown */ 1, &sbreak, /* 17 = break */ 2, L19_chown"~chownipL20_ssig"~ssigaL10002 L22L21 &stat, /* 18 = stat */ 2, &seek, /* 19 = seek */ 0, &getpid, /* 20 = getpid */ 3, &smount, /* 21 = mount */ 1, &sum<_kill"@~kill@afpqL20001VL27L10003dL10004vount, /* 22 = umount */ 0, &setuid, /* 23 = setuid */ 0, &getuid, /* 24 = getuid */ 0, &stime, /* 25 = stime */ 3, &L10005_psignal L24_times"~timespL20003_suword _alarm"~alarmcnullsys, /* 26 = ptrace */ 0, &alarm, /* 27 = alarm */ 1, &fstat, /* 28 = fstat */ 0, &pause, /* 29 = pause */ 1, &n7 # #include "../param.h" #include "../systm.h" #include "../user.h" #include "../proc.h" #include "../reg.h" #define EBIT 1 /* user error bit in PS: C-bit */ #define SETD 0170011 /* SETD instruction */ #define SYS 0104400 /* sys (trap) instruction */ #define USER 020 /* user-mode flag added to dev */ /* * structure of the system entry table (sysent.c) */ struct sysent { int(8HXhx(8HXhx count; /* argument count */ int (*call)(); /* name of handler */ } sysent[64]; /* * Offsets of the user's registers relativ(8HXhxe to * the saved r0. See reg.h */ char regloc[9] { R0, R1, R2, R3, R4, R5, R6, R7, RPS }; /* * Called from l40.s or l45.s w_sysent#_nullsys _rexit _fork _read _write _open _close _wait _crehen a processor trap occurs. * The arguments are the words saved on the system stack * by the hardware and software during the= pipe */ 1, ×, /* 43 = times */ 4, &nosys, /* 44 = prof */ 0, &nosys, /* 45 = tiu */ 0, &nullsys, /* 46 = setgat _link _unlink _exec _chdir _gtime _mknod _chmod _chown _sbreak _stat id */ 0, &nullsys, /* 47 = getgid */ 2, &ssig, /* 48 = sig */ 0, &nosys, /* 49 = x */ 0, &nosys, /* 50 = x */ 0, &n_seek _getpid _smount _sumount _setuid _getuid _stime _alarm _fstat _pause _sttyosys, /* 51 = x */ 0, &nosys, /* 52 = x */ 0, &nosys, /* 53 = x */ 0, &nosys, /* 54 = x */ 0, &nosys, /* 55 = x */ _gtty _nosys _nice _sslep _sync _kill _getswit _dup _times _ssig _hal 0, &nosys, /* 56 = x */ 0, &nosys, /* 57 = x */ 0, &nosys, /* 58 = x */ 0, &nosys, /* 59 = x */ 0, &nosys, /* 60t  = x */ 0, &nosys, /* 61 = x */ 0, &halt, /* 62 = halt */ /* * never change the entry for sys. call 63...the system depends on it * being set to "&nosys". See "trap.c" */ 0, &nosys /* 63 = nosys */ }; 8 ; case 0+USER: /* bus error */ i = SIGBUS; break; /* * If illegal instructions are not * being caught and the offendt * clearing u_intflg; if it's still set, trap * marks an error which means that a system * call (like read on a typewriter) ing instruction * is a SETD, the trap is ignored. * This is because C produces a SETD at * the beginning of every program got interrupted * by a signal. */ trap1(f) int (*f)(); { u.u_intflg = 1; savu(u.u_qsav); (*f)(); u.u_intflg = 0; } /* *which * will trap on CPUs without 11/45 FPU. */ case 1+USER: /* illegal instruction */ if(fuiword(pc-2) == SETD && u.u_si nonexistent system call-- set fatal error code. */ nosys() { u.u_error = 100; } /* * Ignored system call */ nullsys() { } gnal[SIGINS] == 0) goto out; i = SIGINS; break; case 2+USER: /* bpt or trace */ i = SIGTRC; break; case 3+USER: /* iot */ i = SIGIOT; break; case 5+USER: /* emt */ i = SIGEMT; break; case 6+USER: /* sys call */ u.u_error = 0;  ps =& ~EBIT; callp = &sysent[fuiword(pc-2)&077]; if (callp == sysent) { /* indirect */ a = fuiword(pc); pc =+ 2; i$w %`U@e 7@  x    wNe %   = fuword(a); if ((i & ~077) != SYS) i = 077; /* illegal */ callp = &sysent[i&077]; for(i=0; icount; i++) 7ENe Ete%)N e E?%?Ete "e u.u_arg[i] = fuword(a =+ 2); } else { for(i=0; icount; i++) { u.u_arg[i] = fuiword(pc); pc =+ 2; }   1  N  1e "0 fd_DU5 _D _8w } u.u_dirp = u.u_arg[0]; trap1(callp->call); if(u.u_intflg) u.u_error = EINTR; if(u.u_error < 100) { if(u.u_error) 7w|w xdwnw jwf4Trx0~i trap processing. * Their order is dictated by the hardware and the details * of C's calling sequence. They are peculiar in th { ps =| EBIT; r0 = u.u_error; } goto out; } i = SIGSYS; break; } psignal(u.u_procp, i); out: if(issig()at * this call is not 'by value' and changed user registers * get copied back on return. * dev is the kind of trap that occur) psig(); } /* * Call the system-entry routine f (out of the * sysent table). This is a subroutine for trap, and * not in-red. */ trap(dev, sp, r1, nps, r0, pc, ps) char *pc; { register i, a; register struct sysent *callp; if(pc > TOPSYS) dev line, because if a signal occurs * during processing, an (abnormal) return is simulated from * the last caller to savu(qsav); =| USER; u.u_ar0 = &r0; switch(dev) { /* * Trap not expected. * Usually a kernel mode bus error. */ default: dump()if this took place * inside of trap, it wouldn't have a chance to clean up. * * If this occurs, the return takes place withou9 VVVn____- -,  ĥ e BtU2ĥ$8 tĥ0+ĥ9(e- m7 ğ ċ7 ~I_(Y 2ĥ\ &ĥ  w ĥ$vREw X d%\ ` R N B w4 %4 6 fe& q%% .q   @w eu-Vt@& m Nf nd w w 5 DD-Br7R y e r 5 bf $e 33 %&UaN&e .d 3  Nf $e w w  DD-0r7  y e   bf e 2N&e(Y?YY$94YY(Y(Y_8(YY (YpN_9b9(YIb_ * ;I t_l_n_ HYU_T=@ |_| $e 22 w Nf e w j 5 @ȥ)U5 5 5 5 5 5 DD-_f5s7  y HYU_*?UHY|I___|} 0 AII_!IIIVAII_'A4v_24\A4v_3'z4vzߴߪzz(o  e5 e 5eD->U eD-Zt& m %< & 6  .qw  p % n% p 7 & Br%7e04v Bss 5 ~5 @ @m ! P bNf nd 3sss 75sts~%47 ^--c%Pt> p  q w @ @m Ne b5 u-@ `A Amp w Be  &  w w  tms Dm- do  do e7@ 7  tm h7 w zvz4v ^tf m @w~ w l @Ewn w \  A@ : xs@ bt n ht n .@z77| R˥ ztH{ppl  bPz .d Ls Dm gw:w ( e   n kt Dm% t tm   e wt n tt n t n   r erA! y  Ġ(ĥ 7wU? ?  7t& m ? 7 N tt n  x   pNe t n tt n  @ N  pNe t n tu n  [IDbindbin& m ?| xw xv@ 7`l-jft tm` wZw HJĝD7@`. ĥ e4t Dm: fr tm5u tm u Dm5!N nwl nw Rw\w JwTfwuwT f@)w>fwannot execute wait:try again : cannot open: cannot create/dev/null/etc/globglob: cannot execute /usr/bin/: not foundw < ouwfw7 fw w w w  wfAW @wH fT{/bin/shNo shell! : too large : -- Core dumped 7v 0+(v  %ew &n u n @55 5 5%u_h %5 N p@ p5@N m u1T{7< 5 eow(u 5& wx& L& H& D& @&z <&t 8&n 4&h 0& tm5_BhNf@  p @& q 5 @ tm"u Dm V@ =5@& q 5b ,&\ (&V $&P &J &D &> &8 &2 &, && & f& f$f & f q%@& p 5 @ tm0u Dm  pN nN p5 pN nN p@ BRfw,ufwuw| f |& wb }f@wF fww p5 p@ nN p@ p5 @  5  p @u q 5 4   do  uw&@& HADCBFf@ffA w,w"|e"w"rew"h@lw"` do %@@E4P g   p7 ~gf Xg @JuNe@& n Tu tm AlewS &@t`e fw0w,uwlf@wwuwJf@wwgf Xg ?| N@& l f ju @ NF e l N4 l @ tmtu Dm 8@5uw( f@wwuw7 F6rw* 6r@s%s,s1sEsTs]sfsyssss\ p  p J q 58 q 5* p@@EU4PNef& g%@@EU4Pssssssrrrr$  )' pbabFbpbFbbFbFbFbpbaFbFbFbFb &(); dddddd()^|lHePeTeTeNfe& g%_Bh@E5@t] g@t] g_Bhw 8De f n %T  Je()<>le"fLf.ffgikl.__pf0HangupQuitIllegal instructionTrace/BPT trapIOT trapEMT trapFloating exceptionKilled ue& n u tm %   tmu Dm ww N tmu tm  & & q% ww DBus errorMemory faultBad system callSig 14Sig 15Sig 16Sig 17Sig 18Sig 19/usr/adm/sha% # /usr/adm/shb: cannot opens m̋ww fe r%wvw d f& Br% m f& Tr%e0 mw:w (D̋@-wyntax error '" ;&<>()|^ "'Command line overflow Too many argsToo many characters;& <>([?*chdircdchdir: bad directory w DCԢӋw w  ?(v p(v |pNe p%.CE frD- mu tm /usrchdir: "/usr" bad directoryshiftshift: no args synclogin/bin/loginlogin: cannot execute newgrp/bin/newgrpnewgrp: c; 4v 75sts~%47 ^--c%Pt> p  q z4v tms Dm- do  do e7@ 7  tm h7 w zvz4v߶az77| R˥ ztH{ppl  bPz .d Ls Dm gw:w ( e Lnߪ߀z4vz6iuzz7vz߼lzddz߀z7vazsfas`- r erA! y  Ġ(ĥ 7wU? ?  7t& m ? 7 N t[IDbin4vdbin& m ?| xw xv@ 7`l-jft tm` wZw HJĝD7@`. ĥ e4t Dm00001s9vz zvzzH{lWls VVV4vn____ J_(Y(Y?YY$94YY(Y(Y_8(YY (YpN_9b9(YIb_ * ;I t_l_n_ HYU|HYU_ |HYU_J?U|I___|} < AI \II_I4v_'I("A4v_24\"A4v_3&z4vzߴLnp & 6  .qw  p % n% p 7 & Br%7e04v Bss<  $e 22 w Nf e w j 5 @ȥ)U5 5 5 5 5 5 DD-_f5s7  y \ p  p J q 58 q 5* p@@EU4PNef& g%@@EU4P  e5 e 5eD->U eD-Zt& m %<Nfe& g%_Bh@E5@t] g@t] g_Bhw 8De f n %T   5 ~5 @ @m ! P bNf nd 3sss ue& n u tm %   tmu Dm ww N tmu tm  & & q% ww Dw @ @m Ne b5 u-@ `A Amp w Be  &  w w  m̋ww fe r%wvw d f& Br% m f& Tr%e0 mw:w (D̋@-w ^tf m @w~ w l @Ewn w \  A@ : xs@ bt n ht n .@ w DCԢӋw w  ?(v p(v |pNe p%.CE frD- mu tm   n kt Dm% t tm   e wt n tt n t n  fr tm5u tm u Dm5!N nwl nw Rw\w JwTfwuwT f@)w>fwt n  x   pNe t n tt n  @ N  pNe t n tu n  w < ouwfw7 fw w w w  wfAW @wH fT{ &n u n @55 5 5%u_h %5 N p@ p5@N m u1T{7< 5 eow(u 5& wx& L& H& D& @&z <&t 8&n 4&h 0&- -,  ĥ e BtU2ĥ$8 tĥ0+ĥ9(e- m7 ğ ċ7 ~ tm5_BhNf@  p @& q 5 @ tm"u Dm V@ =5@& q 5 2ĥ\ &ĥ  w ĥ$vREw X d%\ ` R N B w4 %4 6 fe & f q%@& p 5 @ tm0u Dm  pN nN p5 pN nN p@& q%% .q   @w eu-Vt@& m Nf nd w w 5 DD- p5 p@ nN p@ p5 @  5  p @u q 5 4   do  Br7R y e r 5 bf $e 33 %&UaN&e .d 3 do %@@E4P g   p7 ~gf Xg @JuNe@& n Tu tm   Nf $e w w  DD-0r7  y e   bf e 2N&egf Xg ?| N@& l f ju @ NF e l N4 l @ tmtu Dm 8@5= uw&@& HADCBFf@ffA w,w"|e"w"rew"h@lw"`AlewS &@t`e fw0w,uwlf@wwuwJf@wwuw( f@wwuw7 F6rw* 6r@s%s,s1sEsTs]sfsyssssssssssrrrr$  )' pbabFbpbFbbFbFbFbpbaFbFbFbFb &(); dddddd()^|lHePeTeTeJe()<>le"fLf.ffgikl.__pf0HangupQuitIllegal instructionTrace/BPT trapIOT trapEMT trapFloating exceptionKilledBus errorMemory faultBad system callSig 14Sig 15Sig 16Sig 17Sig 18Sig 19/usr/adm/sha% # /usr/adm/shb: cannot opens4vyntax error '" ;&<>()|^ "'Command line overflow Too many argsToo many characters;& <>([?*chdircdchdir: bad directoryz4v/usrchdir: "/usr" bad directoryshiftshift: no args synclogin/bin/loginlogin: cannot execute newgrp/bin/newgrpnewgrp: c߶aannot execute wait:try again : cannot open: cannot create/dev/null/etc/globglob: cannot execute /usr/bin/: not foundLnߪ߀z4vzizzz7vz߼lzddz߀z7vazsfas`-/bin/shNo shell! : too large : -- Core dumped 7v 0+(v  %ew900001s9vz zvzzH{lvls  9 9b ,&\ (&V $&P &J &D &> &8 &2 &, && & f& f$f BRfw,ufwuw| f |& wb }f@wF fww> 5 L8 L20001 _sleep _flushtt"t_spl0 _cinit"4~cinit4cpccpcdp  99L11TL20003HL14hL20005b~flushttttpatpspsL18|_getc L20_wakeup _getps L22_putps _canon"~canonbpbp1tpcatp_canonb _swapmap _rootdir _lbolt _time _tout L25L20007L27L24L28L29pL20009_putc L39L31_callout _mount _mpid _runrun _curpri _rootdev _swapdev _updlock _regloc _u &_partabL32hL33DL344L10000ZL38fL30_ttyinpu"~ttyinputpcatp _proc _inode _file _bdevsw _nblkdev _cdevsw _nchrdev _maptab#z_cfree _cfreeli _ttyt_flagsacL42L43L10001L10002L10003_signal L20011L41rL45open"~ttyopenpptpdevatpcsv L2(cret _gtty"8~gtty8L10004.L46H_ttyoutp"vL49l_ttstart"*L10007L64L62L66BL68JL73L76L78~ttyoutpvtpcolpcrtpctypeacL10005L50L51L54L55L56L57L58L61L69~L71_max L74L79_ttrstrt"~ttrstrttpatp~ttstart*addrtpcatpL85DL84L87x_timeout _ttread"~ttreadtpatpL89L91upvpv_sgtty"L3|_suword _stty"~sttyup_fuword ~sgtty_passc _ttwrite"~ttwritetpcatpL94L93*L20015L96L200fpipv_getf L5L6_wflusht"~wflushttpatp_spl13_cpass _ttystty".~ttystty.avtpvatpL99XL98T? @ A B C D E F G H I J K L