From 97ed1f156c2760f5423164261e8ae61a98fdbb40 Mon Sep 17 00:00:00 2001 From: Oliver Lehmann Date: Wed, 7 May 2008 05:02:21 +0000 Subject: [PATCH] add part 2 of the WEGA kernel --- WEGA/src/uts/sys/alloc.c | 362 +++++++++++++++++++ WEGA/src/uts/sys/debug.c | 312 +++++++++++++++++ WEGA/src/uts/sys/fio.c | 309 +++++++++++++++++ WEGA/src/uts/sys/iget.c | 341 ++++++++++++++++++ WEGA/src/uts/sys/malloc.c | 114 ++++++ WEGA/src/uts/sys/mkseg.c | 107 ++++++ WEGA/src/uts/sys/pipe.c | 198 +++++++++++ WEGA/src/uts/sys/slp.c | 441 ++++++++++++++++++++++++ WEGA/src/uts/sys/sys1.c | 707 ++++++++++++++++++++++++++++++++++++++ WEGA/src/uts/sys/text.c | 313 +++++++++++++++++ 10 files changed, 3204 insertions(+) create mode 100644 WEGA/src/uts/sys/alloc.c create mode 100644 WEGA/src/uts/sys/debug.c create mode 100644 WEGA/src/uts/sys/fio.c create mode 100644 WEGA/src/uts/sys/iget.c create mode 100644 WEGA/src/uts/sys/malloc.c create mode 100644 WEGA/src/uts/sys/mkseg.c create mode 100644 WEGA/src/uts/sys/pipe.c create mode 100644 WEGA/src/uts/sys/slp.c create mode 100644 WEGA/src/uts/sys/sys1.c create mode 100644 WEGA/src/uts/sys/text.c diff --git a/WEGA/src/uts/sys/alloc.c b/WEGA/src/uts/sys/alloc.c new file mode 100644 index 0000000..de4b3ec --- /dev/null +++ b/WEGA/src/uts/sys/alloc.c @@ -0,0 +1,362 @@ + +/****************************************************************************** +******************************************************************************* + + W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988 + KERN 3.2 Modul: alloc.c + + + Bearbeiter: + Datum: $D$ + Version: $R$ + +******************************************************************************* +******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern int Ninode; +extern int Nmount; + +/*------------------------------------------ Typdefinitionen ----------------*/ + +typedef struct fblk *FBLKP; + +/*------------------------------------------ Funktionen ---------------------*/ + +/*---------------------------------------------------------------------------*/ +/* + * alloc + * alloc weist den naechsten verfuegbaren (freien) Diskblock aus der + * Freispeicherliste des Superblockes des entsprechenden Geraetes (dev) zu. + * + * Der Superblock enthaelt bis zu NICFREE freie Bloecke. + * Die letzte Eintragung verweist auf einen weiteren Ankerblock der + * Freispeicherliste. + * "no space on dev x/y" --> wenn die Freiliste erschoepft ist +/*---------------------------------------------------------------------------*/ +struct buf * +alloc(dev) +dev_t dev; +{ + daddr_t bno; + register struct filsys *fp; + register struct buf *bp; + + fp = getfs(dev); + while(fp->s_flock) + sleep((caddr_t)&fp->s_flock, PINOD); + do { + if(fp->s_nfree <= 0) + goto nospace; + if (fp->s_nfree > NICFREE) { + prdev("Bad free count", dev); + goto nospace; + } + bno = fp->s_free[--fp->s_nfree]; + if(bno == 0) + goto nospace; + } while (badblock(fp, bno, dev)); + if(fp->s_nfree <= 0) { + fp->s_flock++; + bp = bread(dev, bno); + if ((bp->b_flags&B_ERROR) == 0) { + fp->s_nfree = ((FBLKP)(bp->b_un.b_addr))->df_nfree; + bcopy((caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, + (caddr_t)fp->s_free, sizeof(fp->s_free)); + } + brelse(bp); + fp->s_flock = 0; + wakeup((caddr_t)&fp->s_flock); + if (fp->s_nfree <=0) + goto nospace; + } + bp = getblk(dev, bno); + clrbuf(bp); + if(fp->s_tfree) /* Decrem. freelist-counter */ + fp->s_tfree--; + fp->s_fmod = 1; + return(bp); + +nospace: + fp->s_nfree = 0; + fp->s_tfree = 0; /* Total Free Blocks zero */ + prdev("no space", dev); + u.u_error = ENOSPC; + return(NULL); +} + +/*---------------------------------------------------------------------------*/ +/* + * free + * Rueckketten des Blockes (bno) in die Freispeicherliste des + * Superblockes des entsprechenden Geraetes (dev) + */ +/*---------------------------------------------------------------------------*/ +free(dev, bno) +dev_t dev; +daddr_t bno; +{ + register struct filsys *fp; + register struct buf *bp; + + fp = getfs(dev); + fp->s_fmod = 1; + while(fp->s_flock) + sleep((caddr_t)&fp->s_flock, PINOD); + if (badblock(fp, bno, dev)) + return; + if(fp->s_nfree <= 0) { + fp->s_nfree = 1; + fp->s_free[0] = 0; + } + if(fp->s_nfree >= NICFREE) { + fp->s_flock++; + bp = getblk(dev, bno); + ((FBLKP)(bp->b_un.b_addr))->df_nfree = fp->s_nfree; + bcopy((caddr_t)fp->s_free, + (caddr_t)((FBLKP)(bp->b_un.b_addr))->df_free, + sizeof(fp->s_free)); + fp->s_nfree = 0; + bwrite(bp); + fp->s_flock = 0; + wakeup((caddr_t)&fp->s_flock); + } + fp->s_free[fp->s_nfree++] = bno; + fp->s_tfree++; /* Total Free Blocks */ + fp->s_fmod = 1; +} + +/*---------------------------------------------------------------------------*/ +/* + * badblock + * Test, ob Blocknummer bn zwischen dem Ende der I-Liste und dem + * ersten nicht vorhandenen Block des Geraetes (dev) liegt + * Wird hauptsaechlich genutzt, um zu kontrollieren, ob ein "Garbage"- + * Filesystem gemounted ist + * "bad block on dev x/y" ==> Blck liegt ausserhalb zulaess. Bereich + */ +/*---------------------------------------------------------------------------*/ +badblock(fp, bn, dev) +register struct filsys *fp; +register daddr_t bn; +dev_t dev; +{ + + if (bn < fp->s_isize || bn >= fp->s_fsize) { + prdev("bad block", dev); + return(1); + } + return(0); +} + +/*---------------------------------------------------------------------------*/ +/* + * ialloc + * Weist einen unbenutzten Inode aus der Inode-Freiliste des Superblockes + * fuer das angegebene Geraet (dev) zu und stellt ihn in der Inode-Tabelle + * bereit + * Wird zur File-Kreation benoetigt + * Der Algorithmus durchlaeuft die Inodes, die im Superblock eingetragen + * sind (NICINODE Stueck). Wenn diese nicht ausreichen, so erfolgt eine + * lineare Suche durch die Inodes in den Inode-Bloecken des Geraetes, + * um NICINODE freie Inodes bereitzustellen + */ +/*---------------------------------------------------------------------------*/ +struct inode * +ialloc(dev) +dev_t dev; +{ + register struct filsys *fp; + register struct buf *bp; + register struct inode *ip; + int i; + struct dinode *dp; + ino_t ino; + daddr_t adr; + + fp = getfs(dev); + while(fp->s_ilock) + sleep((caddr_t)&fp->s_ilock, PINOD); +loop: + if(fp->s_ninode > 0) { + ino = fp->s_inode[--fp->s_ninode]; + if (ino < ROOTINO) + goto loop; + ip = iget(dev, ino); + if(ip == NULL) + return(NULL); + if(ip->i_mode == 0) { + for (i=0; ii_blks.i_p.i_a[i] = 0; + if(fp->s_tinode) /* Decr. Inode Counter */ + fp->s_tinode--; + fp->s_fmod = 1; + return(ip); + } + /* + * Inode was allocated after all. + * Look some more. + */ + iput(ip); + goto loop; + } + fp->s_ilock++; + ino = 1; + for(adr = SUPERB+1; adr < fp->s_isize; adr++) { + bp = bread(dev, adr); + if (bp->b_flags & B_ERROR) { + brelse(bp); + ino += INOPB; + continue; + } + dp = bp->b_un.b_dino; + for(i=0; idi_mode != 0) + goto cont; + for(ip = &inode[0]; ip < &inode[Ninode]; ip++) + if(dev==ip->i_dev && ino==ip->i_number) + goto cont; + fp->s_inode[fp->s_ninode++] = ino; + if(fp->s_ninode >= NICINOD) + break; + cont: + ino++; + dp++; + } + brelse(bp); + if(fp->s_ninode >= NICINOD) + break; + } + fp->s_ilock = 0; + wakeup((caddr_t)&fp->s_ilock); + if(fp->s_ninode > 0) + goto loop; + prdev("Out of inodes", dev); + u.u_error = ENOSPC; + fp->s_tinode = 0; /* Clear Inode Counter */ + return(NULL); +} + +/*---------------------------------------------------------------------------*/ +/* + * ifree + * Freigabe der spezifizierten Inode-Nr.(ino) auf dem spezifizierten Device + * Der Algorithmus speichert bis zu NICINOD Inodes im Superblock ab; folgende + * Inodes werden uebergangen + */ +/*---------------------------------------------------------------------------*/ +ifree(dev, ino) +dev_t dev; +ino_t ino; +{ + register struct filsys *fp; + + fp = getfs(dev); + fp->s_tinode++; /* Total free inodes */ + if(fp->s_ilock) + return; + if(fp->s_ninode >= NICINOD) + return; + fp->s_inode[fp->s_ninode++] = ino; + fp->s_fmod = 1; +} + +/*---------------------------------------------------------------------------*/ +/* + * getfs + * Bereitstellen eines Pointers auf den im Kern befindlichen Superblock + * fuer eine angegebene Devicenummer "dev" + * Der Alogorithmus stellt eine lineare Suche durch die Mount-Tabelle dar. + * Konsistenzcheck der sich im Kern befindenden Freispeicherliste und des + * Inode-Zaehlers + * + * "bad count on dev x/y" --> fehlerhafter Inode-Check + * Ab diesem Punkt werden die Inode- Zaehler auf Null gesetzt, was immer + * zu der Diagnose - Ausschrift "no space" fuehrt + * "panic: no fs" --> Device ist nicht gemounted. + */ +/*---------------------------------------------------------------------------*/ +struct filsys * +getfs(dev) +dev_t dev; +{ + register struct mount *mp; + register struct filsys *fp; + struct filsys *fp1; /* ??? 4 Byte */ + + for(mp = &mount[0]; mp < &mount[Nmount]; mp++) + if(mp->m_bufp != NULL && mp->m_dev == dev) { + fp = mp->m_bufp->b_un.b_filsys; + if(fp->s_nfree > NICFREE || fp->s_ninode > NICINOD) { + prdev("bad count", dev); + fp->s_nfree = 0; + fp->s_ninode = 0; + } + return(fp); + } + panic("no fs"); + return(NULL); +} + +/*---------------------------------------------------------------------------*/ +/* + * update + * update ist der interne Name von 'sync; + * -durchlaeuft Disk-Queues zur Aktualisierung zwischengepufferter I/O-Bloecke + * -durchlaeuft Inodes zum Schreiben modifizierter Inodes + * -durchlaeuft Mount-Tabelle zur Aktualiseirung modifizierter Superbloecke + */ +/*---------------------------------------------------------------------------*/ +update() +{ + register struct inode *ip; + register struct mount *mp; + register struct buf *bp; + struct buf *bp1; /* 4 Byte recomp ???? */ + struct filsys *fp; + int fcw; + + if(updlock) + return; + updlock++; + for(mp = &mount[0]; mp < &mount[Nmount]; mp++) + if(mp->m_bufp != NULL) { + fp = mp->m_bufp->b_un.b_filsys; + if(fp->s_fmod==0 || fp->s_ilock!=0 || + fp->s_flock!=0 || fp->s_ronly!=0) + continue; + bp = getblk(mp->m_dev, SUPERB); + if (bp->b_flags & B_ERROR) + continue; + fp->s_fmod = 0; + fp->s_time = time; + bcopy((caddr_t)fp, bp->b_un.b_addr, BSIZE); + bwrite(bp); + } + for(ip = &inode[0]; ip < &inode[Ninode]; ip++) { + fcw=dvi(); + if((ip->i_flag&ILOCK)==0 && ip->i_count) { + ip->i_flag |= ILOCK; + ip->i_count++; + iupdat(ip, &time, &time); + iput(ip); + } + rvi(fcw); + } + updlock = 0; + bflush(NODEV); +} diff --git a/WEGA/src/uts/sys/debug.c b/WEGA/src/uts/sys/debug.c new file mode 100644 index 0000000..7b2092d --- /dev/null +++ b/WEGA/src/uts/sys/debug.c @@ -0,0 +1,312 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define sreg state->s_reg +#define eventid state->s_eventid +#define ps state->s_ps +#define pcseg state->s_pcseg +#define pc state->s_pc + +#define NBPTS 5 +#define NBPL 16 +#define UMASK 0x3f00ffffL +#define KMASK 0x7f00ffffL +#define HMASK (unsigned char)0x0f + +extern char *zpr(); +extern mmut; +extern fubyte(), fpbyte(), fkbyte(); +extern getchar(); +int kdebug; +static char kdbstr[6]; +char hzif[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; +static unsigned char format[18]; +static unsigned int kval; +static struct { + unsigned a; + union { + unsigned int *b; + struct { + unsigned short b; + unsigned short c; + } l; + } b; + unsigned d; + unsigned e; +} breakpt[NBPTS]; + +long +gethex() +{ + char c; + long val; + + for (val = 0; ; ) + if (c = getchar()){ + if ((c >= 'A') && (c <= 'F')) + c = c - 0x37; + else if ((c >= 'a') && (c <= 'f')) + c = c - 0x57; + else if ((c >= '0') && (c <= '9')) + c -= 0x30; + else return(val); + val = (val << 4) + (long)c; + } + else return; +} + +char * +zpr(hval) +unsigned int hval; +{ + unsigned int h; + char *phzif; + + phzif = hzif; + h = hval; + kdbstr[0] = phzif[(unsigned char)((int)h >> 12 & HMASK)]; + kdbstr[1] = phzif[(unsigned char)((int)h >> 8 & HMASK)]; + kdbstr[2] = phzif[(unsigned char)((int)h >> 4 & HMASK)]; + kdbstr[3] = phzif[(unsigned char)((int)h & HMASK)]; + kdbstr[4] = 0; + return (kdbstr); +} + +debug(state) +struct state *state; +{ + caddr_t dadr; + unsigned int *kadr; + int s, v2, v1; + int ic; + int bp_cnt, event; + unsigned long acount, count; + int (*sad)(); + struct segd sdrf; + unsigned char attr; + + if (!kdebug) + return; + s = dvi(); + event = eventid & 0xff; + bp_cnt = NBPTS; + if (event == 2){ + for (bp_cnt = 0; bp_cnt < NBPTS; bp_cnt++) + if ((breakpt[bp_cnt].a) && + (hiword(breakpt[bp_cnt].b) == (pcseg & USEGW)) && + (breakpt[bp_cnt].b.l.c == (pc -2))) + break; + if (bp_cnt >= NBPTS) + printf("KDB: Unset breakpoint\n"); + else { + breakpt[bp_cnt].a = 0; + kadr = breakpt[bp_cnt].b.b; + printf("KDB: @%X Breakpoint",breakpt[bp_cnt].b.b); + getsd(mmut, hibyte(kadr), &sdrf); + attr = sdrf.sg_attr; + sdrf.sg_attr &= 0xfe; + loadsd(mmut, hibyte(kadr), &sdrf); + *kadr = breakpt[bp_cnt].d; + sdrf.sg_attr = attr; + loadsd(mmut, hibyte(kadr), &sdrf); + pc -= (unsigned) 2; + } + } + while (1){ + printf("KDB>\007"); + ic = getchar(); + switch(ic){ + case 'J': + case 'j': + { printf("ump call to @"); + sad = (int (*)())(((unsigned long)gethex()) & KMASK), (*sad)(); + } + default: + { putchar('\n'); + break; + } + case 'B': + case 'b': + { printf("reak point @"); + kadr = (unsigned int *)((gethex() & UMASK) & KMASK); + for (bp_cnt = 0; breakpt[bp_cnt].a && ++bp_cnt= NBPTS){ + printf("KDB: No more break slots\n"); + break; + } + breakpt[bp_cnt].a = 1; + breakpt[bp_cnt].b.b = kadr; + breakpt[bp_cnt].d = *kadr; + getsd(mmut, hibyte(kadr), &sdrf); + attr = sdrf.sg_attr; + sdrf.sg_attr &= ~RD_AT; + loadsd(mmut, hibyte(kadr), &sdrf); + if (!(skbyte(kadr, 0x7f)) && /* 7f02 break */ + (skbyte((((char *)kadr)+1), 0x02))){ + printf(" FAULT "); + break; + } + sdrf.sg_attr = attr; + loadsd(mmut, hibyte(kadr), &sdrf); + break; + } /* von break - Routine */ + case 'U': + case 'u': + { printf("ser space d"); + sad = fubyte; + goto Mdisplay; + } /* von user - Routine */ + case 'P': + case 'p': + { printf("hysical space d"); + sad = fpbyte; + goto Mdisplay; + } + case 'D': + case 'd': + { sad = fkbyte; +Mdisplay: printf("isplay @"); + dadr = (caddr_t)(gethex() & KMASK); + printf("for "); + count = gethex(); + printf("words\n"); + v1 = 0; + count = (((unsigned long)(count + 7L))>>3)<<3; + for (acount = 0; acount < count; acount++){ + if (!(v1)){ + if(acount) + printf("\n"); + printf("%s", zpr(hiword(dadr))); + printf("%s: ", zpr(loword(dadr))); + } + if ((*sad)(dadr, &format[v1])){ + printf(" FAULT "); + break; + } + kval = format[v1]<<8; + if ((format[v1] < ' ') || + (format[v1] > '~')) + format[v1] = ' '; + v1++; + dadr++; + if ((*sad)(dadr, &format[v1])){ + printf(" FAULT "); + break; + } + kval |= format[v1]; + if ((format[v1] < ' ') || + (format[v1] > '~')) + format[v1] = ' '; + v1++; + dadr++; + printf("%s ", zpr(kval)); + if (!(v1 % 0x10)){ + printf(" |%s|", format); + v1 = 0; + } + } + break; + } + case 'M': + case 'm': + { printf("odify "); + switch((getchar())){ + case 'R': + case 'r': + { printf("egister "); + count = gethex(); + printf("(%s) with ", (char *)zpr(sreg[count])); + v2 = ((unsigned int)gethex()); + printf("OK "); + switch(getchar()){ + case 'Y': + case 'y': + sreg[count] = v2; + } + break; + } + case 'M': + case 'm': + { printf("emory @"); + kadr = (unsigned int *)(gethex() & KMASK); + printf("(%s) with ", zpr(*kadr)); + v2 = ((unsigned int)gethex()); + printf("OK "); + switch(getchar()){ + { case 'Y': + case 'y': + getsd(mmut, hibyte(kadr), &sdrf); + attr = sdrf.sg_attr; + sdrf.sg_attr &= ~RD_AT; + loadsd(mmut, hibyte(kadr), &sdrf); + if ((!(skbyte(kadr, hibyte(v2)))) && + (skbyte(((char *)kadr+1), hibyte(v2)))){ + printf(" FAULT "); + break; + } + sdrf.sg_attr = attr; + loadsd(mmut, hibyte(kadr), &sdrf); + break; + } + } + break; + } /* von memory - Routine */ + } + break; + } /* von modify - Routine */ + case 'R': + case 'r': + { printf("egisters\n"); + for (acount = 0; acount < 16; acount++){ + if (!(acount & 7)) + putchar('\n'); + printf("r%d:%s ", zpr(sreg[acount])); + } + printf("\nfcw=%s ", zpr(ps)); + printf("pcseg=%s ", zpr(pcseg)); + printf("pcoff=%s", zpr(pc)); + break; + } /* von register - Routine */ + case 'S': + case 's': + { printf("ingle step\n"); + ps |= TBIT; + rvi(s); + return(1); + } /* von step - Routine */ + case 'T': + case 't': + { printf("ape crash dump\n"); + printf("writable tape loaded in drive 0? "); + switch(getchar()){ + { case 'Y': + case 'y': + dump(state); + } + } + break; + } + case 'C': + case 'c': + { printf("ontinue\n"); + rvi(s); + return(1); + } + case 'E': + case 'e': + { printf("xit\n"); + rvi(s); + return(1); + } + } /* von switch */ + } /* von while (1) */ +} diff --git a/WEGA/src/uts/sys/fio.c b/WEGA/src/uts/sys/fio.c new file mode 100644 index 0000000..24459b0 --- /dev/null +++ b/WEGA/src/uts/sys/fio.c @@ -0,0 +1,309 @@ +/****************************************************************************** +******************************************************************************* + + W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988 + KERN 3.2 Modul: fio.c + + + Bearbeiter: + Datum: $D$ + Version: $R$ + +******************************************************************************* +******************************************************************************/ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern int Nfile; +extern int Nmount; + +/*------------------------------------------ Funktionen ---------------------*/ + +/*---------------------------------------------------------------------------*/ +/* + * getf + * Konvertiert einen vom Nutzer gelieferten Dateidescriptor in der + * Nutzer-Dateidescriptortabelle (u.u_ofile) in einen Zeiger auf eine + * file-Struktur in der Dateitabelle (file[]) + */ +/*---------------------------------------------------------------------------*/ +struct file * +getf(f) +register int f; +{ + register struct file *fp; + + if(0 <= f && f < NOFILE) { + fp = u.u_ofile[f]; + if(fp != NULL) + return(fp); + } + u.u_error = EBADF; + return(NULL); +} + +/*---------------------------------------------------------------------------*/ +/* + * closef + * - interne Form von close + * - dekrementiert den Datei-Referenzzaehler der file-Struktur + * - sichert, dass das pipe-Protokoll nicht verstopft ist + * + * - dekrementiert den Inode-Referenzszaehler, um die Freigabe der + * zugehoerigen Filestruktur zu verfolgen + * - ruft den Device-Handler beim letzten close auf + * Beachte: Der Device-Handler wird bei jedem Open aber nur beim letzten + * Close aufgerufen + */ +/*---------------------------------------------------------------------------*/ +closef(fp) +register struct file *fp; +{ + register struct inode *ip; + struct mount *mp; + int flag, fmt; + dev_t dev; + int (*cfunc)(); + + if (fp == NULL) + return; + unlock(fp->f_inode); + if ((unsigned)fp->f_count > 1) { + fp->f_count--; + return; + } + ip = fp->f_inode; + plock(ip); + flag = fp->f_flag; + dev = (dev_t)ip->i_rdev; + fmt = ip->i_mode&IFMT; + fp->f_count = 0; + switch(fmt) { + + case IFCHR: + cfunc = cdevsw[major(dev)].d_close; + break; + + case IFBLK: + cfunc = bdevsw[major(dev)].d_close; + break; + + case IFIFO: + closep(ip, flag); + + default: + iput(ip); + return; + } + for (fp = file; fp < &file[Nfile]; fp++) { + register struct inode *tip; + + if (fp->f_count) { + tip = fp->f_inode; + if (tip->i_rdev == dev && + (tip->i_mode&IFMT) == fmt) + goto out; + } + } + if (fmt == IFBLK) { + for (mp = mount; mp < &mount[Nmount]; mp++) + if (mp->m_flags == MINUSE && mp->m_dev == dev) + goto out; + bflush(dev); + (*cfunc)(dev, flag); + binval(dev); + } else { + prele(ip); + (*cfunc)(dev, flag); + } +out: + iput(ip); +} + +/*---------------------------------------------------------------------------*/ +/* openi + * Ausfuehrung OPEN-Aktion + * wird aufgerufen, um dem Handler von special files die Moeglichkeit zur + * Initialisierung und Validisierung zu geben, bevor aktuelle I/O folgen + */ +/*---------------------------------------------------------------------------*/ +openi(ip, flag) +register struct inode *ip; +{ + dev_t dev; + register unsigned int maj; + + dev = (dev_t)ip->i_rdev; + maj = major(dev); + switch(ip->i_mode&IFMT) { + + case IFCHR: + if (maj >= nchrdev) + goto bad; + if (u.u_ttyp == NULL) + u.u_ttyd = dev; + (*cdevsw[maj].d_open)(dev, flag); + break; + + case IFBLK: + if (maj >= nblkdev) + goto bad; + (*bdevsw[maj].d_open)(dev, flag); + break; + + case IFIFO: + openp(ip, flag); + break; + } + return; + +bad: + u.u_error = ENXIO; +} + +/*-----------------------------------------------------------*/ +/* access + * Kontrolle Zugriffsrechte auf einen Inode Pointer + * Mode ist READ, WRITE oder EXEC + * WRITE: Read-only Status des Files wird gecheckt; + * reine Textsegmente koennen nicht geschrieben werden + * Der Mode wird verschoben, um die owner/group/other-Felder + * zu selektieren + * Der Superuser hat alle Zugriffsrechte + */ +/*-----------------------------------------------------------*/ +access(ip, mode) +register struct inode *ip; +{ + register m; + + m = mode; + if (m == IWRITE) { + if (getfs(ip->i_dev)->s_ronly) { + u.u_error = EROFS; + return(1); + } + if (ip->i_flag&ITEXT) + xrele(ip); + if (ip->i_flag & ITEXT) { + u.u_error = ETXTBSY; + return(1); + } + } + if (u.u_uid == 0) + return(0); + if (u.u_uid != ip->i_uid) { + m >>= 3; + if (u.u_gid != ip->i_gid) + m >>= 3; + } + if ((ip->i_mode&m) != 0) + return(0); + + u.u_error = EACCES; + return(1); +} + +/*-------------------------------------------------------------------*/ +/* owner + * Absteigen Pfadnamen und Test, ob die resultierende Inode dem + * aktuellen Nutzer gehoert. Wenn nicht, Test auf Superuser + * Ist Zugriff erlaubt, Rueckgabee des Inode-Pointers + */ +/*-------------------------------------------------------------------*/ +struct inode * +owner() +{ + register struct inode *ip; + + ip = namei(uchar, 0); + if (ip == NULL) + return(NULL); + if (u.u_uid == ip->i_uid ) + return(ip); + if( suser()) + return(ip); + iput(ip); + return(NULL); +} + +/*---------------------------------------------------------*/ +/* + * Test, ob der aktuelle Nutzer der Superuser ist + */ +/*---------------------------------------------------------*/ +suser() +{ + + if (u.u_uid == 0) { + u.u_acflag |= ASU; + return(1); + } + u.u_error = EPERM; + return(0); +} + +/*----------------------------------------------*/ +/* + * Zuweisung eines User Filedescriptors + */ +/*----------------------------------------------*/ +ufalloc(i) +register i; +{ + + for(; i */ + /* BYTE-KOMPATIBILITAET*/ + register i; + + i = ufalloc(0); + if (i < 0) + return(NULL); + for(fp = &file[0]; fp < &file[Nfile]; fp++) + if (fp->f_count == 0) { + u.u_ofile[i] = fp; + fp->f_count++; + fp->f_offset = 0; + return(fp); + } + printf("no file\n"); + /*syserr.fileovf++;*/ + u.u_error = ENFILE; + return(NULL); +} diff --git a/WEGA/src/uts/sys/iget.c b/WEGA/src/uts/sys/iget.c new file mode 100644 index 0000000..40a2ebb --- /dev/null +++ b/WEGA/src/uts/sys/iget.c @@ -0,0 +1,341 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern int Ninode; +extern int Nmount; + +char igetwstr[]="@[$]iget.c Rev : 4.1 08/27/83 11:54:46"; + +struct inode *ihash[INOHSZ] = 0 ; +struct inode *ifreelist; + +ihinit() +{ + register i; + register struct inode *ip; + + ifreelist = inode; + for(ip=inode; ip < &inode[Ninode-1]; ip++) + ip->i_link = (struct inode *) ip+1; + ip->i_link = (struct inode *) 0; + for(i=0;i< INOHSZ;i++) + ihash[i] = (struct inode *) 0; +} + +struct inode * +ifind(idev,inum) +register dev_t idev; +register ino_t inum; +{ + register struct inode *ip; + + ip=ihash[INOHASH(idev,inum)]; + while(ip !=(struct inode *)0) { + if(inum == ip->i_number && idev == ip->i_dev) + return(ip); + ip=ip->i_link; + } + return((struct inode *)0); +} + +struct inode * +iget(dev, ino) +register dev_t dev; +register ino_t ino; +{ + register struct inode *ip; + register struct mount *mp; + register h_index; + register struct buf *bp; + register struct dinode *dp; + int i; + + sysinfo.iget++; +loop: + h_index = INOHASH(dev, ino); + for(ip=ihash[h_index];ip!=(struct inode *) 0;ip=ip->i_link) { + if(ino == ip->i_number && dev == ip->i_dev) { + while((ip->i_flag & ILOCK) != 0) { + ip->i_flag |= IWANT; + sleep((caddr_t)ip, PINOD); + if(ino == ip->i_number && dev == ip->i_dev) + continue; + goto loop; + } + if((ip->i_flag & IMOUNT) !=0) { + for(mp = &mount[0]; mp < &mount[Nmount]; mp++) + if(mp->m_inodp == ip) { + dev = mp->m_dev; + ino = ROOTINO; + goto loop; + } + panic("no imt"); + } + ip->i_count++; + ip->i_flag |= ILOCK; + return(ip); + } + } + + if(ifreelist == NULL) { + printf("Inode table overflow\n"); + u.u_error = ENFILE; + return(NULL); + } + ip=ifreelist; + ifreelist=ip->i_link; + ip->i_link=ihash[h_index]; + ihash[h_index]=ip; + ip->i_dev = dev; + ip->i_number = ino; + ip->i_flag = ILOCK; + ip->i_count++; + ip->i_blks.i_l = (daddr_t) 0; + bp = bread(dev, itod(ino)); + + if((bp->b_flags&B_ERROR) != 0) { + brelse(bp); + iput(ip); + return(NULL); + } + dp = bp->b_un.b_dino; + dp += itoo(ino); + iexpand(ip, dp); + brelse(bp); + return(ip); +} + +iexpand(ip, dp) +register struct inode *ip; +register struct dinode *dp; +{ + ip->i_mode = dp->di_mode; + ip->i_nlink = dp->di_nlink; + ip->i_uid = dp->di_uid; + ip->i_gid = dp->di_gid; + ip->i_size = dp->di_size; + l3tol((char *) ip->i_blks.i_p.i_a, (char *)dp->di_addr, NADDR); + ip->i_locklist = 0; +} + +iput(ip) +register struct inode *ip; +{ + register struct inode *ip1; + register h_index, i_unbenutzt; + long unbenutzt; + + if(ip->i_count == 1) { + ip->i_flag |= ILOCK; + if(ip->i_nlink <= 0) { + itrunc(ip); + ip->i_mode = 0; + ip->i_flag |= IUPD|ICHG; + ifree(ip->i_dev, ip->i_number); + } + iupdat(ip, &time, &time); + prele(ip); + h_index = INOHASH(ip->i_dev, ip->i_number); + if(ip == ihash[h_index]) + ihash[h_index] = ip->i_link; + else { + ip1 = ihash[h_index]; + for(;ip1;ip1=ip1->i_link) + if(ip == ip1->i_link) { + ip1->i_link = ip->i_link; + goto m1; + } + panic("iput"); + } +m1: + ip->i_link = ifreelist; + ifreelist = ip; + ip ->i_flag= NULL; + ip->i_number = 0; + } else + prele(ip); + ip->i_count--; +} + +iupdat(ip, ta, tm) +register struct inode *ip; +time_t *ta, *tm; +{ + register struct buf *bp; + register struct dinode *dp; + char *di_addr; + char *i_f; + unsigned i; + + if((ip->i_flag&(IUPD|IACC|ICHG)) == 0) + return; + if(getfs(ip->i_dev)->s_ronly) { + if(ip->i_flag & (IUPD | ICHG)) + u.u_error = EROFS; + ip->i_flag &= ~(IUPD | ICHG | IACC); + return; + } + bp = bread(ip->i_dev, itod(ip->i_number)); + if (bp->b_flags & B_ERROR) { + brelse(bp); + return; + } + dp = bp->b_un.b_dino; + dp += itoo(ip->i_number); + dp->di_mode = ip->i_mode; + dp->di_nlink = ip->i_nlink; + dp->di_uid = ip->i_uid; + dp->di_gid = ip->i_gid; + dp->di_size = ip->i_size; + + if((ip->i_mode & IFMT) == IFIFO) { + di_addr = (char *) dp->di_addr; + i_f = (char *) ip->i_faddr; + i=0; + do { + *di_addr++ = *i_f++; + if( * i_f++) + printf("iaddress > 2^24\n"); + *di_addr++ = *i_f++; + *di_addr++ = *i_f++; + }while(++i < NFADDR); + + for(;i<13;i++) { + *di_addr++ = 0; + *di_addr++ = 0; + *di_addr++ = 0; + } + } else + ltol3((char *)dp->di_addr, (char *)ip->i_addr, NADDR); + if(ip->i_flag&IACC) + dp->di_atime = *ta; + if(ip->i_flag&IUPD) + dp->di_mtime = *tm; + if(ip->i_flag&ICHG) + dp->di_ctime = time; + ip->i_flag &= ~(IUPD|IACC|ICHG); + bdwrite(bp); +} + +itrunc(ip) +register struct inode *ip; +{ + register i; + register dev_t dev; + register daddr_t bn; + + i = ip->i_mode & IFMT; + if (i!=IFREG && i!=IFDIR) + return; + dev = ip->i_dev; + for(i=NADDR-1; i>=0; i--) { + bn = ip->i_addr[i]; + if(bn == (daddr_t)0) + continue; + ip->i_addr[i] = (daddr_t)0; + switch(i) { + + default: + free(dev, bn); + break; + + case NADDR-3: + tloop(dev, bn, 0, 0); + break; + + case NADDR-2: + tloop(dev, bn, 1, 0); + break; + + case NADDR-1: + tloop(dev, bn, 1, 1); + } + } + ip->i_size = 0; + ip->i_flag |= ICHG|IUPD; +} + +tloop(dev, bn, f1, f2) +dev_t dev; +daddr_t bn; +{ + register i; + register struct buf *bp; + register daddr_t *bap; + int unbenutzt, u2, u3, u4, u5; + daddr_t nb; + + bp = NULL; + for(i=NINDIR-1; i>=0; i--) { + if(bp == NULL) { + bp = bread(dev, bn); + if (bp->b_flags & B_ERROR) { + brelse(bp); + return; + } + bap = bp->b_un.b_daddr; + } + nb = bap[i]; + if(nb == (daddr_t)0) + continue; + if(f1) { + brelse(bp); + bp = NULL; + tloop(dev, nb, f2, 0); + } else + free(dev, nb); + } + if(bp != NULL) + brelse(bp); + free(dev, bn); +} + +struct inode * +maknode(mode) +{ + register struct inode *ip; + struct inode *ip1; + + ip = ialloc(u.u_pdir->i_dev); + if(ip == NULL) { + iput(u.u_pdir); + return(NULL); + } + ip->i_flag |= IACC|IUPD|ICHG; + if((mode&IFMT) == 0) + mode |= IFREG; + ip->i_mode = mode & ~u.u_cmask; + ip->i_nlink = 1; + ip->i_uid = u.u_uid; + ip->i_gid = u.u_gid; + wdir(ip); + return(ip); +} + +wdir(ip) +struct inode *ip; +{ + + if (u.u_pdir->i_nlink <= 0) { + u.u_error = ENOTDIR; + } else { + u.u_dent.d_ino = ip->i_number; + bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ); + u.u_count = sizeof(struct direct); + u.u_segflg = 1; + u.u_base.l= (caddr_t) &u.u_dent; + writei(u.u_pdir); + u.u_segflg = 0; + } + iput(u.u_pdir); +} diff --git a/WEGA/src/uts/sys/malloc.c b/WEGA/src/uts/sys/malloc.c new file mode 100644 index 0000000..782bb59 --- /dev/null +++ b/WEGA/src/uts/sys/malloc.c @@ -0,0 +1,114 @@ + +/****************************************************************************** +******************************************************************************* + + W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988 + KERN 3.2 Modul: malloc.c + + Bearbeiter: + Datum: $D$ + Version: $R$ + +******************************************************************************* +******************************************************************************/ + + + +#include "sys/param.h" +#include "sys/sysinfo.h" +#include "sys/systm.h" +#include "sys/map.h" + + +/*--------------------------------------------- Funktionen ------------------*/ + +/* + * Die Module malloc und mfree dienen der Speicherverwaltung in den + * beiden Speichern coremap und swapmap + */ + +/*---------------------------------------------------------------------------*/ + + + +/*---------------------------------------------------------------------------*/ +/* + * malloc + * Bereitstellung von freiem Speicher aus der core- bzw. swapmap + * Zuweisung von 'size' Einheiten + * Rueckgabe Basis des zugewiesenen Bereiches + * In der map werden die Adressen erhoeht, die Liste wird durch eine + * 0-Laenge beendet + * Coremap-Unit = 64 Byte; Swapmap-Unit = 512 Byte + * Algorithmus ist first-fit. + */ +/*---------------------------------------------------------------------------*/ +malloc(mp, size) +struct map *mp; +{ + register unsigned int a; + register struct map *bp; + + for (bp=mp; bp->m_size; bp++) { + if (bp->m_size >= size) { + a = bp->m_addr; + bp->m_addr += size; + if ((bp->m_size -= size) == 0) { + do { + bp++; + (bp-1)->m_addr = bp->m_addr; + } while ((bp-1)->m_size = bp->m_size); + } + return(a); + } + } + return(0); +} + +/*---------------------------------------------------------------------------*/ +/* + * mfree + * Freigabe des vorher zugewiesenen Speichers a mit der Laenge von size + * Einheiten an die spezifizierte Map + * 'a' wird in die Map einsortiert und ein oder beide Enden kombiniert, + * wenn moeglich + */ +/*---------------------------------------------------------------------------*/ +mfree(mp, size, a) +struct map *mp; +register int a; +{ + register struct map *bp; + register unsigned int t; + + if ((bp = mp)==coremap && runin) { + runin = 0; + wakeup((caddr_t)&runin); + } + for (; bp->m_addr<=a && bp->m_size!=0; bp++); + if (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 += bp->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->m_addr; + bp->m_addr = a; + a = t; + t = bp->m_size; + bp->m_size = size; + bp++; + } while (size = t); + } + } +} diff --git a/WEGA/src/uts/sys/mkseg.c b/WEGA/src/uts/sys/mkseg.c new file mode 100644 index 0000000..bd65741 --- /dev/null +++ b/WEGA/src/uts/sys/mkseg.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char mksegwstr[]="@@[$]mkseg.c@i@iRev : 4.1@i08/27/83 11:56:13"; + +mkseg() +{ + register unsigned segno; + register unsigned size; + register struct proc *pp; + struct a { + unsigned segno; + unsigned size; + } + *uap; + char i, j; + + pp = u.u_procp; + segno = ((struct a *)u.u_ap)->segno & 0x7f; + size = ((struct a *)u.u_ap)->size; + if (!segno){ +loop: + i = 4; + for (j=0; j STAK){ + u.u_error = ENOSEG; + return; + } + else + goto loop; + segno = i; + } + else + for (j=0; j umemory){ + u.u_error = ENOMEM; + return; + } + u.u_segno[j] = segno; + u.u_nsegs++; + u.u_dsize += size; + sestabur(size, j, j, 0); + if (u.u_error) + return; + shufflecore(pp->p_size+size, pp->p_size, u.u_ssize); + u.u_r.r_val1 = segno<<8; + u.u_r.r_val2 = 0; +} + +/* sgstat is defined here; it is directly never used */ + +#define NSEGS 10 +sgstat() +{ + cnt_t i,j; + struct { + unsigned segno; + unsigned limit; + } segstat[10]; + register paddr_t *saddr; + + saddr = (paddr_t *)u.u_ap; + j = 0; + if (u.u_sep) + for (i=0; ; ){ + if (i< u.u_nsegs){ + if (u.u_segno[i] & 0x80){ + hibyte(segstat[j].segno) = u.u_segno[i] & 0x7f; + if (u.u_segmts[i].sg_limit == 0xff) + segstat[j].limit = 0xfffe; + else + segstat[j].limit = ((unsigned int)(u.u_segmts[i].sg_limit)+1)<<8; + } + } + if (j++ != NSEGS) + i++; + else + break; + } + else { + hibyte(segstat[0].segno) = u.u_tseg; + segstat[0].limit = u.u_toff<<8; + j++; + } + for(i=j; i +#include +#include +#include +#include +#include +#include +#include +#include + +/*------------------------------------------ Funktionen ---------------------*/ + +/*---------------------------------------------------------------------------*/ +/* + * pipe + * Der Pipe-Systemaufruf. + * Zuweisen eines Inodes des Wurzelgeraetes (root dev). + * Zuweisen von zwei File-Strukturen und Verbinden + * dieser Teile durch Setzen entsprechender Flags. + */ +/*---------------------------------------------------------------------------*/ +pipe() +{ + register struct inode *ip; + register struct file *rf, *wf; + int r; + + ip = ialloc(pipedev); + if(ip == NULL) + return; + rf = falloc(); + if(rf == NULL) { + iput(ip); + return; + } + r = u.u_r.r_val1; + wf = falloc(); + if(wf == NULL) { + rf->f_count = 0; + u.u_ofile[r] = NULL; + iput(ip); + return; + } + u.u_r.r_val2 = u.u_r.r_val1; + u.u_r.r_val1 = r; + wf->f_flag = FWRITE; + wf->f_inode = ip; + rf->f_flag = FREAD; + rf->f_inode = ip; + ip->i_count = 2; + ip->i_mode = IFIFO; + ip->i_flag = IACC|IUPD|ICHG; + ip->i_frcnt=1; + ip->i_fwcnt=1; + iupdat(ip,&time,&time); +} + + +/*----------------------------------------------------------*/ +/* + * openp + * Eroeffnen einer Pipe + * Kontrolle Lese-/Schreibgroesse; streichen, wenn notwendig + */ +/*----------------------------------------------------------*/ + +openp(ip, mode) +register struct inode *ip; +register mode; +{ + if (mode&FREAD) { + if (ip->i_frcnt++ == 0) + wakeup((caddr_t)&ip->i_frcnt); + } + if (mode&FWRITE) { + if (mode&FNDELAY && ip->i_frcnt == 0) { + u.u_error = ENXIO; + return; + } + if (ip->i_fwcnt++ == 0) + wakeup((caddr_t)&ip->i_fwcnt); + } + if (mode&FREAD) { + while (ip->i_fwcnt == 0) { + if (mode&FNDELAY || ip->i_size) + return; + sleep(&ip->i_fwcnt, PPIPE); + } + } + if (mode&FWRITE) { + while (ip->i_frcnt == 0) + sleep(&ip->i_frcnt, PPIPE); + } +} + +/*-------------------------------------------------*/ +/* + * closep + * Schliessen einer Pipe + * Update counts and cleanup + */ +/*------------------------------------------------*/ + +closep(ip, mode) +register struct inode *ip; +register mode; +{ + register i; + daddr_t bn; + + if (mode&FREAD) { + if ((--ip->i_frcnt == 0) && (ip->i_fflag&IFIW)) { + ip->i_fflag &= ~IFIW; + wakeup((caddr_t)&ip->i_fwcnt); + } + } + if (mode&FWRITE) { + if ((--ip->i_fwcnt == 0) && (ip->i_fflag&IFIR)) { + ip->i_fflag &= ~IFIR; + wakeup((caddr_t)&ip->i_frcnt); + } + } + if ((ip->i_frcnt == 0) && (ip->i_fwcnt == 0)) { + for (i=NFADDR-1; i>=0; i--) { + bn = ip->i_faddr[i]; + if (bn == (daddr_t)0) + continue; + ip->i_faddr[i] = (daddr_t)0; + free(ip->i_dev, bn); + } + ip->i_size = 0; + ip->i_frptr = 0; + ip->i_fwptr = 0; + ip->i_flag |= IUPD|ICHG; + } +} +/*---------------------------------------------------------------------------*/ +/* + * plock + * Blockieren eines Pipekanals. + * Wenn er bereits blockiert ist, so wird das WANT-Flag gesetzt + * und auf die Freigabe gewartet. + */ +/*---------------------------------------------------------------------------*/ +plock(ip) +register struct inode *ip; +{ +int fcw; + + fcw=dvi(); + while(ip->i_flag&ILOCK) { + ip->i_flag |= IWANT; + sleep((caddr_t)ip, PINOD); + } + ip->i_flag |= ILOCK; + rvi(fcw); +} + +/*---------------------------------------------------------------------------*/ +/* + * prele + * Aufhebung der Blockierung eines Inodes. + * Wenn das WANT-Flag gesetzt ist, + * so Aufwecken des wartenden Prozesses. + * Diese Routine wird auch allgemein benutzt, + * um die Blockierung eines Inodes aufzuheben. + */ +/*---------------------------------------------------------------------------*/ +prele(ip) +register struct inode *ip; +{ +int fcw; + + fcw=dvi(); + ip->i_flag &= ~ILOCK; + if(ip->i_flag&IWANT) { + ip->i_flag &= ~IWANT; + wakeup((caddr_t)ip); + } + rvi(fcw); +} diff --git a/WEGA/src/uts/sys/slp.c b/WEGA/src/uts/sys/slp.c new file mode 100644 index 0000000..c1b338a --- /dev/null +++ b/WEGA/src/uts/sys/slp.c @@ -0,0 +1,441 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SQSIZE 0100 +struct proc *slpque[SQSIZE+1]; + +#define HASH(x) (( (int) x >> 5) & (SQSIZE-1)) + +extern unsigned Nproc; + +sleep(chan, pri) +caddr_t chan; +int pri; +{ + register struct proc *rp; + register s, h; + register sig; + + rp = u.u_procp; + s = dvi(); + if (chan==0) + panic("zero wchan"); + rp->p_stat = SSLEEP; + rp->p_wchan = chan; + rp->p_pri = pri; + h = 0x40; + else + h = HASH(chan); + rp->p_link = slpque[h]; + slpque[h] = rp; + if(pri > PZERO) { + if(rp->p_sig != 0 && (sig=issig()) != 0) + if((sig & ~(SIGHUP|SIGILL)) || !(rp->p_flag&STRC)) { + rp->p_wchan = 0; + rp->p_stat = SRUN; + slpque[h] = rp->p_link; + evi(); + goto psig; + } + evi(); + if(runin != 0) { + runin = 0; + wakeup((caddr_t)&runin); + } + swtch(); + if(rp->p_sig !=0 && (sig=issig()) != 0) + if((sig & ~(SIGHUP|SIGILL)) || !(rp->p_flag & STRC)) + goto psig; + } else { + evi(); + swtch(); + } + rvi(s); + return; + +psig: + resume(u.u_procp->p_addr, u.u_qsav); +} + +wakeup(chan) +register caddr_t chan; +{ + register struct proc *p, *q; + register i; + register int s; + struct proc *sp; + + s = dvi(); + if (chan == &runout) + i = 0x40; + else + i = HASH(chan); +restrt: + p = slpque[i]; + q = NULL; + while(p != NULL) { + if(p->p_wchan==chan && p->p_stat!=SZOMB) { + if (q == NULL) + sp = slpque[i] = p->p_link; + else + sp = q->p_link = p->p_link; + p->p_wchan = 0; + setrun(p); + p = sp; + continue; + } + q = p; + p = p->p_link; + } + rvi(s); +} + +setrq(p) + struct proc *p; +{ + register struct proc *q; + register s; + + s=dvi(); + for(q=runq; q!=NULL; q=q->p_link) + if(q == p) { + prstate(u.u_state); + panic("proc on q\n"); + goto out; + } + p->p_link = runq; + runq = p; +out: + rvi(s); +} + +setrun(p) +register struct proc *p; +{ + register caddr_t w; + + if (p->p_stat==0 || p->p_stat==SZOMB) { + prstate(u.u_state); + panic("Running a dead proc"); + } + if (w = p->p_wchan) { + wakeup(w); + return; + } + p->p_stat = SRUN; + setrq(p); + if(p->p_pri < curpri) + runrun++; + if(runout != 0 && (p->p_flag&SLOAD) == 0) { + runout = 0; + wakeup((caddr_t)&runout); + } +} + +setpri(pp) +register struct proc *pp; +{ + register p; + + p = (pp->p_cpu & 0377)/16; + p += PUSER + pp->p_nice - NZERO; + if(p > 127) + p = 127; + if(p < curpri) + runrun++; + pp->p_pri = p; + return(p); +} + +sched() +{ + register struct proc *rp, *p; + register outage, inage; + register maxsize; + + +loop: + dvi(); + outage = -20000; + for (rp = &proc[0]; rp < &proc[Nproc]; rp++) + if (rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && + rp->p_time - (rp->p_nice-NZERO)*8 > outage) { + p = rp; + outage = rp->p_time - (rp->p_nice-NZERO)*8; + } + if (outage == -20000) { + runout++; + sleep((caddr_t)&runout, PSWP); + goto loop; + } + evi(); + + if (swapin(p)) + goto loop; + + + dvi(); + p = NULL; + maxsize = -1; + inage = -1; + for (rp = &proc[0]; rp < &proc[Nproc]; rp++) { + if (rp->p_stat==SZOMB + || (rp->p_flag&(SSYS|SLOCK|SULOCK|SLOAD))!=SLOAD) + continue; + if (rp->p_textp && rp->p_textp->x_flag&XLOCK) + continue; + if (rp->p_stat==SSLEEP&&rp->p_pri>=PZERO || rp->p_stat==SSTOP) { + if (maxsize < rp->p_size) { + p = rp; + maxsize = rp->p_size; + } + } else if (maxsize<0 && (rp->p_stat==SRUN||rp->p_stat==SSLEEP)) { + if (rp->p_time+rp->p_nice-NZERO > inage) { + p = rp; + inage = rp->p_time+rp->p_nice-NZERO; + } + } + } + evi(); + if (maxsize>=0 || (outage>=3 && inage>=2)) { + p->p_flag &= ~SLOAD; + xswap(p, 1, 0); + goto loop; + } + dvi(); + runin++; + sleep((caddr_t)&runin, PSWP); + goto loop; +} + +swapin(p) +register struct proc *p; +{ + register struct text *xp; + register int a; + register int x; + + if ((a = malloc(coremap, p->p_size)) == NULL) + return(0); + if (xp = p->p_textp) { + xlock(xp); + if (xp->x_ccount==0) { + if ((x = malloc(coremap, xp->x_size)) == NULL) { + xunlock(xp); + mfree(coremap, p->p_size, a); + return(0); + } + xp->x_caddr = x; + if ((xp->x_flag&XLOAD)==0) + swap(swapdev,xp->x_daddr,x,xp->x_size,B_READ); + } + xp->x_ccount++; + xunlock(xp); + } + swap(swapdev, p->p_addr, a, p->p_size, B_READ); + mfree(swapmap, ctod(p->p_size), p->p_addr); + p->p_addr = a; + p->p_flag |= SLOAD; + p->p_time = 0; + return(1); +} + +qswtch() +{ + + sysinfo.qswitch++; + setrq(u.u_procp); + swtch(); +} + +swtch() +{ + register n; + register struct proc *p, *q; + int undef1, undef2, undef3; + struct proc *pp, *pq; + + if (u.u_procp != &proc[0]) { + if (save(u.u_rsav)) { + sysinfo.pswitch++; + setscr(); + if(u.u_segmented) { + invsdrs(); + segureg(); + return; + } + sureg(); + return; + } + resume(proc[0].p_addr, u.u_qsav); + } + if (save(u.u_qsav)==0 && save(u.u_rsav)) { + setscr(); + return; + } +loop: + dvi(); + runrun = 0; + pp = NULL; + q = NULL; + n = 128; + for(p=runq; p!=NULL; p=p->p_link) { + if((p->p_stat==SRUN) && (p->p_flag&SLOAD)) { + if(p->p_pri <= n) { + pp = p; + pq = q; + n = p->p_pri; + } + } + q = p; + } + p = pp; + if(p == NULL) { + sysinfo.idle++; + idle(); + goto loop; + } + q = pq; + if(q == NULL) + runq = p->p_link; + else + q->p_link = p->p_link; + curpri = n; + evi(); + n = p->p_flag&SSWAP; + p->p_flag &= ~SSWAP; + resume(p->p_addr, n? u.u_ssav: u.u_rsav); +} + +newproc() +{ + long undef; + struct proc *rpp, *rip; + int n; + register a1, a2; + register struct proc *p, *up; + + p = NULL; +retry: + mpid++; + if(mpid >= 30000) { + mpid = 0; + goto retry; + } + for(rpp = &proc[0]; rpp < &proc[Nproc]; rpp++) { + if(rpp->p_stat == NULL && p==NULL) + p = rpp; + if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) + goto retry; + } + if ((rpp = p)==NULL) + panic("no procs"); + + rip = u.u_procp; + up =rip; + rpp->p_stat = SRUN; + rpp->p_clktim = 0; + rpp->p_flag = SLOAD; + rpp->p_uid = rip->p_uid; + rpp->p_pgrp = rip->p_pgrp; + rpp->p_nice = rip->p_nice; + rpp->p_textp = rip->p_textp; + rpp->p_pid = mpid; + rpp->p_ppid = rip->p_pid; + rpp->p_time = 0; + rpp->p_cpu = 0; + + + for(n=0; nf_count++; + if(up->p_textp != NULL) { + up->p_textp->x_count++; + up->p_textp->x_ccount++; + } + u.u_cdir->i_count++; + if (u.u_rdir) + u.u_rdir->i_count++; + rpp = p; + u.u_procp = rpp; + rip = up; + n = rip->p_size; + a1 = rip->p_addr; + rpp->p_size = n; + if (save(u.u_ssav)) { + setscr(); + if(u.u_segmented) { + invsdrs(); + segureg(); + } else + sureg(); + return(1); + } + a2 = malloc(coremap, n); + if(a2 == NULL) { + rip->p_stat = SIDL; + rpp->p_addr = a1; + xswap(rpp, 0, 0); + rip->p_stat = SRUN; + } else { + rpp->p_addr = a2; + while(n--) + copyseg(a1++, a2++); + } + u.u_procp = rip; + setrq(rpp); + rpp->p_flag |= SSWAP; + return(0); +} + +expand(newsize) +{ + register i, n; + register struct proc *p; + register a1, a2; + int k; + + p = u.u_procp; + n = p->p_size; + p->p_size = newsize; + a1 = p->p_addr; + if(n >= newsize) { + mfree(coremap, n-newsize, a1+newsize); + return; + } + if (save(u.u_ssav)) { + setscr(); + if(u.u_segmented) { + invsdrs(); + segureg(); + return; + } + sureg(); + return; + } + a2 = malloc(coremap, newsize); + if(a2 == NULL) { + xswap(p, 1, n); + p->p_flag |= SSWAP; + qswtch(); + /* no return */ + } + p->p_addr = a2; + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern Nproc, Maxmem, Maxuprc; + +/* + * exec system call, with and without environments. + */ + +struct execa { + char *fname; + char **argp; + char **envp; +}; + +exec() +{ + ((struct execa *)u.u_ap)->envp = NULL; + exece(); +} + +#define NCABLK (NCARGS+BSIZE-1)/BSIZE +exece() +{ + register int nc, nc1; + register char *cp; + register struct buf *bp; + register struct execa *uap; + int ne; + int bno; + unsigned ap; + char b; + saddr_t c, stkv; + struct inode *ip; + extern struct inode *gethead(); + + if ((ip = namei(uchar, 0)) == NULL) + return; + bno = 0; + bp = 0; + if (access(ip, IEXEC)) + goto bad1; + if ((ip->i_mode & IFMT) != IFREG || + (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0){ +bad: u.u_error = EACCES; + goto bad1; + } + nc1 = 0; + ne = 0; + nc = 0; + uap = (struct execa *)u.u_ap; + if ((bno = malloc(swapmap, 10)) == 0) + panic("Out of swap"); + if (((!u.u_segmented) && ((long)uap->argp & 0x0ffffL) != 0L) || + (u.u_segmented && uap->argp)) + for (;;){ + c.l = 0; + if (((!u.u_segmented) && (long)uap->argp & 0x0ffffL) || + (u.u_segmented && uap->argp)){ + if (u.u_segmented){ + if (fuword(uap->argp, &c.left) || + (fuword((long)uap->argp+2, &c.right))) + goto bad; + (long)uap->argp += 4; + } else { if (fuword(uap->argp,&c.right)) + goto bad; + c.left = nsseg(c.right); + (long)uap->argp += 2; + } + } + if ((!u.u_segmented && c.right == NULL && ((long)uap->envp & 0xffffL) != NULL) || + (u.u_segmented && (c.l == 0L) && (uap->envp != 0L))){ + uap->argp = 0; +/* b24 */ if (u.u_segmented){ + if ((fuword(uap->envp, &c.left)) || + (fuword((long)uap->envp+2, &c.right))) + goto bad; +/* 27 */ if (!c.l) + break; + (long)uap->envp += 2; + } else { +/* 28 */ if (fuword(uap->envp, &c.right)) + goto bad; + if (c.right != 0L) + break; + c.left = nsseg(c.right); + } + (long)uap->envp += 2; + ne++; + } +/* 30 */ if ((u.u_segmented || c.right != 0L) && + (!u.u_segmented || c.l != 0)){ + nc1++; + do { + /* 34 */ if (nc >= 0x13ff) + u.u_error = E2BIG; + if (fubyte (c.l++, &b)) + u.u_error = EFAULT; + if (u.u_error) + goto bad1; + if ((nc & 0x1ff) == 0){ + if (bp) + bawrite(bp); + bp = getblk(swapdev, (daddr_t)(bno+swplo+(nc>>BSHIFT))); + cp = bp->b_un.b_addr; + } + nc++; + *cp++ = b; + } while (b > 0); + } else + break; + } +/*40*/ if (bp) + bawrite(bp); + bp = 0; + nc = (nc + NBPW -1) & ~(NBPW -1); + if (u.u_error || getxfile(ip, nc) || u.u_error){ + u.u_segmented = (u.u_state->s_ps & SEGFCW)?1:0; + setscr(); + goto bad1; + } + ap = -nc - NBPW; + c.left = u.u_stakseg << 8; +/*45*/ if (u.u_segmented) + c.right = ap - nc1*2*NBPW - 3*2*NBPW; + else + c.right = ap - nc1*NBPW - 3*NBPW; + u.u_state->s_sp = c.right; +/*46*/ if (suword(c.l, nc1 - ne)) + goto bad; + nc = 0; + while (1){ +/* b57 */ if (u.u_segmented){ + c.right += 2; +/* b58 */ if (nc1 == ne){ + if (suword(c.l, 0) || suword(c.l+2, 0)) + goto bad; + c.right += 4; + } +/* b61 */ if (--nc1 >= 0){ + if (suword(c.l, u.u_stakseg<<8) || suword(c.l+2, ap)) + goto bad; + c.right += 2; + } else + break; + } else { + c.right += 2; + if (nc1 == ne){ + if (suword(c.l, 0)) + goto bad; + c.right += 2; + } +/* b54 */ if (--nc1 >= 0){ + if (suword(c.l, ap)) + goto bad; + } else + break; + } + while (1){ +/* b49 */ if ((nc & 0x1ff) == 0){ + if (bp) + brelse(bp); + bp = bread(swapdev, (daddr_t)bno+swplo+(nc>>BSHIFT)); + cp = bp->b_un.b_addr; + } + stkv.left = u.u_stakseg<<8; + stkv.right = ap++; + if (subyte(stkv.l, (b = *cp++))) + goto bad; + nc++; +/* b56 */ if (b & 0xff) + continue; + else + break; + } + } + if (suword(c.l, 0)) + goto bad; + if (u.u_error) + if (suword(c.l+2, 0)) + goto bad; + stkv.left = u.u_stakseg<<8; + stkv.right = ap; + if (suword(stkv.l, 0)) + goto bad; + setregs(); +bad1: if (bp) + brelse(bp); + if (bno) + mfree(swapmap, 10, bno); + iput(ip); +} + +/* + * Read in and set up memory for executed file. + */ + +getxfile(ip, nargc) +register struct inode *ip; +register unsigned nargc; +{ + register i; + register magic, udsize; + unsigned int utsize, ussize, head_size; + int sepid; + int ovly; + unsigned long curdsiz; + unsigned long code_size, data_size; + unsigned long bss_size; + int scn, nseg, cseg; + int segment; + int stackno, offs; + char segno[NUSEGS]; + int j; + unsigned int segmts[NUSEGS-1]; + unsigned int stext; + unsigned int sdata; + unsigned int sbss; + + u.u_base.l = (caddr_t)&u.u_exdata; + u.u_count = sizeof(struct s_head); + u.u_offset = 0; + u.u_segflg = 1; + readi(); + u.u_segflg = 0; + if (u.u_error) /* 1 */ + return ovly; + if (u.u_count){ +bad0: u.u_error = ENOEXEC; + return ovly; + } + sepid = 0; + ovly = 0; + if (((magic = u.u_exdata.s_exc.s_magic) & 0x100) == 0){ + bss_size = 0; + data_size = 0; + code_size = 0; + cseg = 0; + nseg = u.u_exdata.s_exc.s_segt/sizeof(struct segt); + if (u.u_exdata.s_exc.s_flag & SF_7FSTK) + stackno = STAK; + else + stackno = OLDSEGSTAK; + if (nseg > NUSEGS){ + u.u_error = ENOEXEC; + return ovly; + } + switch (magic){ + case S_MAGIC3: sepid++; + case S_MAGIC1: scn = -1; + for (i=0; i < (nseg+1)/2; i++){ + for(j = 0; ; j++){ + if ( j <= 1){ + segment = u.u_exdata.segtable[j].sg_segno; + stext = u.u_exdata.segtable[j].sg_code; + sdata = u.u_exdata.segtable[j].sg_data; + sbss = u.u_exdata.segtable[j].sg_bss; + if (++cseg > nseg) /* 10 */ + break; + } else + break; + segno[++scn] = segment; + segmts[scn] = 0; +/* 11 */ if (u.u_exdata.segtable[j].sg_atr & SG_CODE){ + segmts[scn] = stext; +/* 12 */ if (sepid){ + segno[scn] |= 0x80; + code_size += (unsigned long)stext; +/* 13 */ if (sestabur(lbtoc((long)stext), segno[scn], scn, 0)) + goto bad0; + else + continue; + } else { + u.u_tseg = segno[scn]; + u.u_toff = lbtoc((long)stext); + data_size += stext; + if (sdata == 0 && sbss == 0) + if (sestabur(lbtoc((long)stext), segno[scn], scn, 1)) + goto bad0; + } + } +/* 17 */ if (u.u_exdata.segtable[j].sg_atr & SG_DATA){ + segmts[scn] += sdata; + curdsiz = (unsigned long)segmts[scn] + (unsigned long)sbss; + if ((unsigned)curdsiz != curdsiz){ + u.u_error = ENOMEM; + return ovly; + } + data_size += sdata; + bss_size += sbss; +/* 19 */ if (sestabur(lbtoc((long)(segmts[scn]+sbss)), segno[scn], scn, 1)) + goto bad0; + } else { + if (u.u_exdata.segtable[j].sg_atr & SG_BSS){ + bss_size += sbss; +/* 21 */ if (sestabur(lbtoc((long)(sbss + stext)), segno[scn], scn, 1)) + goto bad0; + } + } + } + u.u_base.l = (caddr_t)u.u_exdata.segtable; + u.u_count = 32; + u.u_segflg = 1; + readi(ip); + u.u_segflg = 0; + } + if (code_size && (ip->i_flag & ITEXT) == 0 && ip->i_count != 1){ + u.u_error = ENOSEG; + return ovly; + } + ussize = lbtoc((long)nargc) + SSIZE; + u.u_stakseg = stackno; +/* 25*/ if (sestabur(ussize, stackno, 0, 0)) + goto bad0; + utsize = lbtoc((long)code_size); + udsize = lbtoc((long)(data_size + bss_size)); + if ((utsize+USIZE+udsize+ussize) > umemory){ + u.u_error = ENOMEM; + return ovly; + } + u.u_segmented = 1; + setscr(); + u.u_exdsz = u.u_exdata.s_exc.s_segt + 24; + u.u_nsegs = nseg; +/* 27*/ for (i = 0; i < nseg; i++) + u.u_segno[i] = segno[i]; + u.u_sep = (unsigned char)sepid; + u.u_prof[0].pr_scale = 0; + u.u_nprof = 0; + xfree(); + i = udsize + USIZE + ussize; + expand(i); + while (--i >= USIZE) + clearseg(u.u_procp->p_addr + i); + xalloc(ip, code_size, &segmts[0]); + if (code_size == 0){ + invsdrs(); + segureg(); + } + u.u_offset = u.u_exdsz; + for (scn = 0;scn < nseg; scn++){ + if (u.u_segno[scn] & 0x80){ + u.u_offset += segmts[scn]; + sestabur(u.u_segmts[scn].sg_limit+1, u.u_segno[scn], scn, 1); + } else { + u.u_base.left = ctob(u.u_segno[scn] & 0x7f); + u.u_base.right = 0; + u.u_count = segmts[scn]; + readi(ip); + } + } + if ((u.u_procp->p_flag & STRC) == 0){ + if ((ip->i_mode & ISUID) && (u.u_uid)){ + u.u_uid = ip->i_uid; + u.u_procp->p_uid = ip->i_uid; + } + if (ip->i_mode & ISGID) + u.u_gid = ip->i_gid; + } else + psignal(u.u_procp, SIGTRAP); + u.u_dsize = u.u_tsize = utsize; + u.u_ssize = ussize; + segureg(); + return ovly; + case S_MAGIC4: + default: u.u_error = ENOEXEC; + return ovly; + } + } else /* von b3 */ + code_size = u.u_exdata.segtable[0].sg_code; + if ((head_size = u.u_exdata.s_exc.s_segt) == sizeof(struct segt) || (magic == N_MAGIC1)) + data_size = u.u_exdata.segtable[0].sg_data; + else + data_size = u.u_exdata.segtable[1].sg_data; + bss_size = (unsigned)u.u_exdata.s_exc.s_bss; + u.u_exdsz = sizeof(struct s_head); + if (head_size == sizeof(struct segt)) + u.u_exdsz -= head_size; + switch(magic){ + case N_MAGIC1: + { data_size = curdsiz = data_size + code_size; + u.u_exdata.segtable[0].sg_data = curdsiz; + if ((unsigned)curdsiz != curdsiz){ + u.u_error = ENOMEM; + return ovly; + } + code_size=0; + u.u_exdata.segtable[0].sg_code=0; + break; + } + case N_MAGIC4: + { ovly++; + break; + } + case N_MAGIC3: + { sepid++; + break; + } + default: + { u.u_error = ENOEXEC; + return ovly; + } + } + if (code_size && (ip->i_flag & ITEXT) == 0 && + ip->i_count!=(cnt_t)1){ + u.u_error = ENOSEG; + return ovly; + } + utsize = lbtoc((long)code_size); + curdsiz = data_size + bss_size; +/* 45 */if ((unsigned)curdsiz != curdsiz){ + u.u_error = ENOMEM; + return ovly; + } + udsize = lbtoc((long)curdsiz); + ussize = lbtoc((long)nargc) + SSIZE; + u.u_segmented = 0; + setscr(); + if (ovly){ + if (u.u_sep == 0) + if (ctos(utsize) != ctos(u.u_tsize)){ + u.u_error = ENOMEM; + return ovly; + } +/* 49 */if (nargc){ + u.u_error = ENOMEM; + return ovly; + } + udsize = u.u_dsize; + ussize = u.u_ssize; + sepid = u.u_sep; + xfree(); + xalloc(ip, code_size); + u.u_state->s_pc = u.u_exdata.s_exc.s_entry & -2L; + } else { + u.u_prof[0].pr_scale = 0; + xfree(); + i = udsize + USIZE + ussize; + expand(i); + while (--i >= USIZE) + clearseg(u.u_procp->p_addr + i); + xalloc(ip, code_size); + estabur(0, udsize, 0, 1); + u.u_base.left = USEGW; + u.u_base.right = 0; + u.u_offset = (unsigned long)(u.u_exdsz+(unsigned)code_size); + u.u_count = data_size; + readi(ip); +/* 51 */ if ((u.u_procp->p_flag & STRC)==0){ + if ((ip->i_mode & ISUID) && (u.u_uid)){ + u.u_uid = ip->i_uid; + u.u_procp->p_uid = ip->i_uid; + } + if (ip->i_mode & ISGID) + u.u_gid = ip->i_gid; + } else + psignal(u.u_procp, SIGTRAP); + } + u.u_tsize = utsize; + u.u_dsize = udsize; + u.u_ssize = ussize; + u.u_sep = (unsigned char)sepid; + u.u_stakseg = STAK; + estabur(utsize, udsize, ussize, 1); + return ovly; +} + +/* + * Clear registers on exec + */ +setregs() +{ + register long *rp; + register i; + register struct file *fp; + + for (rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++) + if ((*rp & 1) == 0) + *rp = 0; + for (i = 0; i < 15; i++) + u.u_state->s_reg[i] = 0; + if (u.u_segmented) + u.u_state->s_reg[14] = u.u_stakseg<<8; + for (i = 0; i < 8; i++){ + u.u_fpstate.uf_reg[i][0] = 0x3fff; + u.u_fpstate.uf_reg[i][1] = 0x8000; + u.u_fpstate.uf_reg[i][2] = 0; + u.u_fpstate.uf_reg[i][3] = 0; + u.u_fpstate.uf_reg[i][4] = 0; + } + fsetregs(); + u.u_state->s_pc = u.u_exdata.s_exc.s_entry & -2; + if (!u.u_segmented) + u.u_state->s_pcseg = USEGW; + else + u.u_state->s_pcseg = u.u_exdata.s_exc.s_entry >> 16; + for (i=0; irval & 0xff) << 8); +} + +/* + * Release resources. + * Enter zombie state. + * Wake up parent and init processes, + * and dispose of children. + */ +exit(rv) +{ + register int i; + register struct proc *p, *q; + struct file *fp; + + p = u.u_procp; + p->p_flag &= ~(SULOCK | STRC); + p->p_clktim = 0; + for (i=0; ip_pid == p->p_pgrp) + && (u.u_ttyp != NULL) + && (u.u_ttyp->t_pgrp == p->p_pgrp)) { + u.u_ttyp->t_pgrp = 0; + signal(p->p_pgrp, SIGHUP); + } + p->p_pgrp = 0; + for (i=0; ip_size, p->p_addr); + p->p_stat = SZOMB; + ((struct xproc *)p)->xp_xstat = rv; + ((struct xproc *)p)->xp_utime = u.u_cutime + u.u_utime; + ((struct xproc *)p)->xp_stime = u.u_cstime + u.u_stime; + for (q = &proc[1]; q < &proc[Nproc]; q++) { + if (p->p_pid == q->p_ppid) { + q->p_ppid = 1; + if (q->p_stat == SZOMB) + psignal(&proc[1], SIGCLD); + if (q->p_stat == SSTOP) + setrun(q); + } else if (p->p_ppid==q->p_pid) + psignal(q, SIGSYS); + if (p->p_pid == q->p_pgrp) + q->p_pgrp = 0; + } + swtch(); +} + +/* + * Wait system call. + * Search for a terminated (zombie) child, + * finally lay it to rest, and collect its status. + * Look also for stopped (traced) children, + * and pass back status from them. + */ +wait() +{ + register f; + register struct proc *p; + +loop: + f = 0; + for (p = &proc[1]; p < &proc[Nproc]; p++) + if (p->p_ppid == u.u_procp->p_pid) { + f++; + if (p->p_stat == SZOMB) { + freeproc(p, 1); + return; + } + if (p->p_stat == SSTOP) { + if ((p->p_flag&SWTED) == 0) { + p->p_flag |= SWTED; + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = (fsig(p)<<8) | 0177; + return; + } + continue; + } + } + if (f) { + sleep((caddr_t)u.u_procp, PWAIT); + goto loop; + } + u.u_error = ECHILD; +} + +/* + * Remove zombie children from the process table. + */ +freeproc(p, flag) +register struct proc *p; +{ + if (flag) { + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; + } + u.u_cutime += ((struct xproc *)p)->xp_utime; + u.u_cstime += ((struct xproc *)p)->xp_stime; + p->p_stat = NULL; + p->p_pid = 0; + p->p_ppid = 0; + p->p_sig = 0L; + p->p_flag = 0; + p->p_wchan = 0; +} + +/* + * fork system call. + */ +fork() +{ + register struct proc *p1, *p2; + register a; + register n; + + if (u.u_segmented){ + n = ctod(u.u_tsize + USIZE + u.u_dsize + u.u_ssize); + if ((a = malloc(swapmap, n)) == (int)0){ +out0: u.u_error = ENOMEM; + goto out; + } else + mfree(swapmap, n, a); + } else + if ((a = malloc(swapmap, ctod(Maxmem))) == (int)0) + goto out0; + else + mfree(swapmap, ctod(Maxmem), a); + for (a=0,p2=0,p1 = &proc[0]; p1 < &proc[Nproc]; p1++){ + if (p1->p_stat == NULL && p2 == NULL) + p2 = p1; + if (p1->p_uid == u.u_uid && p1->p_stat) + a++; + } + if (!p2 || u.u_uid && ((p2 == &proc[Nproc-1]) || (a>Maxuprc))){ + u.u_error = EAGAIN; + goto out; + } + p1 = u.u_procp; + if (newproc()){ + u.u_r.r_val1 = p1->p_pid; + u.u_start = time; + u.u_mem = p2->p_size; + u.u_ioch = 0; + u.u_iow = 0; + u.u_ior = 0; + u.u_cstime = 0; + u.u_stime = 0; + u.u_cutime = 0; + u.u_utime = 0; + u.u_acflag = AFORK; + return; + } + u.u_r.r_val1 = p2->p_pid; + +out: + u.u_state->s_pc += NBPW; +} diff --git a/WEGA/src/uts/sys/text.c b/WEGA/src/uts/sys/text.c new file mode 100644 index 0000000..9d77fcf --- /dev/null +++ b/WEGA/src/uts/sys/text.c @@ -0,0 +1,313 @@ +/* @(#)text.c 1.2 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char textwstr[]="@[$]text.c Rev : 4.1 08/27/83 12:00:24"; +extern Ntext; + +/* + * Swap out process p. + * The ff flag causes its core to be freed-- + * it may be off when called to create an image for a + * child process in newproc. + * Os is the old size of the data area of the process, + * and is supplied during core expansion swaps. + */ +xswap(p, ff, os) +register struct proc *p; +{ + register a; + + if (os == 0) + os = p->p_size; + a = malloc(swapmap, ctod(p->p_size)); + if (a == 0L) + panic("out of swap space"); + p->p_flag |= SLOCK; + xccdec(p->p_textp); + swap(swapdev, a, p->p_addr, os, B_WRITE); + if (ff) + mfree(coremap, os, p->p_addr); + p->p_addr = a; + p->p_flag &= ~(SLOAD|SLOCK); + p->p_time = 0; + if (runout) { + runout = 0; + wakeup((caddr_t)&runout); + } +} + + +/* + * relinquish use of the shared text segment + * of a process. + */ +xfree() +{ + char a[8]; /* fill stack region */ + register struct text *xp; + register struct inode *ip; + int s; + + if ((xp=u.u_procp->p_textp) == NULL) + return; + xlock(xp); + xp->x_flag &= ~XLOCK; + u.u_procp->p_textp = NULL; + ip = xp->x_iptr; + if (--xp->x_count==0 && (ip->i_mode&ISVTX)==0) { + xp->x_iptr = NULL; + mfree(swapmap, (ctod(xp->x_size)), xp->x_daddr); + mfree(coremap, xp->x_size, xp->x_caddr); + s = dvi(); + ip->i_flag &= ~ITEXT; + if (ip->i_flag&ILOCK) + ip->i_count--; + else { + iput(ip); + rvi(s); + } + } + else + xccdec(xp); +} + + +/* + * Attach to a shared text segment. + * If there is no shared text, just return. + * If there is, hook up to it: + * if it is not currently being used, it has to be read + * in from the inode (ip); the written bit is set to force it + * to be written out as appropriate. + * If it is being used, but is not currently in core, + * a swap has to be done to get it back. + */ + +xalloc(ip, lc, ld) +register struct inode *ip; +long lc; +register unsigned int ld[]; +{ + register struct text *xp; + register unsigned ts; + register struct text *xp1; + short s; + unsigned s2; + + if (lc == 0) + return; + xp1 = NULL; +loop: + for (xp = &text[0]; xp < &text[Ntext]; xp++) { + if (xp->x_iptr == NULL) { + if (xp1 == NULL) + xp1 = xp; + continue; + } + if ( ip == xp->x_iptr) { + xlock(xp); + xp->x_count++; + u.u_procp->p_textp = xp; + if (xp->x_ccount == 0) + xexpand(xp); + else + xp->x_ccount++; + xunlock(xp); + return; + } + } + if ((xp=xp1) == NULL) { + printf("out of text"); + psignal(u.u_procp, SIGKILL); + return; + } + xp->x_flag = XLOAD|XLOCK; + xp->x_count = 1; + xp->x_ccount = 0; + xp->x_iptr = ip; + ip->i_flag |= ITEXT; + ip->i_count++; + ts = lbtoc(lc); + xp->x_size = ts; + if ((xp->x_daddr = malloc(swapmap, ctod((int)ts))) == NULL) + panic("out of swap space"); + u.u_procp->p_textp = xp; + xexpand(xp); + u.u_segflg = 2; + u.u_offset = u.u_exdsz; + if (u.u_segmented){ + invsdrs(); + segureg(); + for (s=0; u.u_nsegs > s; s++){ + s2 = ld[s]; + if (((int)u.u_segno[s] & 0x80) == 0) + u.u_offset += s2; + else + u.u_count = s2; + u.u_base.left = (u.u_segno[s] & 0x7f)<<8; + u.u_base.right = 0; + u.u_procp->p_flag |= SLOCK; /* proc can't be swapped */ + readi(ip); + u.u_procp->p_flag &= ~SLOCK; + } + } else { + estabur(ts, 0, 0, 0 ); + u.u_count = lc.right; + u.u_base.left = USEGW; + u.u_base.right = 0; + u.u_procp->p_flag |= SLOCK; + readi(ip); + u.u_procp->p_flag &= ~SLOCK; + } + u.u_segflg = 0; + xp->x_flag = XWRIT;/* written into, must swap out */ +} + +/* + * Assure core for text segment + * Text must be locked to keep someone else from + * freeing it in the meantime. + * x_ccount must be 0. + */ +xexpand(xp) +register struct text *xp; +{ + if ((xp->x_caddr = malloc(coremap, xp->x_size)) != NULL) { + if ((xp->x_flag&XLOAD)==0) + swap(swapdev, xp->x_daddr, xp->x_caddr, xp->x_size, B_READ); + xp->x_ccount++; + xunlock(xp); + return; + } + if (save(u.u_ssav)){ + setscr(); + if (u.u_segmented){ + invsdrs(); + segureg(); + } else + sureg(); + return; + } + xswap(u.u_procp, 1, 0); + xunlock(xp); + u.u_procp->p_flag |= SSWAP; + qswtch(); + /* no return */ +} + +/* + * Lock and unlock a text segment from swapping + */ +xlock(xp) +register struct text *xp; +{ + + while(xp->x_flag&XLOCK) { + xp->x_flag |= XWANT; + sleep((caddr_t)xp, PSWP); + } + xp->x_flag |= XLOCK; +} + +xunlock(xp) +register struct text *xp; +{ + + if (xp->x_flag&XWANT) + wakeup((caddr_t)xp); + xp->x_flag &= ~(XLOCK|XWANT); +} + +/* + * Decrement the in-core usage count of a shared text segment. + * When it drops to zero, free the core space. + */ +xccdec(xp) +register struct text *xp; +{ + + if (xp==NULL || xp->x_ccount==0) + return; + xlock(xp); + if (--xp->x_ccount==0) { + if (xp->x_flag&XWRIT) { + xp->x_flag &= ~XWRIT; + swap(swapdev, xp->x_daddr, xp->x_caddr, xp->x_size, B_WRITE); + } + mfree(coremap, xp->x_size, xp->x_caddr); + } + xunlock(xp); +} +/* + * free the swap image of all unused saved-text text segments + * which are from device dev (used by umount system call). + */ +xumount(dev) +register dev_t dev; +{ + register struct text *xp; + + for (xp = &text[0]; xp < &text[Ntext] ; xp++) { + if (xp->x_iptr == NULL) + continue; + if (dev != xp->x_iptr->i_dev) + continue; + xuntext(xp); + } +} + +/* + * remove a shared text segment from the text table, if possible. + */ +xrele(ip) +register struct inode *ip; +{ + register struct text *xp; + + if ((ip->i_flag&ITEXT) == 0) + return; + for (xp = &text[0]; xp < &text[Ntext]; xp++) + if (ip==xp->x_iptr) + xuntext(xp); +} + +/* + * remove text image from the text table. + * the use count must be zero. + */ +xuntext(xp) +register struct text *xp; +{ + register struct inode *ip; + int s; + + xlock(xp); + if (xp->x_count) { + xunlock(xp); + return; + } + ip = xp->x_iptr; + xp->x_flag &= ~XLOCK; + xp->x_iptr = NULL; + mfree(swapmap, ctod(xp->x_size), xp->x_daddr); + ip->i_flag &= ~ITEXT; + s = dvi(); + if (ip->i_flag&ILOCK) + ip->i_count--; + else + iput(ip); + rvi(s); + return; +}