/ u1 -- unix unkni: / used for all system calls sysent: incb sysflg / indicate a system routine is beq 1f / in progress jmp panic / called if trap inside system 1: mov $s.syst+2,clockp mov r0,-(sp) / save user registers mov sp,u.r0 / pointer to bottom of users stack in u.r0 mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) mov r4,-(sp) mov r5,-(sp) mov ac,-(sp) / "accumulator" register for extended / arithmetic unit mov mq,-(sp) / "multiplier quotient" register for the / extended arithmetic unit mov sc,-(sp) / "step count" register for the extended / arithmetic unit mov sp,u.sp / u.sp points to top of users stack mov 18.(sp),r0 / store pc in r0 mov -(r0),r0 / sys inst in r0 10400xxx sub $sys,r0 / get xxx code asl r0 / multiply by 2 to jump indirect in bytes cmp r0,$2f-1f / limit of table (35) exceeded bhis badsys / yes, bad system call bic $341,20.(sp) / set users processor priority to 0 and clear / carry bit jmp *1f(r0) / jump indirect thru table of addresses / to proper system routine. 1: sysrele / 0 sysexit / 1 sysfork / 2 sysread / 3 syswrite / 4 sysopen / 5 sysclose / 6 syswait / 7 syscreat / 8 syslink / 9 sysunlink / 10 sysexec / 11 syschdir / 12 systime / 13 sysmkdir / 14 syschmod / 15 syschown / 16 sysbreak / 17 sysstat / 18 sysseek / 19 systell / 20 sysmount / 21 sysumount / 22 syssetuid / 23 sysgetuid / 24 sysstime / 25 sysquit / 26 sysintr / 27 sysfstat / 28 sysemt / 29 sysmdate / 30 sysstty / 31 sysgtty / 32 sysilgins / 33 2: error: mov u.sp,r1 bis $1,20.(r1) / set c bit in processor status word below / users stack sysret: tstb u.bsys / is a process about to be terminated because bne sysexit / of an error? yes, go to sysexit mov u.sp,sp / no point stack to users stack clr r1 / zero r1 to check last mentioned i-node jsr r0,iget / if last mentioned i-node has been modified / it is written out tstb smod / has the super block been modified beq 1f / no, 1f clrb smod / yes, clear smod bis $1000,sb0 / set write bit in I/O queue for super block / output jsr r0,ppoke / write out modified super block to disk 1: tstb mmod / has the super block for the dismountable file / system beq 1f / been modified? no, 1f clrb mmod / yes, clear mmod movb mntd,sb1 / set the I/O queue bis $1000,sb1 / set write bit in I/O queue for detached sb jsr r0,ppoke / write it out to its device 1: tstb uquant / is the time quantum 0? bne 1f / no, don't swap it out sysrele: jsr r0,tswap / yes, swap it out 1: mov (sp)+,sc / restore user registers mov (sp)+,mq mov (sp)+,ac mov (sp)+,r5 mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 mov $s.chrgt+2,clockp decb sysflg / turn system flag off jsr r0,isintr / is there an interrupt from the user br intract / yes, output gets flushed, take interrupt / action rti / no return from interrupt badsys: incb u.bsys / turn on the user's bad-system flag mov $3f,u.namep / point u.namep to "core\0\0" jsr r0,namei / get the i-number for the core image file br 1f / error neg r1 / negate the i-number to open the core image file / for writing jsr r0,iopen / open the core image file jsr r0,itrunc / free all associated blocks br 2f 1: mov $17,r1 / put i-node mode (17) in r1 jsr r0,maknod / make an i-node mov u.dirbuf,r1 / put i-nodes number in r1 2: mov $core,u.base / move address core to u.base mov $ecore-core,u.count / put the byte count in u.count mov $u.off,u.fofp / more user offset to u.fofp clr u.off / clear user offset jsr r0,writei / write out the core image to the user mov $user,u.base / pt. u.base to user mov $64.,u.count / u.count = 64 jsr r0,writei / write out all the user parameters neg r1 / make i-number positive jsr r0,iclose / close the core image file br sysexit / 3: <core\0\0> sysexit: / terminate process clr u.intr / clear interrupt control word clr r1 / clear r1 1: / r1 has file descriptor (index to u.fp list) Search the whole list jsr r0,fclose / close all files the process opened br .+2 / ignore error return inc r1 / increment file descriptor cmp r1,$10. / end of u.fp list? blt 1b / no, go back movb u.uno,r1 / yes, move dying process's number to r1 clrb p.stat-1(r1) / free the process asl r1 / use r1 for index into the below tables mov p.pid-2(r1),r3 / move dying process's name to r3 mov p.ppid-2(r1),r4 / move its parents name to r4 clr r2 clr r5 / initialize reg 1: / find children of this dying process, if they are zombies, free them add $2,r2 / search parent process table for dying process's name cmp p.ppid-2(r2),r3 / found it? bne 3f / no asr r2 / yes, it is a parent cmpb p.stat-1(r2),$3 / is the child of this dying process a / zombie bne 2f / no clrb p.stat-1(r2) / yes, free the child process 2: asl r2 3: / search the process name table for the dying process's parent cmp p.pid-2(r2),r4 / found it? bne 3f / no mov r2,r5 / yes, put index to p.pid table (parents / process # x2) in r5 3: cmp r2,$nproc+nproc / has whole table been searched? blt 1b / no, go back mov r5,r1 / yes, r1 now has parents process # x2 beq 2f / no parent has been found. The process just dies asr r1 / set up index to p.stat movb p.stat-1(r1),r2 / move status of parent to r2 beq 2f / if its been freed, 2f cmp r2,$3 / is parent a zombie? beq 2f / yes, 2f movb u.uno,r3 / move dying process's number to r3 movb $3,p.stat-1(r3) / make the process a zombie cmp r2,$2 / is the parent waiting for this child to die bne 2f / yes, notify parent not to wait any more decb p.stat-1(r1) / awaken it by putting it (parent) mov $runq+4,r2 / on the runq jsr r0, putlu 2: / the process dies clrb u.uno / put zero as the process number, so "swap" will jsr r0,swap / overwrite process with another process 0 / and thereby kill it; halt? intract: / interrupt action cmp *(sp),$rti / are you in a clock interrupt? bne 1f / no, 1f cmp (sp)+,(sp)+ / pop clock pointer 1: / now in user area mov r1,-(sp) / save r1 mov u.ttyp,r1 / pointer to tty buffer in control-to r1 cmpb 6(r1),$177 / is the interrupt char equal to "del" beq 1f / yes, 1f clrb 6(r1) / no, clear the byte (must be a quit character) mov (sp)+,r1 / restore r1 clr u.quit / clear quit flag bis $20,2(sp) / set trace for quit (sets t bit of ps-trace trap) rti / return from interrupt 1: / interrupt char = del clrb 6(r1) / clear the interrupt byte in the buffer mov (sp)+,r1 / restore r1 cmp u.intr,$core / should control be transferred to loc core? blo 1f jmp *u.intr / user to do rti yes, transfer to loc core 1: sys 1 / exit syswait: / wait for a process to die movb u.uno,r1 / put parents process number in r1 asl r1 / x2 to get index into p.pid table mov p.pid-2(r1),r1 / get the name of this process clr r2 clr r3 / initialize reg 3 1: add $2,r2 / use r2 for index into p.ppid table / search table / of parent processes for this process name cmp p.ppid-2(r2),r1 / r2 will contain the childs process number bne 3f / branch if no match of parent process name inc r3 / yes, a match, r3 indicates number of children asr r2 / r2/2 to get index to p.stat table cmpb p.stat-1(r2),$3 / is the child process a zombie? bne 2f / no, skip it clrb p.stat-1(r2) / yes, free it asl r2 / r2x2 to get index into p.pid table mov p.pid-2(r2),*u.r0 / put childs process name in (u.r0) br sysret1 / return cause child is dead 2: asl r2 / r2x2 to get index into p.ppid table 3: cmp r2,$nproc+nproc / have all processes been checked? blt 1b / no, continue search tst r3 / one gets here if there are no children or children / that are still active beq error1 / there are no children, error movb u.uno,r1 / there are children so put parent process number / in r1 incb p.stat-1(r1) / it is waiting for other children to die jsr r0,swap / swap it out, because it's waiting br syswait / wait on next process error1: jmp error / see 'error' routine sysret1: jmp sysret / see 'sysret' routine sysfork: / create a new process clr r1 1: / search p.stat table for unused process number inc r1 tstb p.stat-1(r1) / is process active, unused, dead beq 1f / it's unused so branch cmp r1,$nproc / all processes checked blt 1b / no, branch back add $2,18.(sp) / add 2 to pc when trap occured, points / to old process return br error1 / no room for a new process 1: movb u.uno,-(sp) / save parent process number movb r1,u.uno / set child process number to r1 incb p.stat-1(r1) / set p.stat entry for child process to / active status mov u.ttyp,r2 / put pointer to parent process' control tty / buffer in r2 beq 2f / branch, if no such tty assigned clrb 6(r2) / clear interrupt character in tty buffer 2: mov $runq+4,r2 jsr r0,putlu / put child process on lowest priority run queue asl r1 / multiply r1 by 2 to get index into p.pid table inc mpid / increment m.pid; get a new process name mov mpid,p.pid-2(r1) / put new process name in child process' / name slot movb (sp),r2 / put parent process number in r2 asl r2 / multiply by 2 to get index into below tables mov p.pid-2(r2),r2 / get process name of parent process mov r2,p.ppid-2(r1) / put parent process name in parent / process slot for child mov r2,*u.r0 / put parent process name on stack at location / where r0 was saved mov $sysret1,-(sp) / mov sp,u.usp / contents of sp at the time when user is / swapped out mov $sstack,sp / point sp to swapping stack space jsr r0,wswap / put child process out on drum jsr r0,unpack / unpack user stack mov u.usp,sp / restore user stack pointer tst (sp)+ / bump stack pointer movb (sp)+,u.uno / put parent process number in u.uno mov mpid,*u.r0 / put child process name on stack where r0 / was saved add $2,18.(sp) / add 2 to pc on stack; gives parent / process return clr r1 1: / search u.fp list to find the files opened by the parent process movb u.fp(r1),r2 / get an open file for this process beq 2f / file has not been opened by parent, so branch asl r2 / multiply by 8 asl r2 / to get index into fsp table asl r2 incb fsp-2(r2) / increment number of processes using file, / because child will now be using this file 2: inc r1 / get next open file cmp r1,$10. / 10. files is the maximum number which can be / opened blt 1b / check next entry br sysret1 sysread: jsr r0,rw1 / get i-number of file to be read into r1 tst r1 / negative i-number? ble error1 / yes, error 1 to read it should be positive jsr r0,readi / read data into core br 1f syswrite: jsr r0,rw1 / get i-number in r1 of file to write tst r1 / positive i-number ? bge error1 / yes, error 1 negative i-number means write neg r1 / make it positive jsr r0,writei / write data 1: mov u.nread,*u.r0 / put no. of bytes transferred into (u.r0) br sysret1 rw1: jsr r0,arg; u.base / get buffer pointer jsr r0,arg; u.count / get no. of characters mov *u.r0,r1 / put file descriptor (index to u.fp table) in r1 jsr r0,getf / get i-number of the file in r1 rts r0 sysopen: jsr r0,arg2 / get sys args into u.namep and on stack jsr r0,namei / i-number of file in r1 br error2 / file not found tst (sp) / is mode = 0 (2nd arg of call; 0 means, open for read) beq 1f / yes, leave i-number positive neg r1 / open for writing so make i-number negative 1: jsr r0,iopen / open file whose i-number is in r1 tst (sp)+ / pop the stack and test the mode beq op1 / is open for read op1 op0: neg r1 / make i-number positive if open for writing op1: clr r2 / clear registers clr r3 1: / scan the list of entries in fsp table tstb u.fp(r2) / test the entry in the u.fp list beq 1f / if byte in list is 0 branch inc r2 / bump r2 so next byte can be checked cmp r2,$10. / reached end of list? blt 1b / no, go back br error2 / yes, error (no files open) 1: tst fsp(r3) / scan fsp entries beq 1f / if 0 branch add $8.,r3 / add 8 to r3 to bump it to next entry mfsp table cmp r3,$[nfiles*8.] / done scanning blt 1b / no, back br error2 / yes, error 1: / r2 has index to u.fp list; r3, has index to fsp table mov r1,fsp(r3) / put i-number of open file into next available mov cdev,fsp+2(r3) / entry in fsp table, put # of device in / next word clr fsp+4(r3) clr fsp+6(r3) / clear the next two words asr r3 asr r3 / divide by 8 to get number of the fsp entry-1 asr r3 inc r3 / add 1 to get fsp entry number movb r3,u.fp(r2) / move entry number into next available slot / in u.fp list mov r2,*u.r0 / move index to u.fp list into r0 loc on stack br sysret2 error2: jmp error / see 'error' routine sysret2: jmp sysret / see 'sysret' routine syscreat: / name; mode jsr r0,arg2 / put file name in u.namep put mode on stack jsr r0,namei / get the i-number br 2f / if file doesn't exist 2f neg r1 / if file already exists make i-number negative / (open for writing) jsr r0,iopen / jsr r0,itrunc / truncate to 0 length br op0 2: / file doesn't exist mov (sp)+,r1 / put the mode in r1 bic $!377,r1 / clear upper byte jsr r0,maknod / make an i-node for this file mov u.dirbuf,r1 / put i-number for this new file in r1 br op0 / open the file sysmkdir: / make a directory jsr r0,arg2 / point u.namep to the file name jsr r0,namei / get the i-number br .+4 / if file not found branch around error br error2 / directory already exists (error) tstb u.uid / is user the super user bne error2 / no, not allowed mov (sp)+,r1 / put the mode in r1 bic $!317,r1 / all but su and ex bis $40000,r1 / directory flag jsr r0,maknod / make the i-node for the directory br sysret2 / sysclose: / close the file mov *u.r0,r1 / move index to u.fp list into r1 jsr r0,fclose / close the file br error2 / unknown file descriptor br sysret2 sysemt: jsr r0,arg; 30 / put the argument of the sysemt call in loc 30 cmp 30,$core / was the argument a lower address than core blo 1f / yes, rtssym cmp 30,$ecore / no, was it higher than "core" and less than / "ecore" blo 2f / yes, sysret2 1: mov $rtssym,30 2: br sysret2 sysilgins: / calculate proper illegal instruction trap address jsr r0,arg; 10 / take address from sysilgins call , put / it in loc 8., cmp 10,$core / making it the illegal instruction trap address blo 1f / is the address a user core address? yes, go to 2f cmp 10,$ecore blo 2f 1: mov $fpsym,10 / no, make 'fpsum' the illegal instruction trap / address for the system 2: br sysret2 / return to the caller via 'sysret' sysmdate: / change the modification time of a file jsr r0,arg; u.namep / point u.namep to the file name jsr r0,namei / get its i-number br error2 / no, such file jsr r0,iget / get i-node into core cmpb u.uid,i.uid / is user same as owner beq 1f / yes tstb u.uid / no, is user the super user bne error2 / no, error 1: jsr r0,setimod / fill in modification data, time etc. mov 4(sp),i.mtim / move present time to mov 2(sp),i.mtim+2 / modification time br sysret2 sysstty: / set mode of typewriter; 3 consequtive word arguments jsr r0,gtty / r1 will have offset to tty block, r2 has source mov r2,-(sp) mov r1,-(sp) / put r1 and r2 on the stack 1: / flush the clist wait till typewriter is quiescent mov (sp),r1 / restore r1 to tty block offset movb tty+3(r1),0f / put cc offset into getc argument mov $240,*$ps / set processor priority to 5 jsr r0,getc; 0:../ put character from clist in r1 br .+4 / list empty, skip branch br 1b / get another character until list is empty mov 0b,r1 / move cc offset to r1 inc r1 / bump it for output clist tstb cc(r1) / is it 0 beq 1f / yes, no characters to output mov r1,0f / no, put offset in sleep arg jsr r0,sleep; 0:.. / put tty output process to sleep br 1b / try to calm it down again 1: mov (sp)+,r1 mov (sp)+,r2 / restore registers mov (r2)+,r3 / put reader control status in r3 beq 1f / if 0, 1f mov r3,rcsr(r1) / move r.c. status to reader control status / register 1: mov (r2)+,r3 / move pointer control status to r3 beq 1f / if 0 1f mov r3,tcsr(r1) / move p.c. status to printer control status reg 1: mov (r2)+,tty+4(r1) / move to flag byte of tty block jmp sysret2 / return to user sysgtty: / get status of typewriter; 3 consequtive word arguments jsr r0,gtty / r1 will have offset to tty block, r2 has / destination mov rcsr(r1),(r2)+ / put reader control status in 1st word / of dest mov tcsr(r1),(r2)+ / put printer control status in 2nd word / of dest mov tty+4(r1),(r2)+ / put mode in 3rd word jmp sysret2 / return to user gtty: jsr r0,arg; u.off / put first arg in u.off mov *u.r0,r1 / put file descriptor in r1 jsr r0,getf / get the i-number of the file tst r1 / is it open for reading bgt 1f / yes neg r1 / no, i-number is negative, so make it positive 1: sub $14.,r1 / get i-number of tty0 cmp r1,$ntty-1 / is there such a typewriter bhis error9 / no, error asl r1 / 0%2 asl r1 / 0%4 / yes asl r1 / 0%8 / multiply by 8 so r1 points to tty block mov u.off,r2 / put argument in r2 rts r0 / return