Skip to content

Instantly share code, notes, and snippets.

@sondnm
Created March 2, 2020 15:38
Show Gist options
  • Save sondnm/3515259a534227b5b5b4d25115260234 to your computer and use it in GitHub Desktop.
Save sondnm/3515259a534227b5b5b4d25115260234 to your computer and use it in GitHub Desktop.
Lions' Commentary on UNIX source code
0100: /* fundamental constants: cannot be changed */
0100: /* fundamental constants: cannot be changed */
0101:
0102:
0103: #define USIZE 16 /* size of user block (*64) */
0104: #define NULL 0
0105: #define NODEV (-1)
0106: #define ROOTINO 1 /* i number of all roots */
0107: #define DIRSIZ 14 /* max characters per directory */
0108:
0109:
0110: /* signals: dont change */
0111:
0112:
0113: #define NSIG 20
0114: #define SIGHUP 1 /* hangup */
0115: #define SIGINT 2 /* interrupt (rubout) */
0116: #define SIGQIT 3 /* quit (FS) */
0117: #define SIGINS 4 /* illegal instruction */
0118: #define SIGTRC 5 /* trace or breakpoint */
0119: #define SIGIOT 6 /* iot */
0120: #define SIGEMT 7 /* emt */
0121: #define SIGFPT 8 /* floating exception */
0122: #define SIGKIL 9 /* kill */
0123: #define SIGBUS 10 /* bus error */
0124: #define SIGSEG 11 /* segmentation violation */
0125: #define SIGSYS 12 /* sys */
0126: #define SIGPIPE 13 /* end of pipe */
0127:
0128: /* tunable variables */
0129:
0130: #define NBUF 15 /* size of buffer cache */
0131: #define NINODE 100 /* number of in core inodes */
0132: #define NFILE 100 /* number of in core file structures */
0133: #define NMOUNT 5 /* number of mountable file systems */
0134: #define NEXEC 3 /* number of simultaneous exec's */
0135: #define MAXMEM (64*32) /* max core per process
0136: - first # is Kw */
0137: #define SSIZE 20 /* initial stack size (*64 bytes) */
0138: #define SINCR 20 /* increment of stack (*64 bytes) */
0139: #define NOFILE 15 /* max open files per process */
0140: #define CANBSIZ 256 /* max size of typewriter line */
0141: #define CMAPSIZ 100 /* size of core allocation area */
0142: #define SMAPSIZ 100 /* size of swap allocation area */
0143: #define NCALL 20 /* max simultaneous time callouts */
0144: #define NPROC 50 /* max number of processes */
0145: #define NTEXT 40 /* max number of pure texts */
0146: #define NCLIST 100 /* max total clist size */
0147: #define HZ 60 /* Ticks/second of the clock */
0148:
0149:
0150:
0151: /* priorities: probably should not be altered too much */
0152:
0153:
0154: #define PSWP -100
0155: #define PINOD -90
0156: #define PRIBIO -50
0157: #define PPIPE 1
0158: #define PWAIT 40
0159: #define PSLEP 90
0160: #define PUSER 100
0161:
0162: /* Certain processor registers */
0163:
0164: #define PS 0177776
0165: #define KL 0177560
0166: #define SW 0177570
0167:
0168: /* --------------------------- */
0169:
0170: /* structure to access : */
0171:
0172:
0173: /* an integer */
0174:
0175: struct { int integ; };
0176:
0177:
0178: /* an integer in bytes */
0179:
0180: struct { char lobyte; char hibyte; };
0181:
0182:
0183: /* a sequence of integers */
0184:
0185: struct { int r[]; };
0186:
0187:
0188: /* --------------------------- */
0200: /* Random set of variables used by more than one routine. */
0201:
0202: char canonb[CANBSIZ]; /* buffer for erase and kill (#@) */
0203: int coremap[CMAPSIZ]; /* space for core allocation */
0204: int swapmap[SMAPSIZ]; /* space for swap allocation */
0205:
0206: int *rootdir; /* pointer to inode of root directory */
0207:
0208: int cputype; /* type of cpu =40, 45, or 70 */
0209:
0210: int execnt; /* number of processes in exec */
0211:
0212: int lbolt; /* time of day in 60th not in time */
0213: int time[2]; /* time in sec from 1970 */
0214: int tout[2]; /* time of day of next sleep */
0215:
0216: int mpid; /* generic for unique process id's */
0217:
0218: char runin; /* scheduling flag */
0219: char runout; /* scheduling flag */
0220: char runrun; /* scheduling flag */
0221:
0222: char curpri; /* more scheduling */
0223:
0224: int maxmem; /* actual max memory per process */
0225:
0226: int *lks; /* pointer to clock device */
0227:
0228: int rootdev; /* dev of root see conf.c */
0229: int swapdev; /* dev of swap see conf.c */
0230:
0231: int swplo; /* block number of swap space */
0232: int nswap; /* size of swap space */
0233:
0234: int updlock; /* lock for sync */
0235: int rablock; /* block to be read ahead */
0236:
0237: char regloc[]; /* locs. of saved user registers (trap.c) */
0238:
0239:
0240:
0241: /* --------------------------- */
0242:
0243:
0244:
0245:
0246:
0247:
0248:
0249:
0250:
0251: /* --------------------------- */
0252:
0253: /* The callout structure is for a routine
0254: * arranging to be called by the clock interrupt
0255: * (clock.c) with a specified argument,
0256: * within a specified amount of time.
0257: * It is used, for example, to time tab delays
0258: * on teletypes. */
0259:
0260: struct callo
0261: {
0262: int c_time; /* incremental time */
0263: int c_arg; /* argument to routine */
0264: int (*c_func)(); /* routine */
0265: } callout[NCALL];
0266: /* --------------------------- */
0267:
0268: /* Mount structure.
0269: * One allocated on every mount. Used to find the super block.
0270: */
0271:
0272: struct mount
0273: {
0274: int m_dev; /* device mounted */
0275: int *m_bufp; /* pointer to superblock */
0276: int *m_inodp; /* pointer to mounted on inode */
0277: } mount[NMOUNT];
0278: /* --------------------------- */
0300:
0301: /* KT-11 addresses and bits */
0302:
0303: #define UISD 0177600 /* first user I-space descriptor register */
0304:
0305: #define UISA 0177640 /* first user I-space address register */
0306:
0307: #define UDSA 0177660 /* first user D-space address register */
0308:
0309:
0310: #define UBMAP 0170200 /* address to access 11/70 UNIBUS map */
0311:
0312: #define RO 02 /* access abilities */
0313: #define WO 04
0314: #define RW 06
0315: #define ED 010 /* extend direction */
0316:
0317: /* --------------------------- */
0318:
0319: int *ka6; /* 11/40 KISA6; 11/45 KDSA6 */
0350: /*
0351: * One structure allocated per active
0352: * process. It contains all data needed
0353: * about the process while the
0354: * process may be swapped out.
0355: * Other per process data (user.h)
0356: * is swapped with the process.
0357: */
0358: struct proc
0359: {
0360: char p_stat;
0361: char p_flag;
0362: char p_pri; /* priority, negative is high */
0363: char p_sig; /* signal number sent to this process */
0364: char p_uid; /* user id, used to direct tty signals */
0365: char p_time; /* resident time for scheduling */
0366: char p_cpu; /* cpu usage for scheduling */
0367: char p_nice; /* nice for scheduling */
0368: int p_ttyp; /* controlling tty */
0369: int p_pid; /* unique process id */
0370: int p_ppid; /* process id of parent */
0371: int p_addr; /* address of swappable image */
0372: int p_size; /* size of swappable image (*64 bytes) */
0373: int p_wchan; /* event process is awaiting */
0374: int *p_textp; /* pointer to text structure */
0375:
0376: } proc[NPROC];
0377: /* --------------------------- */
0378:
0379: /* stat codes */
0380:
0381:
0382: #define SSLEEP 1 /* sleeping on high priority */
0383: #define SWAIT 2 /* sleeping on low priority */
0384: #define SRUN 3 /* running */
0385: #define SIDL 4 /* intermediate state in process creation */
0386: #define SZOMB 5 /* intermediate state in process termination */
0387: #define SSTOP 6 /* process being traced */
0388:
0389: /* flag codes */
0390:
0391: #define SLOAD 01 /* in core */
0392: #define SSYS 02 /* scheduling process */
0393: #define SLOCK 04 /* process cannot be swapped */
0394: #define SSWAP 010 /* process is being swapped out */
0395: #define STRC 020 /* process is being traced */
0396: #define SWTED 040 /* another tracing flag */
0400: /*
0401: * The user structure.
0402: * One allocated per process.
0403: * Contains all per process data
0404: * that doesn't need to be referenced
0405: * while the process is swapped.
0406: * The user block is USIZE*64 bytes
0407: * long; resides at virtual kernel
0408: * loc 140000; contains the system
0409: * stack per user; is cross referenced
0410: * with the proc structure for the
0411: * same process.
0412: */
0413: struct user
0414: {
0415: int u_rsav[2]; /* save r5,r6 when exchanging stacks */
0416: int u_fsav[25]; /* save fp registers */
0417: /* rsav and fsav must be first in structure */
0418: char u_segflg; /* flag for IO; user or kernel space */
0419: char u_error; /* return error code */
0420: char u_uid; /* effective user id */
0421: char u_gid; /* effective group id */
0422: char u_ruid; /* real user id */
0423: char u_rgid; /* real group id */
0424: int u_procp; /* pointer to proc structure */
0425: char *u_base; /* base address for IO */
0426: char *u_count; /* bytes remaining for IO */
0427: char *u_offset[2]; /* offset in file for IO */
0428: int *u_cdir; /* pointer to inode of current directory */
0429: char u_dbuf[DIRSIZ]; /* current pathname component */
0430: char *u_dirp; /* current pointer to inode */
0431: struct { /* current directory entry */
0432: int u_ino;
0433: char u_name[DIRSIZ];
0434: } u_dent;
0435: int *u_pdir; /* inode of parent directory of dirp */
0436: int u_uisa[16]; /* prototype of segmentation addresses */
0437: int u_uisd[16]; /* prototype of segmentation descriptors */
0438: int u_ofile[NOFILE]; /* pointers to file structures of open files */
0439: int u_arg[5]; /* arguments to current system call */
0440: int u_tsize; /* text size (*64) */
0441: int u_dsize; /* data size (*64) */
0442: int u_ssize; /* stack size (*64) */
0443: int u_sep; /* flag for I and D separation */
0444: int u_qsav[2]; /* label variable for quits and interrupts */
0445: int u_ssav[2]; /* label variable for swapping */
0446: int u_signal[NSIG]; /* disposition of signals */
0447: int u_utime; /* this process user time */
0448: int u_stime; /* this process system time */
0449: int u_cutime[2]; /* sum of childs' utimes */
0450: int u_cstime[2]; /* sum of childs' stimes */
0451: int *u_ar0; /* address of users saved R0 */
0452: int u_prof[4]; /* profile arguments */
0453: char u_intflg; /* catch intr from sys */
0454: /* kernel stack per user
0455: * extends from u + USIZE*64
0456: * backward not to reach here
0457: */
0458: } u;
0459: /* --------------------------- */
0460:
0461: /* u_error codes */
0462:
0463:
0464:
0465: #define EFAULT 106
0466: #define EPERM 1
0467: #define ENOENT 2
0468: #define ESRCH 3
0469: #define EINTR 4
0470: #define EIO 5
0471: #define ENXIO 6
0472: #define E2BIG 7
0473: #define ENOEXEC 8
0474: #define EBADF 9
0475: #define ECHILD 10
0476: #define EAGAIN 11
0477: #define ENOMEM 12
0478: #define EACCES 13
0479: #define ENOTBLK 15
0480: #define EBUSY 16
0481: #define EEXIST 17
0482: #define EXDEV 18
0483: #define ENODEV 19
0484: #define ENOTDIR 20
0485: #define EISDIR 21
0486: #define EINVAL 22
0487: #define ENFILE 23
0488: #define EMFILE 24
0489: #define ENOTTY 25
0490: #define ETXTBSY 26
0491: #define EFBIG 27
0492: #define ENOSPC 28
0493: #define ESPIPE 29
0494: #define EROFS 30
0495: #define EMLINK 31
0496: #define EPIPE 32
0500: / low core
0501:
0502: br4 = 200
0503: br5 = 240
0504: br6 = 300
0505: br7 = 340
0506:
0507: . = 0^.
0508: br 1f
0509: 4
0510:
0511: / trap vectors
0512: trap; br7+0. / bus error
0513: trap; br7+1. / illegal instruction
0514: trap; br7+2. / bpt-trace trap
0515: trap; br7+3. / iot trap
0516: trap; br7+4. / power fail
0517: trap; br7+5. / emulator trap
0518: trap; br7+6. / system entry
0519:
0520: . = 40^.
0521: .globl start, dump
0522: 1: jmp start
0523: jmp dump
0524:
0525: . = 60^.
0526: klin; br4
0527: klou; br4
0528:
0529: . = 70^.
0530: pcin; br4
0531: pcou; br4
0532:
0533: . = 100^.
0534: kwlp; br6
0535: kwlp; br6
0536:
0537: . = 114^.
0538: trap; br7+7. / 11/70 parity
0539:
0540: . = 200^.
0541: lpou; br4
0542:
0543: . = 220^.
0544: rkio; br5
0545:
0546: . = 240^.
0547: trap; br7+7. / programmed interrupt
0548: trap; br7+8. / floating point
0549: trap; br7+9. / segmentation violation
0550:
0551: //////////////////////////////////////////////////////
0552: / interface code to C
0553: //////////////////////////////////////////////////////
0554:
0555: .globl call, trap
0556:
0557: .globl _klrint
0558: klin: jsr r0,call; _klrint
0559:
0560: .globl _klxint
0561: klou: jsr r0,call; _klxint
0562:
0563: .globl _pcrint
0564: pcin: jsr r0,call; _pcrint
0565:
0566: .globl _pcpint
0567: pcou: jsr r0,call; _pcpint
0568:
0569: .globl _clock
0570: kwlp: jsr r0,call; _clock
0571:
0572:
0573: .globl _lpintr
0574: lpou: jsr r0,call; _lpintr
0575:
0576: .globl _rkintr
0577: rkio: jsr r0,call; _rkintr
0600: / machine language assist
0601: / for 11/40
0602:
0603: / non-UNIX instructions
0604: mfpi = 6500^tst
0605: mtpi = 6600^tst
0606: wait = 1
0607: rtt = 6
0608: reset = 5
0609:
0610: /* --------------------------- */
0611: .globl start, _end, _edata, _main
0612: start:
0613: bit $1,SSR0
0614: bne start / loop if restart
0615: reset
0616:
0617: / initialize systems segments
0618:
0619: mov $KISA0,r0
0620: mov $KISD0,r1
0621: mov $200,r4
0622: clr r2
0623: mov $6,r3
0624: 1:
0625: mov r2,(r0)+
0626: mov $77406,(r1)+ / 4k rw
0627: add r4,r2
0628: sob r3,1b
0629:
0630: / initialize user segment
0631:
0632: mov $_end+63.,r2
0633: ash $-6,r2
0634: bic $!1777,r2
0635: mov r2,(r0)+ / ksr6 = sysu
0636: mov $usize-1\<8|6,(r1)+
0637:
0638: / initialize io segment
0639: / set up counts on supervisor segments
0640:
0641: mov $IO,(r0)+
0642: mov $77406,(r1)+ / rw 4k
0643:
0644: / get a sp and start segmentation
0645:
0646: mov $_u+[usize*64.],sp
0647: inc SSR0
0648:
0649: / clear bss
0650:
0651: mov $_edata,r0
0652: 1:
0653: clr (r0)+
0654: cmp r0,$_end
0655: blo 1b
0656:
0657: / clear user block
0658:
0659: mov $_u,r0
0660: 1:
0661: clr (r0)+
0662: cmp r0,$_u+[usize*64.]
0663: blo 1b
0664:
0665: / set up previous mode and call main
0666: / on return, enter user mode at 0R
0667:
0668: mov $30000,PS
0669: jsr pc,_main
0670: mov $170000,-(sp)
0671: clr -(sp)
0672: rtt
0673:
0674: /* --------------------------- */
0675: .globl _clearseg
0676: _clearseg:
0677: mov PS,-(sp)
0678: mov UISA0,-(sp)
0679: mov $30340,PS
0680: mov 6(sp),UISA0
0681: mov UISD0,-(sp)
0682: mov $6,UISD0
0683: clr r0
0684: mov $32.,r1
0685: 1:
0686: clr -(sp)
0687: mtpi (r0)+
0688: sob r1,1b
0689: mov (sp)+,UISD0
0690: mov (sp)+,UISA0
0691: mov (sp)+,PS
0692: rts pc
0693:
0694: /* --------------------------- */
0695: .globl _copyseg
0696: _copyseg:
0697: mov PS,-(sp)
0698: mov UISA0,-(sp)
0699: mov UISA1,-(sp)
0700: mov $30340,PS
0701: mov 10(sp),UISA0
0702: mov 12(sp),UISA1
0703: mov UISD0,-(sp)
0704: mov UISD1,-(sp)
0705: mov $6,UISD0
0706: mov $6,UISD1
0707: mov r2,-(sp)
0708: clr r0
0709: mov $8192.,r1
0710: mov $32.,r2
0711: 1:
0712: mfpi (r0)+
0713: mtpi (r1)+
0714: sob r2,1b
0715: mov (sp)+,r2
0716: mov (sp)+,UISD1
0717: mov (sp)+,UISD0
0718: mov (sp)+,UISA1
0719: mov (sp)+,UISA0
0720: mov (sp)+,PS
0721: rts pc
0722:
0723: /* --------------------------- */
0724: .globl _savu, _retu, _aretu
0725: _savu:
0726: bis $340,PS
0727: mov (sp)+,r1
0728: mov (sp),r0
0729: mov sp,(r0)+
0730: mov r5,(r0)+
0731: bic $340,PS
0732: jmp (r1)
0733:
0734: _aretu:
0735: bis $340,PS
0736: mov (sp)+,r1
0737: mov (sp),r0
0738: br 1f
0739:
0740: _retu:
0741: bis $340,PS
0742: mov (sp)+,r1
0743: mov (sp),KISA6
0744: mov $_u,r0
0745: 1:
0746: mov (r0)+,sp
0747: mov (r0)+,r5
0748: bic $340,PS
0749: jmp (r1)
0750:
0751: /* --------------------------- */
0752: .globl trap, call
0753: /* --------------------------- */
0754: .globl _trap
0755: trap:
0756: mov PS,-4(sp)
0757: tst nofault
0758: bne 1f
0759: mov SSR0,ssr
0760: mov SSR2,ssr+4
0761: mov $1,SSR0
0762: jsr r0,call1; _trap
0763: / no return
0764: 1:
0765: mov $1,SSR0
0766: mov nofault,(sp)
0767: rtt
0768:
0769: /* --------------------------- */
0770: .globl _runrun, _swtch
0771: call1:
0772: tst -(sp)
0773: bic $340,PS
0774: br 1f
0775:
0776: call:
0777: mov PS,-(sp)
0778: 1:
0779: mov r1,-(sp)
0780: mfpi sp
0781: mov 4(sp),-(sp)
0782: bic $!37,(sp)
0783: bit $30000,PS
0784: beq 1f
0785: jsr pc,*(r0)+
0786: 2:
0787: bis $340,PS
0788: tstb _runrun
0789: beq 2f
0790: bic $340,PS
0791: jsr pc,_swtch
0792: br 2b
0793: 2:
0794: tst (sp)+
0795: mtpi sp
0796: br 2f
0797: 1:
0798: bis $30000,PS
0799: jsr pc,*(r0)+
0800: cmp (sp)+,(sp)+
0801: 2:
0802: mov (sp)+,r1
0803: tst (sp)+
0804: mov (sp)+,r0
0805: rtt
0806: /* --------------------------- */
0807: .globl _fubyte, _subyte
0808: /* --------------------------- */
0809: .globl _fuibyte, _suibyte
0810: /* --------------------------- */
0811: .globl _fuword, _suword
0812: /* --------------------------- */
0813: .globl _fuiword, _suiword
0814: _fuibyte:
0815: _fubyte:
0816: mov 2(sp),r1
0817: bic $1,r1
0818: jsr pc,gword
0819: cmp r1,2(sp)
0820: beq 1f
0821: swab r0
0822: 1:
0823: bic $!377,r0
0824: rts pc
0825:
0826: _suibyte:
0827: _subyte:
0828: mov 2(sp),r1
0829: bic $1,r1
0830: jsr pc,gword
0831: mov r0,-(sp)
0832: cmp r1,4(sp)
0833: beq 1f
0834: movb 6(sp),1(sp)
0835: br 2f
0836: 1:
0837: movb 6(sp),(sp)
0838: 2:
0839: mov (sp)+,r0
0840: jsr pc,pword
0841: clr r0
0842: rts pc
0843:
0844: _fuiword:
0845: _fuword:
0846: mov 2(sp),r1
0847: fuword:
0848: jsr pc,gword
0849: rts pc
0850:
0851: gword:
0852: mov PS,-(sp)
0853: bis $340,PS
0854: mov nofault,-(sp)
0855: mov $err,nofault
0856: mfpi (r1)
0857: mov (sp)+,r0
0858: br 1f
0859:
0860: _suiword:
0861: _suword:
0862: mov 2(sp),r1
0863: mov 4(sp),r0
0864: suword:
0865: jsr pc,pword
0866: rts pc
0867:
0868: pword:
0869: mov PS,-(sp)
0870: bis $340,PS
0871: mov nofault,-(sp)
0872: mov $err,nofault
0873: mov r0,-(sp)
0874: mtpi (r1)
0875: 1:
0876: mov (sp)+,nofault
0877: mov (sp)+,PS
0878: rts pc
0879:
0880: err:
0881: mov (sp)+,nofault
0882: mov (sp)+,PS
0883: tst (sp)+
0884: mov $-1,r0
0885: rts pc
0886:
0887: /* --------------------------- */
0888: .globl _savfp, _display
0889: _savfp:
0890: _display:
0891: rts pc
0892:
0893: /* --------------------------- */
0894: .globl _incupc
0895: _incupc:
0896: mov r2,-(sp)
0897: mov 6(sp),r2 / base of prof with base,leng,off,scale
0898: mov 4(sp),r0 / pc
0899: sub 4(r2),r0 / offset
0900: clc
0901: ror r0
0902: mul 6(r2),r0 / scale
0903: ashc $-14.,r0
0904: inc r1
0905: bic $1,r1
0906: cmp r1,2(r2) / length
0907: bhis 1f
0908: add (r2),r1 / base
0909: mov nofault,-(sp)
0910: mov $2f,nofault
0911: mfpi (r1)
0912: inc (sp)
0913: mtpi (r1)
0914: br 3f
0915: 2:
0916: clr 6(r2)
0917: 3:
0918: mov (sp)+,nofault
0919: 1:
0920: mov (sp)+,r2
0921: rts pc
0922:
0923: / Character list get/put
0924:
0925: /* --------------------------- */
0926: .globl _getc, _putc
0927: /* --------------------------- */
0928: .globl _cfreelist
0929:
0930: _getc:
0931: mov 2(sp),r1
0932: mov PS,-(sp)
0933: mov r2,-(sp)
0934: bis $340,PS
0935: bic $100,PS / spl 5
0936: mov 2(r1),r2 / first ptr
0937: beq 9f / empty
0938: movb (r2)+,r0 / character
0939: bic $!377,r0
0940: mov r2,2(r1)
0941: dec (r1)+ / count
0942: bne 1f
0943: clr (r1)+
0944: clr (r1)+ / last block
0945: br 2f
0946: 1:
0947: bit $7,r2
0948: bne 3f
0949: mov -10(r2),(r1) / next block
0950: add $2,(r1)
0951: 2:
0952: dec r2
0953: bic $7,r2
0954: mov _cfreelist,(r2)
0955: mov r2,_cfreelist
0956: 3:
0957: mov (sp)+,r2
0958: mov (sp)+,PS
0959: rts pc
0960: 9:
0961: clr 4(r1)
0962: mov $-1,r0
0963: mov (sp)+,r2
0964: mov (sp)+,PS
0965: rts pc
0966:
0967: _putc:
0968: mov 2(sp),r0
0969: mov 4(sp),r1
0970: mov PS,-(sp)
0971: mov r2,-(sp)
0972: mov r3,-(sp)
0973: bis $340,PS
0974: bic $100,PS / spl 5
0975: mov 4(r1),r2 / last ptr
0976: bne 1f
0977: mov _cfreelist,r2
0978: beq 9f
0979: mov (r2),_cfreelist
0980: clr (r2)+
0981: mov r2,2(r1) / first ptr
0982: br 2f
0983: 1:
0984: bit $7,r2
0985: bne 2f
0986: mov _cfreelist,r3
0987: beq 9f
0988: mov (r3),_cfreelist
0989: mov r3,-10(r2)
0990: mov r3,r2
0991: clr (r2)+
0992: 2:
0993: movb r0,(r2)+
0994: mov r2,4(r1)
0995: inc (r1) / count
0996: clr r0
0997: mov (sp)+,r3
0998: mov (sp)+,r2
0999: mov (sp)+,PS
1000: rts pc
1001: 9:
1002: mov pc,r0
1003: mov (sp)+,r3
1004: mov (sp)+,r2
1005: mov (sp)+,PS
1006: rts pc
1007:
1008: /* --------------------------- */
1009: .globl _backup
1010: /* --------------------------- */
1011: .globl _regloc
1012: _backup:
1013: mov 2(sp),ssr+2
1014: mov r2,-(sp)
1015: jsr pc,backup
1016: mov r2,ssr+2
1017: mov (sp)+,r2
1018: movb jflg,r0
1019: bne 2f
1020: mov 2(sp),r0
1021: movb ssr+2,r1
1022: jsr pc,1f
1023: movb ssr+3,r1
1024: jsr pc,1f
1025: movb _regloc+7,r1
1026: asl r1
1027: add r0,r1
1028: mov ssr+4,(r1)
1029: clr r0
1030: 2:
1031: rts pc
1032: 1:
1033: mov r1,-(sp)
1034: asr (sp)
1035: asr (sp)
1036: asr (sp)
1037: bic $!7,r1
1038: movb _regloc(r1),r1
1039: asl r1
1040: add r0,r1
1041: sub (sp)+,(r1)
1042: rts pc
1043:
1044: / hard part
1045: / simulate the ssr2 register missing on 11/40
1046:
1047: backup:
1048: clr r2 / backup register ssr1
1049: mov $1,bflg / clrs jflg
1050: mov ssr+4,r0
1051: jsr pc,fetch
1052: mov r0,r1
1053: ash $-11.,r0
1054: bic $!36,r0
1055: jmp *0f(r0)
1056: 0: t00; t01; t02; t03; t04; t05; t06; t07
1057: t10; t11; t12; t13; t14; t15; t16; t17
1058:
1059: t00:
1060: clrb bflg
1061:
1062: t10:
1063: mov r1,r0
1064: swab r0
1065: bic $!16,r0
1066: jmp *0f(r0)
1067: 0: u0; u1; u2; u3; u4; u5; u6; u7
1068:
1069: u6: / single op, m[tf]pi, sxt, illegal
1070: bit $400,r1
1071: beq u5 / all but m[tf], sxt
1072: bit $200,r1
1073: beq 1f / mfpi
1074: bit $100,r1
1075: bne u5 / sxt
1076:
1077: / simulate mtpi with double (sp)+,dd
1078: bic $4000,r1 / turn instr into (sp)+
1079: br t01
1080:
1081: / simulate mfpi with double ss,-(sp)
1082: 1:
1083: ash $6,r1
1084: bis $46,r1 / -(sp)
1085: br t01
1086:
1087: u4: / jsr
1088: mov r1,r0
1089: jsr pc,setreg / assume no fault
1090: bis $173000,r2 / -2 from sp
1091: rts pc
1092:
1093: t07: / EIS
1094: clrb bflg
1095:
1096: u0: / jmp, swab
1097: u5: / single op
1098: mov r1,r0
1099: br setreg
1100:
1101: t01: / mov
1102: t02: / cmp
1103: t03: / bit
1104: t04: / bic
1105: t05: / bis
1106: t06: / add
1107: t16: / sub
1108: clrb bflg
1109:
1110: t11: / movb
1111: t12: / cmpb
1112: t13: / bitb
1113: t14: / bicb
1114: t15: / bisb
1115: mov r1,r0
1116: ash $-6,r0
1117: jsr pc,setreg
1118: swab r2
1119: mov r1,r0
1120: jsr pc,setreg
1121:
1122: / if delta(dest) is zero,
1123: / no need to fetch source
1124:
1125: bit $370,r2
1126: beq 1f
1127:
1128: / if mode(source) is R,
1129: / no fault is possible
1130:
1131: bit $7000,r1
1132: beq 1f
1133:
1134: / if reg(source) is reg(dest),
1135: / too bad.
1136:
1137: mov r2,-(sp)
1138: bic $174370,(sp)
1139: cmpb 1(sp),(sp)+
1140: beq t17
1141:
1142: / start source cycle
1143: / pick up value of reg
1144:
1145: mov r1,r0
1146: ash $-6,r0
1147: bic $!7,r0
1148: movb _regloc(r0),r0
1149: asl r0
1150: add ssr+2,r0
1151: mov (r0),r0
1152:
1153: / if reg has been incremented,
1154: / must decrement it before fetch
1155:
1156: bit $174000,r2
1157: ble 2f
1158: dec r0
1159: bit $10000,r2
1160: beq 2f
1161: dec r0
1162: 2:
1163:
1164: / if mode is 6,7 fetch and add X(R) to R
1165:
1166: bit $4000,r1
1167: beq 2f
1168: bit $2000,r1
1169: beq 2f
1170: mov r0,-(sp)
1171: mov ssr+4,r0
1172: add $2,r0
1173: jsr pc,fetch
1174: add (sp)+,r0
1175: 2:
1176:
1177: / fetch operand
1178: / if mode is 3,5,7 fetch *
1179:
1180: jsr pc,fetch
1181: bit $1000,r1
1182: beq 1f
1183: bit $6000,r1
1184: bne fetch
1185: 1:
1186: rts pc
1187:
1188: t17: / illegal
1189: u1: / br
1190: u2: / br
1191: u3: / br
1192: u7: / illegal
1193: incb jflg
1194: rts pc
1195:
1196: setreg:
1197: mov r0,-(sp)
1198: bic $!7,r0
1199: bis r0,r2
1200: mov (sp)+,r0
1201: ash $-3,r0
1202: bic $!7,r0
1203: movb 0f(r0),r0
1204: tstb bflg
1205: beq 1f
1206: bit $2,r2
1207: beq 2f
1208: bit $4,r2
1209: beq 2f
1210: 1:
1211: cmp r0,$20
1212: beq 2f
1213: cmp r0,$-20
1214: beq 2f
1215: asl r0
1216: 2:
1217: bisb r0,r2
1218: rts pc
1219:
1220: 0: .byte 0,0,10,20,-10,-20,0,0
1221:
1222: fetch:
1223: bic $1,r0
1224: mov nofault,-(sp)
1225: mov $1f,nofault
1226: mfpi (r0)
1227: mov (sp)+,r0
1228: mov (sp)+,nofault
1229: rts pc
1230:
1231: 1:
1232: mov (sp)+,nofault
1233: clrb r2 / clear out dest on fault
1234: mov $-1,r0
1235: rts pc
1236:
1237: .bss
1238: bflg: .=.+1
1239: jflg: .=.+1
1240: .text
1241:
1242: /* --------------------------- */
1243: .globl _copyin, _copyout
1244: _copyin:
1245: jsr pc,copsu
1246: 1:
1247: mfpi (r0)+
1248: mov (sp)+,(r1)+
1249: sob r2,1b
1250: br 2f
1251:
1252: _copyout:
1253: jsr pc,copsu
1254: 1:
1255: mov (r0)+,-(sp)
1256: mtpi (r1)+
1257: sob r2,1b
1258: 2:
1259: mov (sp)+,nofault
1260: mov (sp)+,r2
1261: clr r0
1262: rts pc
1263:
1264: copsu:
1265: mov (sp)+,r0
1266: mov r2,-(sp)
1267: mov nofault,-(sp)
1268: mov r0,-(sp)
1269: mov 10(sp),r0
1270: mov 12(sp),r1
1271: mov 14(sp),r2
1272: asr r2
1273: mov $1f,nofault
1274: rts pc
1275:
1276: 1:
1277: mov (sp)+,nofault
1278: mov (sp)+,r2
1279: mov $-1,r0
1280: rts pc
1281:
1282: /* --------------------------- */
1283: .globl _idle
1284: _idle:
1285: mov PS,-(sp)
1286: bic $340,PS
1287: wait
1288: mov (sp)+,PS
1289: rts pc
1290:
1291: /* --------------------------- */
1292: .globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7
1293: _spl0:
1294: bic $340,PS
1295: rts pc
1296:
1297: _spl1:
1298: bis $40,PS
1299: bic $300,PS
1300: rts pc
1301:
1302: _spl4:
1303: _spl5:
1304: bis $340,PS
1305: bic $100,PS
1306: rts pc
1307:
1308: _spl6:
1309: bis $340,PS
1310: bic $40,PS
1311: rts pc
1312:
1313: _spl7:
1314: bis $340,PS
1315: rts pc
1316:
1317: /* --------------------------- */
1318: .globl _dpadd
1319: _dpadd:
1320: mov 2(sp),r0
1321: add 4(sp),2(r0)
1322: adc (r0)
1323: rts pc
1324:
1325: /* --------------------------- */
1326: .globl _dpcmp
1327: _dpcmp:
1328: mov 2(sp),r0
1329: mov 4(sp),r1
1330: sub 6(sp),r0
1331: sub 8(sp),r1
1332: sbc r0
1333: bge 1f
1334: cmp r0,$-1
1335: bne 2f
1336: cmp r1,$-512.
1337: bhi 3f
1338: 2:
1339: mov $-512.,r0
1340: rts pc
1341: 1:
1342: bne 2f
1343: cmp r1,$512.
1344: blo 3f
1345: 2:
1346: mov $512.,r1
1347: 3:
1348: mov r1,r0
1349: rts pc
1350:
1351: /* --------------------------- */
1352: .globl dump
1353: dump:
1354: bit $1,SSR0
1355: bne dump
1356:
1357: / save regs r0,r1,r2,r3,r4,r5,r6,KIA6
1358: / starting at abs location 4
1359:
1360: mov r0,4
1361: mov $6,r0
1362: mov r1,(r0)+
1363: mov r2,(r0)+
1364: mov r3,(r0)+
1365: mov r4,(r0)+
1366: mov r5,(r0)+
1367: mov sp,(r0)+
1368: mov KISA6,(r0)+
1369:
1370: / dump all of core (ie to first mt error)
1371: / onto mag tape. (9 track or 7 track 'binary')
1372:
1373: mov $MTC,r0
1374: mov $60004,(r0)+
1375: clr 2(r0)
1376: 1:
1377: mov $-512.,(r0)
1378: inc -(r0)
1379: 2:
1380: tstb (r0)
1381: bge 2b
1382: tst (r0)+
1383: bge 1b
1384: reset
1385:
1386: / end of file and loop
1387:
1388: mov $60007,-(r0)
1389: br .
1390:
1391: /* --------------------------- */
1392: .globl _ldiv
1393: _ldiv:
1394: clr r0
1395: mov 2(sp),r1
1396: div 4(sp),r0
1397: rts pc
1398:
1399: /* --------------------------- */
1400: .globl _lrem
1401: _lrem:
1402: clr r0
1403: mov 2(sp),r1
1404: div 4(sp),r0
1405: mov r1,r0
1406: rts pc
1407:
1408: /* --------------------------- */
1409: .globl _lshift
1410: _lshift:
1411: mov 2(sp),r1
1412: mov (r1)+,r0
1413: mov (r1),r1
1414: ashc 4(sp),r0
1415: mov r1,r0
1416: rts pc
1417:
1418: /* --------------------------- */
1419: .globl csv
1420: csv:
1421: mov r5,r0
1422: mov sp,r5
1423: mov r4,-(sp)
1424: mov r3,-(sp)
1425: mov r2,-(sp)
1426: jsr pc,(r0)
1427:
1428: /* --------------------------- */
1429: .globl cret
1430: cret:
1431: mov r5,r1
1432: mov -(r1),r4
1433: mov -(r1),r3
1434: mov -(r1),r2
1435: mov r5,sp
1436: mov (sp)+,r5
1437: rts pc
1438:
1439: /* --------------------------- */
1440: .globl _u
1441: _u = 140000
1442: usize = 16.
1443:
1444: PS = 177776
1445: SSR0 = 177572
1446: SSR2 = 177576
1447: KISA0 = 172340
1448: KISA6 = 172354
1449: KISD0 = 172300
1450: MTC = 172522
1451: UISA0 = 177640
1452: UISA1 = 177642
1453: UISD0 = 177600
1454: UISD1 = 177602
1455: IO = 7600
1456:
1457: .data
1458: /* --------------------------- */
1459: .globl _ka6, _cputype
1460: _ka6: KISA6
1461: _cputype:40.
1462:
1463: .bss
1464: /* --------------------------- */
1465: .globl nofault, ssr, badtrap
1466: nofault:.=.+2
1467: ssr: .=.+6
1468: badtrap:.=.+2
1500: #
1501: #include "../param.h"
1502: #include "../user.h"
1503: #include "../systm.h"
1504: #include "../proc.h"
1505: #include "../text.h"
1506: #include "../inode.h"
1507: #include "../seg.h"
1508:
1509: #define CLOCK1 0177546
1510: #define CLOCK2 0172540
1511: /*
1512: * Icode is the octal bootstrap
1513: * program executed in user mode
1514: * to bring up the system.
1515: */
1516: int icode[]
1517: {
1518: 0104413, /* sys exec; init; initp */
1519: 0000014,
1520: 0000010,
1521: 0000777, /* br . */
1522: 0000014, /* initp: init; 0 */
1523: 0000000,
1524: 0062457, /* init: </etc/init\0> */
1525: 0061564,
1526: 0064457,
1527: 0064556,
1528: 0000164,
1529: };
1530: /* --------------------------- */
1531:
1532: /*
1533: * Initialization code.
1534: * Called from m40.s or m45.s as
1535: * soon as a stack and segmentation
1536: * have been established.
1537: * Functions:
1538: * clear and free user core
1539: * find which clock is configured
1540: * hand craft 0th process
1541: * call all initialization routines
1542: * fork - process 0 to schedule
1543: * - process 1 execute bootstrap
1544: *
1545: * panic: no clock -- neither clock responds
1546: * loop at loc 6 in user mode -- /etc/init
1547: * cannot be executed.
1548: */
1549:
1550: main()
1551: {
1552: extern schar;
1553: register i, *p;
1554:
1555: /*
1556: * zero and free all of core
1557: */
1558:
1559: updlock = 0;
1560: i = *ka6 + USIZE;
1561: UISD->r[0] = 077406;
1562: for(;;) {
1563: UISA->r[0] = i;
1564: if(fuibyte(0) < 0)
1565: break;
1566: clearseg(i);
1567: maxmem++;
1568: mfree(coremap, 1, i);
1569: i++;
1570: }
1571: if(cputype == 70)
1572: for(i=0; i<62; i=+2) {
1573: UBMAP->r[i] = i<<12;
1574: UBMAP->r[i+1] = 0;
1575: }
1576: printf("mem = %l\n", maxmem*5/16);
1577:
1578:
1579:
1580:
1581:
1582: maxmem = min(maxmem, MAXMEM);
1583: mfree(swapmap, nswap, swplo);
1584:
1585: /*
1586: * set up system process
1587: */
1588:
1589: proc[0].p_addr = *ka6;
1590: proc[0].p_size = USIZE;
1591: proc[0].p_stat = SRUN;
1592: proc[0].p_flag =| SLOAD|SSYS;
1593: u.u_procp = &proc[0];
1594:
1595: /*
1596: * determine clock
1597: */
1598:
1599: UISA->r[7] = ka6[1]; /* io segment */
1600: UISD->r[7] = 077406;
1601: lks = CLOCK1;
1602: if(fuiword(lks) == -1) {
1603: lks = CLOCK2;
1604: if(fuiword(lks) == -1)
1605: panic("no clock");
1606: }
1607:
1608: /*
1609: * set up 'known' i-nodes
1610: */
1611:
1612: *lks = 0115;
1613: cinit();
1614: binit();
1615: iinit();
1616: rootdir = iget(rootdev, ROOTINO);
1617: rootdir->i_flag =& ~ILOCK;
1618: u.u_cdir = iget(rootdev, ROOTINO);
1619: u.u_cdir->i_flag =& ~ILOCK;
1620:
1621: /*
1622: * make init process
1623: * enter scheduling loop
1624: * with system process
1625: */
1626:
1627: if(newproc()) {
1628: expand(USIZE+1);
1629: estabur(0, 1, 0, 0);
1630: copyout(icode, 0, sizeof icode);
1631: /*
1632: * Return goes to loc. 0 of user init
1633: * code just copied out.
1634: */
1635: return;
1636: }
1637: sched();
1638: }
1639: /* --------------------------- */
1640:
1641: /*
1642: * Set up software prototype segmentation
1643: * registers to implement the 3 pseudo
1644: * text,data,stack segment sizes passed
1645: * as arguments.
1646: * The argument sep specifies if the
1647: * text and data+stack segments are to
1648: * be separated.
1649: */
1650: estabur(nt, nd, ns, sep)
1651: {
1652: register a, *ap, *dp;
1653:
1654: if(sep) {
1655: if(cputype == 40)
1656: goto err;
1657: if(nseg(nt) > 8 || nseg(nd)+nseg(ns) > 8)
1658: goto err;
1659: } else
1660: if(nseg(nt)+nseg(nd)+nseg(ns) > 8)
1661: goto err;
1662: if(nt+nd+ns+USIZE > maxmem)
1663: goto err;
1664: a = 0;
1665: ap = &u.u_uisa[0];
1666: dp = &u.u_uisd[0];
1667: while(nt >= 128) {
1668: *dp++ = (127<<8) | RO;
1669: *ap++ = a;
1670: a =+ 128;
1671: nt =- 128;
1672: }
1673: if(nt) {
1674: *dp++ = ((nt-1)<<8) | RO;
1675: *ap++ = a;
1676: }
1677: if(sep)
1678: while(ap < &u.u_uisa[8]) {
1679: *ap++ = 0;
1680: *dp++ = 0;
1681: }
1682: a = USIZE;
1683: while(nd >= 128) {
1684: *dp++ = (127<<8) | RW;
1685: *ap++ = a;
1686: a =+ 128;
1687: nd =- 128;
1688: }
1689: if(nd) {
1690: *dp++ = ((nd-1)<<8) | RW;
1691: *ap++ = a;
1692: a =+ nd;
1693: }
1694: while(ap < &u.u_uisa[8]) {
1695: *dp++ = 0;
1696: *ap++ = 0;
1697: }
1698: if(sep)
1699: while(ap < &u.u_uisa[16]) {
1700: *dp++ = 0;
1701: *ap++ = 0;
1702: }
1703: a =+ ns;
1704: while(ns >= 128) {
1705: a =- 128;
1706: ns =- 128;
1707: *--dp = (127<<8) | RW;
1708: *--ap = a;
1709: }
1710: if(ns) {
1711: *--dp = ((128-ns)<<8) | RW | ED;
1712: *--ap = a-128;
1713: }
1714: if(!sep) {
1715: ap = &u.u_uisa[0];
1716: dp = &u.u_uisa[8];
1717: while(ap < &u.u_uisa[8])
1718: *dp++ = *ap++;
1719: ap = &u.u_uisd[0];
1720: dp = &u.u_uisd[8];
1721: while(ap < &u.u_uisd[8])
1722: *dp++ = *ap++;
1723: }
1724: sureg();
1725: return(0);
1726:
1727: err:
1728: u.u_error = ENOMEM;
1729: return(-1);
1730: }
1731: /* --------------------------- */
1732:
1733: /*
1734: * Load the user hardware segmentation
1735: * registers from the software prototype.
1736: * The software registers must have
1737: * been setup prior by estabur.
1738: */
1739: sureg()
1740: {
1741: register *up, *rp, a;
1742:
1743: a = u.u_procp->p_addr;
1744: up = &u.u_uisa[16];
1745: rp = &UISA->r[16];
1746: if(cputype == 40) {
1747: up =- 8;
1748: rp =- 8;
1749: }
1750: while(rp > &UISA->r[0])
1751: *--rp = *--up + a;
1752: if((up=u.u_procp->p_textp) != NULL)
1753: a =- up->x_caddr;
1754: up = &u.u_uisd[16];
1755: rp = &UISD->r[16];
1756: if(cputype == 40) {
1757: up =- 8;
1758: rp =- 8;
1759: }
1760: while(rp > &UISD->r[0]) {
1761: *--rp = *--up;
1762: if((*rp & WO) == 0)
1763: rp[(UISA-UISD)/2] =- a;
1764: }
1765: }
1766: /* --------------------------- */
1767:
1768: /*
1769: * Return the arg/128 rounded up.
1770: */
1771: nseg(n)
1772: {
1773:
1774: return((n+127)>>7);
1775: }
1776: /* --------------------------- */
1800: #
1801: /*
1802: */
1803:
1804: #include "../param.h"
1805: #include "../user.h"
1806: #include "../proc.h"
1807: #include "../text.h"
1808: #include "../systm.h"
1809: #include "../file.h"
1810: #include "../inode.h"
1811: #include "../buf.h"
1812: /* --------------------------- */
1813: /*
1814: * Create a new process-- the internal version of
1815: * sys fork.
1816: * It returns 1 in the new process.
1817: * How this happens is rather hard to understand.
1818: * The essential fact is that the new process is created
1819: * in such a way that appears to have started executing
1820: * in the same call to newproc as the parent;
1821: * but in fact the code that runs is that of swtch.
1822: * The subtle implication of the returned value of swtch
1823: * (see above) is that this is the value that newproc's
1824: * caller in the new process sees.
1825: */
1826: newproc()
1827: {
1828: int a1, a2;
1829: struct proc *p, *up;
1830: register struct proc *rpp;
1831: register *rip, n;
1832:
1833: p = NULL;
1834: /*
1835: * First, just locate a slot for a process
1836: * and copy the useful info from this process into it.
1837: * The panic "cannot happen" because fork has already
1838: * checked for the existence of a slot.
1839: */
1840: retry:
1841: mpid++;
1842: if(mpid < 0) {
1843: mpid = 0;
1844: goto retry;
1845: }
1846: for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {
1847: if(rpp->p_stat == NULL && p==NULL)
1848: p = rpp;
1849: if (rpp->p_pid==mpid)
1850: goto retry;
1851: }
1852: if ((rpp = p)==NULL)
1853: panic("no procs");
1854:
1855: /*
1856: * make proc entry for new proc
1857: */
1858:
1859: rip = u.u_procp;
1860: up = rip;
1861: rpp->p_stat = SRUN;
1862: rpp->p_flag = SLOAD;
1863: rpp->p_uid = rip->p_uid;
1864: rpp->p_ttyp = rip->p_ttyp;
1865: rpp->p_nice = rip->p_nice;
1866: rpp->p_textp = rip->p_textp;
1867: rpp->p_pid = mpid;
1868: rpp->p_ppid = rip->p_pid;
1869: rpp->p_time = 0;
1870:
1871: /*
1872: * make duplicate entries
1873: * where needed
1874: */
1875:
1876: for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];)
1877: if((rpp = *rip++) != NULL)
1878: rpp->f_count++;
1879: if((rpp=up->p_textp) != NULL) {
1880: rpp->x_count++;
1881: rpp->x_ccount++;
1882: }
1883: u.u_cdir->i_count++;
1884: /*
1885: * Partially simulate the environment
1886: * of the new process so that when it is actually
1887: * created (by copying) it will look right.
1888: */
1889: savu(u.u_rsav);
1890: rpp = p;
1891: u.u_procp = rpp;
1892: rip = up;
1893: n = rip->p_size;
1894: a1 = rip->p_addr;
1895: rpp->p_size = n;
1896: a2 = malloc(coremap, n);
1897: /*
1898: * If there is not enough core for the
1899: * new process, swap out the current process to generate the
1900: * copy.
1901: */
1902: if(a2 == NULL) {
1903: rip->p_stat = SIDL;
1904: rpp->p_addr = a1;
1905: savu(u.u_ssav);
1906: xswap(rpp, 0, 0);
1907: rpp->p_flag =| SSWAP;
1908: rip->p_stat = SRUN;
1909: } else {
1910: /*
1911: * There is core, so just copy.
1912: */
1913: rpp->p_addr = a2;
1914: while(n--)
1915: copyseg(a1++, a2++);
1916: }
1917: u.u_procp = rip;
1918: return(0);
1919: }
1920: /* --------------------------- */
1921:
1922: /*
1923: * The main loop of the scheduling (swapping)
1924: * process.
1925: * The basic idea is:
1926: * see if anyone wants to be swapped in;
1927: * swap out processes until there is room;
1928: * swap him in;
1929: * repeat.
1930: * Although it is not remarkably evident, the basic
1931: * synchronization here is on the runin flag, which is
1932: * slept on and is set once per second by the clock routine.
1933: * Core shuffling therefore takes place once per second.
1934: *
1935: * panic: swap error -- IO error while swapping.
1936: * this is the one panic that should be
1937: * handled in a less drastic way. Its
1938: * very hard.
1939: */
1940: sched()
1941: {
1942: struct proc *p1;
1943: register struct proc *rp;
1944: register a, n;
1945:
1946: /*
1947: * find user to swap in
1948: * of users ready, select one out longest
1949: */
1950:
1951: goto loop;
1952:
1953: sloop:
1954: runin++;
1955: sleep(&runin, PSWP);
1956:
1957: loop:
1958: spl6();
1959: n = -1;
1960: for(rp = &proc[0]; rp < &proc[NPROC]; rp++)
1961: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 &&
1962: rp->p_time > n) {
1963: p1 = rp;
1964: n = rp->p_time;
1965: }
1966: if(n == -1) {
1967: runout++;
1968: sleep(&runout, PSWP);
1969: goto loop;
1970: }
1971:
1972: /*
1973: * see if there is core for that process
1974: */
1975:
1976: spl0();
1977: rp = p1;
1978: a = rp->p_size;
1979: if((rp=rp->p_textp) != NULL)
1980: if(rp->x_ccount == 0)
1981: a =+ rp->x_size;
1982: if((a=malloc(coremap, a)) != NULL)
1983: goto found2;
1984:
1985: /*
1986: * none found,
1987: * look around for easy core
1988: */
1989:
1990: spl6();
1991: for(rp = &proc[0]; rp < &proc[NPROC]; rp++)
1992: if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&
1993: (rp->p_stat == SWAIT || rp->p_stat==SSTOP))
1994: goto found1;
1995:
1996: /*
1997: * no easy core,
1998: * if this process is deserving,
1999: * look around for
2000: * oldest process in core
2001: */
2002:
2003: if(n < 3)
2004: goto sloop;
2005: n = -1;
2006: for(rp = &proc[0]; rp < &proc[NPROC]; rp++)
2007: if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&
2008: (rp->p_stat==SRUN || rp->p_stat==SSLEEP) &&
2009: rp->p_time > n) {
2010: p1 = rp;
2011: n = rp->p_time;
2012: }
2013: if(n < 2)
2014: goto sloop;
2015: rp = p1;
2016:
2017: /*
2018: * swap user out
2019: */
2020:
2021: found1:
2022: spl0();
2023: rp->p_flag =& ~SLOAD;
2024: xswap(rp, 1, 0);
2025: goto loop;
2026:
2027: /*
2028: * swap user in
2029: */
2030:
2031: found2:
2032: if((rp=p1->p_textp) != NULL) {
2033: if(rp->x_ccount == 0) {
2034: if(swap(rp->x_daddr, a, rp->x_size, B_READ))
2035: goto swaper;
2036: rp->x_caddr = a;
2037: a =+ rp->x_size;
2038: }
2039: rp->x_ccount++;
2040: }
2041: rp = p1;
2042: if(swap(rp->p_addr, a, rp->p_size, B_READ))
2043: goto swaper;
2044: mfree(swapmap, (rp->p_size+7)/8, rp->p_addr);
2045: rp->p_addr = a;
2046: rp->p_flag =| SLOAD;
2047: rp->p_time = 0;
2048: goto loop;
2049:
2050: swaper:
2051: panic("swap error");
2052: }
2053: /* --------------------------- */
2054:
2055: /*
2056: * Give up the processor till a wakeup occurs
2057: * on chan, at which time the process
2058: * enters the scheduling queue at priority pri.
2059: * The most important effect of pri is that when
2060: * pri<0 a signal cannot disturb the sleep;
2061: * if pri>=0 signals will be processed.
2062: * Callers of this routine must be prepared for
2063: * premature return, and check that the reason for
2064: * sleeping has gone away.
2065: */
2066: sleep(chan, pri)
2067: {
2068: register *rp, s;
2069:
2070: s = PS->integ;
2071: rp = u.u_procp;
2072: if(pri >= 0) {
2073: if(issig())
2074: goto psig;
2075: spl6();
2076: rp->p_wchan = chan;
2077: rp->p_stat = SWAIT;
2078: rp->p_pri = pri;
2079: spl0();
2080: if(runin != 0) {
2081: runin = 0;
2082: wakeup(&runin);
2083: }
2084: swtch();
2085: if(issig())
2086: goto psig;
2087: } else {
2088: spl6();
2089: rp->p_wchan = chan;
2090: rp->p_stat = SSLEEP;
2091: rp->p_pri = pri;
2092: spl0();
2093: swtch();
2094: }
2095: PS->integ = s;
2096: return;
2097:
2098: /*
2099: * If priority was low (>=0) and
2100: * there has been a signal,
2101: * execute non-local goto to
2102: * the qsav location.
2103: * (see trap1/trap.c)
2104: */
2105: psig:
2106: aretu(u.u_qsav);
2107: }
2108: /* --------------------------- */
2109:
2110: /*
2111: * Wake up all processes sleeping on chan.
2112: */
2113: wakeup(chan)
2114: {
2115: register struct proc *p;
2116: register c, i;
2117:
2118: c = chan;
2119: p = &proc[0];
2120: i = NPROC;
2121: do {
2122: if(p->p_wchan == c) {
2123: setrun(p);
2124: }
2125: p++;
2126: } while(--i);
2127: }
2128: /* --------------------------- */
2129:
2130: /*
2131: * Set the process running;
2132: * arrange for it to be swapped in if necessary.
2133: */
2134: setrun(p)
2135: {
2136: register struct proc *rp;
2137:
2138: rp = p;
2139: rp->p_wchan = 0;
2140: rp->p_stat = SRUN;
2141: if(rp->p_pri < curpri)
2142: runrun++;
2143: if(runout != 0 && (rp->p_flag&SLOAD) == 0) {
2144: runout = 0;
2145: wakeup(&runout);
2146: }
2147: }
2148: /* --------------------------- */
2149:
2150: /*
2151: * Set user priority.
2152: * The rescheduling flag (runrun)
2153: * is set if the priority is higher
2154: * than the currently running process.
2155: */
2156: setpri(up)
2157: {
2158: register *pp, p;
2159:
2160: pp = up;
2161: p = (pp->p_cpu & 0377)/16;
2162: p =+ PUSER + pp->p_nice;
2163: if(p > 127)
2164: p = 127;
2165: if(p > curpri)
2166: runrun++;
2167: pp->p_pri = p;
2168: }
2169: /* --------------------------- */
2170:
2171:
2172: /*
2173: * This routine is called to reschedule the CPU.
2174: * if the calling process is not in RUN state,
2175: * arrangements for it to restart must have
2176: * been made elsewhere, usually by calling via sleep.
2177: */
2178: swtch()
2179: {
2180: static struct proc *p;
2181: register i, n;
2182: register struct proc *rp;
2183:
2184: if(p == NULL)
2185: p = &proc[0];
2186: /*
2187: * Remember stack of caller
2188: */
2189: savu(u.u_rsav);
2190: /*
2191: * Switch to scheduler's stack
2192: */
2193: retu(proc[0].p_addr);
2194:
2195: loop:
2196: runrun = 0;
2197: rp = p;
2198: p = NULL;
2199: n = 128;
2200: /*
2201: * Search for highest-priority runnable process
2202: */
2203: i = NPROC;
2204: do {
2205: rp++;
2206: if(rp >= &proc[NPROC])
2207: rp = &proc[0];
2208: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) {
2209: if(rp->p_pri < n) {
2210: p = rp;
2211: n = rp->p_pri;
2212: }
2213: }
2214: } while(--i);
2215: /*
2216: * If no process is runnable, idle.
2217: */
2218: if(p == NULL) {
2219: p = rp;
2220: idle();
2221: goto loop;
2222: }
2223: rp = p;
2224: curpri = n;
2225: /* Switch to stack of the new process and set up
2226: * his segmentation registers.
2227: */
2228: retu(rp->p_addr);
2229: sureg();
2230: /*
2231: * If the new process paused because it was
2232: * swapped out, set the stack level to the last call
2233: * to savu(u_ssav). This means that the return
2234: * which is executed immediately after the call to aretu
2235: * actually returns from the last routine which did
2236: * the savu.
2237: *
2238: * You are not expected to understand this.
2239: */
2240: if(rp->p_flag&SSWAP) {
2241: rp->p_flag =& ~SSWAP;
2242: aretu(u.u_ssav);
2243: }
2244: /* The value returned here has many subtle implications.
2245: * See the newproc comments.
2246: */
2247: return(1);
2248: }
2249: /* --------------------------- */
2250:
2251: /*
2252: * Change the size of the data+stack regions of the process.
2253: * If the size is shrinking, it's easy-- just release the extra core.
2254: * If it's growing, and there is core, just allocate it
2255: * and copy the image, taking care to reset registers to account
2256: * for the fact that the system's stack has moved.
2257: *
2258: * If there is no core, arrange for the process to be swapped
2259: * out after adjusting the size requirement-- when it comes
2260: * in, enough core will be allocated.
2261: * Because of the ssave and SSWAP flags, control will
2262: * resume after the swap in swtch, which executes the return
2263: * from this stack level.
2264: *
2265: * After the expansion, the caller will take care of copying
2266: * the user's stack towards or away from the data area.
2267: */
2268: expand(newsize)
2269: {
2270: int i, n;
2271: register *p, a1, a2;
2272:
2273: p = u.u_procp;
2274: n = p->p_size;
2275: p->p_size = newsize;
2276: a1 = p->p_addr;
2277: if(n >= newsize) {
2278: mfree(coremap, n-newsize, a1+newsize);
2279: return;
2280: }
2281: savu(u.u_rsav);
2282: a2 = malloc(coremap, newsize);
2283: if(a2 == NULL) {
2284: savu(u.u_ssav);
2285: xswap(p, 1, n);
2286: p->p_flag =| SSWAP;
2287: swtch();
2288: /* no return */
2289: }
2290: p->p_addr = a2;
2291: for(i=0; i<n; i++)
2292: copyseg(a1+i, a2++);
2293: mfree(coremap, n, a1);
2294: retu(p->p_addr);
2295: sureg();
2296: }
2297: /* --------------------------- */
2300: #
2301: /*
2302: */
2303:
2304: #include "../param.h"
2305: #include "../seg.h"
2306: #include "../buf.h"
2307: #include "../conf.h"
2308:
2309: /*
2310: * Address and structure of the
2311: * KL-11 console device registers.
2312: */
2313: struct
2314: {
2315: int rsr;
2316: int rbr;
2317: int xsr;
2318: int xbr;
2319: };
2320: /* --------------------------- */
2321:
2322: /*
2323: * In case console is off,
2324: * panicstr contains argument to last
2325: * call to panic.
2326: */
2327:
2328: char *panicstr;
2329:
2330: /*
2331: * Scaled down version of C Library printf.
2332: * Only %s %l %d (==%l) %o are recognized.
2333: * Used to print diagnostic information
2334: * directly on console tty.
2335: * Since it is not interrupt driven,
2336: * all system activities are pretty much
2337: * suspended.
2338: * Printf should not be used for chit-chat.
2339: */
2340: printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc)
2341: char fmt[];
2342: {
2343: register char *s;
2344: register *adx, c;
2345:
2346: adx = &x1;
2347: loop:
2348: while((c = *fmt++) != '%') {
2349: if(c == '\0')
2350: return;
2351: putchar(c);
2352: }
2353: c = *fmt++;
2354: if(c == 'd' || c == 'l' || c == 'o')
2355: printn(*adx, c=='o'? 8: 10);
2356: if(c == 's') {
2357: s = *adx;
2358: while(c = *s++)
2359: putchar(c);
2360: }
2361: adx++;
2362: goto loop;
2363: }
2364: /* --------------------------- */
2365:
2366: /*
2367: * Print an unsigned integer in base b.
2368: */
2369: printn(n, b)
2370: {
2371: register a;
2372:
2373: if(a = ldiv(n, b))
2374: printn(a, b);
2375: putchar(lrem(n, b) + '0');
2376: }
2377: /* --------------------------- */
2378:
2379: /*
2380: * Print a character on console.
2381: * Attempts to save and restore device
2382: * status.
2383: * If the switches are 0, all
2384: * printing is inhibited.
2385: */
2386: putchar(c)
2387: {
2388: register rc, s;
2389:
2390: rc = c;
2391: if(SW->integ == 0)
2392: return;
2393: while((KL->xsr&0200) == 0)
2394: ;
2395: if(rc == 0)
2396: return;
2397: s = KL->xsr;
2398: KL->xsr = 0;
2399: KL->xbr = rc;
2400: if(rc == '\n') {
2401: putchar('\r');
2402: putchar(0177);
2403: putchar(0177);
2404: }
2405: putchar(0);
2406: KL->xsr = s;
2407: }
2408: /* --------------------------- */
2409:
2410: /*
2411: * Panic is called on unresolvable
2412: * fatal errors.
2413: * It syncs, prints "panic: mesg" and
2414: * then loops.
2415: */
2416: panic(s)
2417: char *s;
2418: {
2419: panicstr = s;
2420: update();
2421: printf("panic: %s\n", s);
2422: for(;;)
2423: idle();
2424: }
2425: /* --------------------------- */
2426:
2427: /*
2428: * prdev prints a warning message of the
2429: * form "mesg on dev x/y".
2430: * x and y are the major and minor parts of
2431: * the device argument.
2432: */
2433: prdev(str, dev)
2434: {
2435:
2436: printf("%s on dev %l/%l\n", str, dev.d_major, dev.d_minor);
2437: }
2438: /* --------------------------- */
2439:
2440: /*
2441: * deverr prints a diagnostic from
2442: * a device driver.
2443: * It prints the device, block number,
2444: * and an octal word (usually some error
2445: * status register) passed as argument.
2446: */
2447: deverror(bp, o1, o2)
2448: int *bp;
2449: {
2450: register *rbp;
2451:
2452: rbp = bp;
2453: prdev("err", rbp->b_dev);
2454: printf("bn%l er%o %o\n", rbp->b_blkno, o1, o2);
2455: }
2456: /* --------------------------- */
2500: #
2501: /*
2502: */
2503:
2504: /*
2505: * Structure of the coremap and swapmap
2506: * arrays. Consists of non-zero count
2507: * and base address of that many
2508: * contiguous units.
2509: * (The coremap unit is 64 bytes,
2510: * the swapmap unit is 512 bytes)
2511: * The addresses are increasing and
2512: * the list is terminated with the
2513: * first zero count.
2514: */
2515: struct map
2516: {
2517: char *m_size;
2518: char *m_addr;
2519: };
2520: /* --------------------------- */
2521:
2522: /*
2523: * Allocate size units from the given
2524: * map. Return the base of the allocated
2525: * space.
2526: * Algorithm is first fit.
2527: */
2528: malloc(mp, size)
2529: struct map *mp;
2530: {
2531: register int a;
2532: register struct map *bp;
2533:
2534: for (bp = mp; bp->m_size; bp++) {
2535: if (bp->m_size >= size) {
2536: a = bp->m_addr;
2537: bp->m_addr =+ size;
2538: if ((bp->m_size =- size) == 0)
2539: do {
2540: bp++;
2541: (bp-1)->m_addr = bp->m_addr;
2542: } while ((bp-1)->m_size = bp->m_size);
2543: return(a);
2544: }
2545: }
2546: return(0);
2547: }
2548: /* --------------------------- */
2549:
2550: /*
2551: * Free the previously allocated space aa
2552: * of size units into the specified map.
2553: * Sort aa into map and combine on
2554: * one or both ends if possible.
2555: */
2556: mfree(mp, size, aa)
2557: struct map *mp;
2558: {
2559: register struct map *bp;
2560: register int t;
2561: register int a;
2562:
2563: a = aa;
2564: for (bp = mp; bp->m_addr<=a && bp->m_size!=0; bp++);
2565: if (bp>mp && (bp-1)->m_addr+(bp-1)->m_size == a) {
2566: (bp-1)->m_size =+ size;
2567: if (a+size == bp->m_addr) {
2568: (bp-1)->m_size =+ bp->m_size;
2569: while (bp->m_size) {
2570: bp++;
2571: (bp-1)->m_addr = bp->m_addr;
2572: (bp-1)->m_size = bp->m_size;
2573: }
2574: }
2575: } else {
2576: if (a+size == bp->m_addr && bp->m_size) {
2577: bp->m_addr =- size;
2578: bp->m_size =+ size;
2579: } else if (size) do {
2580: t = bp->m_addr;
2581: bp->m_addr = a;
2582: a = t;
2583: t = bp->m_size;
2584: bp->m_size = size;
2585: bp++;
2586: } while (size = t);
2587: }
2588: }
2589: /* --------------------------- */
2600: /*
2601: * Location of the users' stored
2602: * registers relative to R0.
2603: * Usage is u.u_ar0[XX].
2604: */
2605: #define R0 (0)
2606: #define R1 (-2)
2607: #define R2 (-9)
2608: #define R3 (-8)
2609: #define R4 (-7)
2610: #define R5 (-6)
2611: #define R6 (-3)
2612: #define R7 (1)
2613: #define RPS (2)
2614:
2615: #define TBIT 020 /* PS trace bit */
2650: #
2651: #include "../param.h"
2652: #include "../systm.h"
2653: #include "../user.h"
2654: #include "../proc.h"
2655: #include "../reg.h"
2656: #include "../seg.h"
2657:
2658: #define EBIT 1 /* user error bit in PS: C-bit */
2659: #define UMODE 0170000 /* user-mode bits in PS word */
2660: #define SETD 0170011 /* SETD instruction */
2661: #define SYS 0104400 /* sys (trap) instruction */
2662: #define USER 020 /* user-mode flag added to dev */
2663:
2664: /*
2665: * structure of the system entry table (sysent.c)
2666: */
2667: struct sysent {
2668: int count; /* argument count */
2669: int (*call)(); /* name of handler */
2670: } sysent[64];
2671: /* --------------------------- */
2672:
2673: /*
2674: * Offsets of the user's registers relative to
2675: * the saved r0. See reg.h
2676: */
2677: char regloc[9]
2678: {
2679: R0, R1, R2, R3, R4, R5, R6, R7, RPS
2680: };
2681: /* --------------------------- */
2682:
2683: /*
2684: * Called from l40.s or l45.s when a processor trap occurs.
2685: * The arguments are the words saved on the system stack
2686: * by the hardware and software during the trap processing.
2687: * Their order is dictated by the hardware and the details
2688: * of C's calling sequence. They are peculiar in that
2689: * this call is not 'by value' and changed user registers
2690: * get copied back on return.
2691: * dev is the kind of trap that occurred.
2692: */
2693: trap(dev, sp, r1, nps, r0, pc, ps)
2694: {
2695: register i, a;
2696: register struct sysent *callp;
2697:
2698: savfp();
2699: if ((ps&UMODE) == UMODE)
2700: dev =| USER;
2701: u.u_ar0 = &r0;
2702: switch(dev) {
2703:
2704: /*
2705: * Trap not expected.
2706: * Usually a kernel mode bus error.
2707: * The numbers printed are used to
2708: * find the hardware PS/PC as follows.
2709: * (all numbers in octal 18 bits)
2710: * address_of_saved_ps =
2711: * (ka6*0100) + aps - 0140000;
2712: * address_of_saved_pc =
2713: * address_of_saved_ps - 2;
2714: */
2715: default:
2716: printf("ka6 = %o\n", *ka6);
2717: printf("aps = %o\n", &ps);
2718: printf("trap type %o\n", dev);
2719: panic("trap");
2720:
2721: case 0+USER: /* bus error */
2722: i = SIGBUS;
2723: break;
2724:
2725: /*
2726: * If illegal instructions are not
2727: * being caught and the offending instruction
2728: * is a SETD, the trap is ignored.
2729: * This is because C produces a SETD at
2730: * the beginning of every program which
2731: * will trap on CPUs without 11/45 FPU.
2732: */
2733: case 1+USER: /* illegal instruction */
2734: if(fuiword(pc-2) == SETD && u.u_signal[SIGINS] == 0)
2735: goto out;
2736: i = SIGINS;
2737: break;
2738:
2739: case 2+USER: /* bpt or trace */
2740: i = SIGTRC;
2741: break;
2742:
2743: case 3+USER: /* iot */
2744: i = SIGIOT;
2745: break;
2746:
2747: case 5+USER: /* emt */
2748: i = SIGEMT;
2749: break;
2750:
2751: case 6+USER: /* sys call */
2752: u.u_error = 0;
2753: ps =& ~EBIT;
2754: callp = &sysent[fuiword(pc-2)&077];
2755: if (callp == sysent) { /* indirect */
2756: a = fuiword(pc);
2757: pc =+ 2;
2758: i = fuword(a);
2759: if ((i & ~077) != SYS)
2760: i = 077; /* illegal */
2761: callp = &sysent[i&077];
2762: for(i=0; i<callp->count; i++)
2763: u.u_arg[i] = fuword(a =+ 2);
2764: } else {
2765: for(i=0; i<callp->count; i++) {
2766: u.u_arg[i] = fuiword(pc);
2767: pc =+ 2;
2768: }
2769: }
2770: u.u_dirp = u.u_arg[0];
2771: trap1(callp->call);
2772: if(u.u_intflg)
2773: u.u_error = EINTR;
2774: if(u.u_error < 100) {
2775: if(u.u_error) {
2776: ps =| EBIT;
2777: r0 = u.u_error;
2778: }
2779: goto out;
2780: }
2781: i = SIGSYS;
2782: break;
2783:
2784: /*
2785: * Since the floating exception is an
2786: * imprecise trap, a user generated
2787: * trap may actually come from kernel
2788: * mode. In this case, a signal is sent
2789: * to the current process to be picked
2790: * up later.
2791: */
2792: case 8: /* floating exception */
2793: psignal(u.u_procp, SIGFPT);
2794: return;
2795:
2796: case 8+USER:
2797: i = SIGFPT;
2798: break;
2799:
2800: /*
2801: * If the user SP is below the stack segment,
2802: * grow the stack automatically.
2803: * This relies on the ability of the hardware
2804: * to restart a half executed instruction.
2805: * On the 11/40 this is not the case and
2806: * the routine backup/l40.s may fail.
2807: * The classic example is on the instruction
2808: * cmp -(sp),-(sp)
2809: */
2810: case 9+USER: /* segmentation exception */
2811: a = sp;
2812: if(backup(u.u_ar0) == 0)
2813: if(grow(a))
2814: goto out;
2815: i = SIGSEG;
2816: break;
2817: }
2818: psignal(u.u_procp, i);
2819:
2820: out:
2821: if(issig())
2822: psig();
2823: setpri(u.u_procp);
2824: }
2825: /* --------------------------- */
2826:
2827: /*
2828: * Call the system-entry routine f (out of the
2829: * sysent table). This is a subroutine for trap, and
2830: * not in-line, because if a signal occurs
2831: * during processing, an (abnormal) return is simulated from
2832: * the last caller to savu(qsav); if this took place
2833: * inside of trap, it wouldn't have a chance to clean up.
2834: *
2835: * If this occurs, the return takes place without
2836: * clearing u_intflg; if it's still set, trap
2837: * marks an error which means that a system
2838: * call (like read on a typewriter) got interrupted
2839: * by a signal.
2840: */
2841: trap1(f)
2842: int (*f)();
2843: {
2844:
2845: u.u_intflg = 1;
2846: savu(u.u_qsav);
2847: (*f)();
2848: u.u_intflg = 0;
2849: }
2850:
2851: /* --------------------------- */
2852: /*
2853: * nonexistent system call-- set fatal error code.
2854: */
2855: nosys()
2856: {
2857: u.u_error = 100;
2858: }
2859: /* --------------------------- */
2860:
2861: /*
2862: * Ignored system call
2863: */
2864: nullsys()
2865: {
2866: }
2867: /* --------------------------- */
2900: #
2901: /*
2902: */
2903:
2904: /*
2905: * This table is the switch used to transfer
2906: * to the appropriate routine for processing a system call.
2907: * Each row contains the number of arguments expected
2908: * and a pointer to the routine.
2909: */
2910: int sysent[]
2911: {
2912: 0, &nullsys, /* 0 = indir */
2913: 0, &rexit, /* 1 = exit */
2914: 0, &fork, /* 2 = fork */
2915: 2, &read, /* 3 = read */
2916: 2, &write, /* 4 = write */
2917: 2, &open, /* 5 = open */
2918: 0, &close, /* 6 = close */
2919: 0, &wait, /* 7 = wait */
2920: 2, &creat, /* 8 = creat */
2921: 2, &link, /* 9 = link */
2922: 1, &unlink, /* 10 = unlink */
2923: 2, &exec, /* 11 = exec */
2924: 1, &chdir, /* 12 = chdir */
2925: 0, &gtime, /* 13 = time */
2926: 3, &mknod, /* 14 = mknod */
2927: 2, &chmod, /* 15 = chmod */
2928: 2, &chown, /* 16 = chown */
2929: 1, &sbreak, /* 17 = break */
2930: 2, &stat, /* 18 = stat */
2931: 2, &seek, /* 19 = seek */
2932: 0, &getpid, /* 20 = getpid */
2933: 3, &smount, /* 21 = mount */
2934: 1, &sumount, /* 22 = umount */
2935: 0, &setuid, /* 23 = setuid */
2936: 0, &getuid, /* 24 = getuid */
2937: 0, &stime, /* 25 = stime */
2938: 3, &ptrace, /* 26 = ptrace */
2939: 0, &nosys, /* 27 = x */
2940: 1, &fstat, /* 28 = fstat */
2941: 0, &nosys, /* 29 = x */
2942: 1, &nullsys, /* 30 = smdate; inoperative */
2943: 1, &stty, /* 31 = stty */
2944: 1, &gtty, /* 32 = gtty */
2945: 0, &nosys, /* 33 = x */
2946: 0, &nice, /* 34 = nice */
2947: 0, &sslep, /* 35 = sleep */
2948: 0, &sync, /* 36 = sync */
2949: 1, &kill, /* 37 = kill */
2950: 0, &getswit, /* 38 = switch */
2951: 0, &nosys, /* 39 = x */
2952: 0, &nosys, /* 40 = x */
2953: 0, &dup, /* 41 = dup */
2954: 0, &pipe, /* 42 = pipe */
2955: 1, &times, /* 43 = times */
2956: 4, &profil, /* 44 = prof */
2957: 0, &nosys, /* 45 = tiu */
2958: 0, &setgid, /* 46 = setgid */
2959: 0, &getgid, /* 47 = getgid */
2960: 2, &ssig, /* 48 = sig */
2961: 0, &nosys, /* 49 = x */
2962: 0, &nosys, /* 50 = x */
2963: 0, &nosys, /* 51 = x */
2964: 0, &nosys, /* 52 = x */
2965: 0, &nosys, /* 53 = x */
2966: 0, &nosys, /* 54 = x */
2967: 0, &nosys, /* 55 = x */
2968: 0, &nosys, /* 56 = x */
2969: 0, &nosys, /* 57 = x */
2970: 0, &nosys, /* 58 = x */
2971: 0, &nosys, /* 59 = x */
2972: 0, &nosys, /* 60 = x */
2973: 0, &nosys, /* 61 = x */
2974: 0, &nosys, /* 62 = x */
2975: 0, &nosys /* 63 = x */
2976: };
2977: /* --------------------------- */
3000: #
3001: #include "../param.h"
3002: #include "../systm.h"
3003: #include "../user.h"
3004: #include "../proc.h"
3005: #include "../buf.h"
3006: #include "../reg.h"
3007: #include "../inode.h"
3008:
3009: /*
3010: * exec system call.
3011: * Because of the fact that an I/O buffer is used
3012: * to store the caller's arguments during exec,
3013: * and more buffers are needed to read in the text file,
3014: * deadly embraces waiting for free buffers are possible.
3015: * Therefore the number of processes simultaneously
3016: * running in exec has to be limited to NEXEC.
3017: */
3018: #define EXPRI -1
3019:
3020: exec()
3021: {
3022: int ap, na, nc, *bp;
3023: int ts, ds, sep;
3024: register c, *ip;
3025: register char *cp;
3026: extern uchar;
3027:
3028: /*
3029: * pick up file names
3030: * and check various modes
3031: * for execute permission
3032: */
3033:
3034: ip = namei(&uchar, 0);
3035: if(ip == NULL)
3036: return;
3037: while(execnt >= NEXEC)
3038: sleep(&execnt, EXPRI);
3039: execnt++;
3040: bp = getblk(NODEV);
3041: if(access(ip, IEXEC) || (ip->i_mode&IFMT)!=0)
3042: goto bad;
3043:
3044: /*
3045: * pack up arguments into
3046: * allocated disk buffer
3047: */
3048:
3049: cp = bp->b_addr;
3050: na = 0;
3051: nc = 0;
3052: while(ap = fuword(u.u_arg[1])) {
3053: na++;
3054: if(ap == -1)
3055: goto bad;
3056: u.u_arg[1] =+ 2;
3057: for(;;) {
3058: c = fubyte(ap++);
3059: if(c == -1)
3060: goto bad;
3061: *cp++ = c;
3062: nc++;
3063: if(nc > 510) {
3064: u.u_error = E2BIG;
3065: goto bad;
3066: }
3067: if(c == 0)
3068: break;
3069: }
3070: }
3071: if((nc&1) != 0) {
3072: *cp++ = 0;
3073: nc++;
3074: }
3075:
3076: /* read in first 8 bytes
3077: * of file for segment
3078: * sizes:
3079: * w0 = 407/410/411 (410 implies RO text) (411 implies sep ID)
3080: * w1 = text size
3081: * w2 = data size
3082: * w3 = bss size
3083: */
3084:
3085: u.u_base = &u.u_arg[0];
3086: u.u_count = 8;
3087: u.u_offset[1] = 0;
3088: u.u_offset[0] = 0;
3089: u.u_segflg = 1;
3090: readi(ip);
3091: u.u_segflg = 0;
3092: if(u.u_error)
3093: goto bad;
3094: sep = 0;
3095: if(u.u_arg[0] == 0407) {
3096: u.u_arg[2] =+ u.u_arg[1];
3097: u.u_arg[1] = 0;
3098: } else
3099: if(u.u_arg[0] == 0411)
3100: sep++; else
3101: if(u.u_arg[0] != 0410) {
3102: u.u_error = ENOEXEC;
3103: goto bad;
3104: }
3105: if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
3106: u.u_error = ETXTBSY;
3107: goto bad;
3108: }
3109:
3110: /*
3111: * find text and data sizes
3112: * try them out for possible
3113: * exceed of max sizes
3114: */
3115:
3116: ts = ((u.u_arg[1]+63)>>6) & 01777;
3117: ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777;
3118: if(estabur(ts, ds, SSIZE, sep))
3119: goto bad;
3120:
3121: /*
3122: * allocate and clear core
3123: * at this point, committed
3124: * to the new image
3125: */
3126:
3127: u.u_prof[3] = 0;
3128: xfree();
3129: expand(USIZE);
3130: xalloc(ip);
3131: c = USIZE+ds+SSIZE;
3132: expand(c);
3133: while(--c >= USIZE)
3134: clearseg(u.u_procp->p_addr+c);
3135:
3136: /* read in data segment */
3137:
3138: estabur(0, ds, 0, 0);
3139: u.u_base = 0;
3140: u.u_offset[1] = 020+u.u_arg[1];
3141: u.u_count = u.u_arg[2];
3142: readi(ip);
3143:
3144: /*
3145: * initialize stack segment
3146: */
3147:
3148: u.u_tsize = ts;
3149: u.u_dsize = ds;
3150: u.u_ssize = SSIZE;
3151: u.u_sep = sep;
3152: estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep);
3153: cp = bp->b_addr;
3154: ap = -nc - na*2 - 4;
3155: u.u_ar0[R6] = ap;
3156: suword(ap, na);
3157: c = -nc;
3158: while(na--) {
3159: suword(ap=+2, c);
3160: do
3161: subyte(c++, *cp);
3162: while(*cp++);
3163: }
3164: suword(ap+2, -1);
3165:
3166: /*
3167: * set SUID/SGID protections, if no tracing
3168: */
3169:
3170: if ((u.u_procp->p_flag&STRC)==0) {
3171: if(ip->i_mode&ISUID)
3172: if(u.u_uid != 0) {
3173: u.u_uid = ip->i_uid;
3174: u.u_procp->p_uid = ip->i_uid;
3175: }
3176: if(ip->i_mode&ISGID)
3177: u.u_gid = ip->i_gid;
3178: }
3179:
3180: /* clear sigs, regs and return */
3181:
3182: c = ip;
3183: for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++)
3184: if((*ip & 1) == 0)
3185: *ip = 0;
3186: for(cp = &regloc[0]; cp < &regloc[6];)
3187: u.u_ar0[*cp++] = 0;
3188: u.u_ar0[R7] = 0;
3189: for(ip = &u.u_fsav[0]; ip < &u.u_fsav[25];)
3190: *ip++ = 0;
3191: ip = c;
3192:
3193: bad:
3194: iput(ip);
3195: brelse(bp);
3196: if(execnt >= NEXEC)
3197: wakeup(&execnt);
3198: execnt--;
3199: }
3200: /* --------------------------- */
3201:
3202: /* exit system call:
3203: * pass back caller's r0
3204: */
3205: rexit()
3206: {
3207:
3208: u.u_arg[0] = u.u_ar0[R0] << 8;
3209: exit();
3210: }
3211: /* --------------------------- */
3212:
3213: /* Release resources.
3214: * Save u. area for parent to look at.
3215: * Enter zombie state.
3216: * Wake up parent and init processes,
3217: * and dispose of children.
3218: */
3219: exit()
3220: {
3221: register int *q, a;
3222: register struct proc *p;
3223:
3224: u.u_procp->p_flag =& ~STRC;
3225: for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];)
3226: *q++ = 1;
3227: for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++)
3228: if(a = *q) {
3229: *q = NULL;
3230: closef(a);
3231: }
3232: iput(u.u_cdir);
3233: xfree();
3234: a = malloc(swapmap, 1);
3235: if(a == NULL)
3236: panic("out of swap");
3237: p = getblk(swapdev, a);
3238: bcopy(&u, p->b_addr, 256);
3239: bwrite(p);