|
|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 133680 (0x20a30)
Types: TextFile
Notes: flxfile
Names: »s18100:1.tsos main «, »tsos main «
└─⟦b9333063a⟧ Bits:30009129 PD8100/1/6.0 - OPERATING SYSTEM MISP/TS - 1 OF 2
└─⟦bfa983fec⟧
└─⟦this⟧ »s18100:1.tsos main «
! *** tsos ***
;
;
; swopping online system for execution of a number of interactive processes
; in the same piece of core
;
; release 3.0 mar. 1982 knud christensen, edith rosenberg, flemming biggas
; release 3.1 aug. 1982 flemming biggas
; release 3.2 apr. 1983 flemming biggas
; release 3.3 aug. 1984 flemming biggas
; release 4.0 aug. 1985 flemming biggas (mp release).
!
onlinesystem
begin
!fp.no;
!branch 1,2;
!sections 35;
procedure prepare(.w3.);
comment prepare process to be activated;
procedure waitevent(.w3.;w0;w1;w2);
comment call: w0 irrelevant
w1 irrelevant
w2 irrelevant
return: w0 event kind
w1 abs ref userentry
w2 abs ref eventbuffer
;
procedure unintelligible(.w3.;w1);
comment call: w1 abs ref userentry
return: all registers unchanged
;
procedure send_primo(.w3.;w1;w2);
comment call: w1 abs ref userentry
w2 abs ref message sent to pseudo process primo
return: w1 abs ref userentry
w2 abs ref message sent to primo (real process)
w3 old w2 (from call)
;
procedure primess(.w3.);
procedure send(.w3.;w0;w1;w2);
comment call: w0 kind of event to be send
w1 abs ref userentry
w2 first word of message or answer
return: -- all registers unchanged
;
procedure link(.w3.;w1;w2);
comment call: w1 abs ref userentry to be linked
w2 abs ref userentry after which to link w1
return: w1 unchanged
w2 unchanged
;
procedure swop(.w3.;w1);
comment call: w1 abs ref userentry of process to be swopped in
return: w1 unchanged
;
procedure copy(.w3.;w0;w1;w2);
comment call: w0 no of bytes to copy
w1 abs from
w2 abs to
return: -- all registers unchanged
;
procedure startstop(.w3.;w0;w1);
comment call: w0 boolean stop or start process
w1 abs ref userentry of process to start-stop
return: -- all registers unchanged
;
procedure transport(.w2.;w1;w3);
comment call: w1 abs ref message to be send
w3 abs ref area name
return: -- all registers unchanged
;
procedure parentmess(.w3.;w1;w2);
comment call: w1 abs ref userentry of sending process
w2 abs ref message buffer
return: -- all registers unchanged
;
procedure syscommand(.w3.;w1);
comment call: w1 abs ref userentry of commanding user
return: -- all registers unchanged
;
procedure scancat(.w3.;w0;w1;w2);
comment call: w1 abs ref process name
w2 abs ref terminal name or zero
return: w0 result -3 = usercat reservation error
-2 = terminal unknown
-1 = process unknown
>=0 = ok (catalog segm.no)
w1 abs ref process description
w2 abs ref terminal description or zero
;
procedure break(.w3.;w1);
comment call: w1 abs ref userentry to break
return: -- all registers unchanged
;
procedure clean(.w3.;w1);
comment call: w1 abs ref userentry
return: -- all registers unchanged
;
procedure compare(.w3.;w0;w1;w2);
comment call: w0 no of bytes to compare
w1 abs 1.string
w2 abs 2.string
return: w0 = 0 the bytes are equal
;
procedure nextchar(.w3.;word stp;w0;w1;w2);
comment call: w0 irrelevant
w1 partial word
w2 abs ref next input word
w3 return
stp abs ref word next to last input word
return: w0 next character
w1 partial word
w2 abs ref next input word
;
procedure init(.w3.);
comment call: -- all registers irrelevant
return: -- all registers destroyed
;
procedure opmess(.w3.;w1;w2);
comment call: w1 abs ref message,
w2 abs ref sender process description
;
procedure logout(.w3.;w1);
comment call: w1 abs ref userentry
return: -- jumps directly to main program
;
procedure outtext(.w3.;w0;w1;w2);
comment call: w0 format pattern:
bits 21-23: type of message
0 = normal
1 = error
2 = warning
3 = pending
4 = normal
bit 20: time (yes or no)
bit 19: system name (yes or no)
bit 18: job name (yes or no)
w1 abs ref userentry
w2 text number
return: -- all registers unchanged
;
procedure outtime(.w3.;w2);
comment call: w2 abs ref buffer
return: -- all registers unchanged
;
procedure calldev(.w3.;w1);
comment call: w1 abs ref string1
return: w1 abs ref error message or zero
;
procedure testout(.w3.;w0;w1;w2);
comment call: w0 length of testrecord
w1 abs ref first word of record
w2 kind of testrecord
return: w0 destroyed
w1 unchanged
w2 unchanged
;
\f
label continue,interrupt,initialize,activate,repeatmaybe,regrettimer,timeout,
stopcoreuser,discfault,semibusy,emptyanswer,actioncase,messwait, a_ready;
record name (double name1,name2);
record answer (word status,bytes,characters);
record message (ref nextmess,lastmess,receiver,sender;
byte operation,mode;
ref mbfst,mblst;
word segmno;
ref mbilast);
record userentry (ref nextuser,prevuser,buffer,
messgot,messsend,procbuf1,peripheral,internal,primdevi;
word swopsegm,class,prio;
byte state,state2,buflength,intervent,primio,bufrel;
word statusinf,currlocid,procsize;
text(14) pr_in,pr_out);
record termdescr
(text(11) extid;
word intid;
text(11) userkey;
byte tbufs,ttimers;
array(1:6) tfill of byte);
record procdescr
(byte procbuffers,procareas;
word procsb1,procsb2,
procub1,procub2,
procmb1,procmb2;
text(11) ppass;
word pminsize,pmaxsize;
array(1:10) pfill of byte;
text(59) procfp;
array(1:12) procdiscs of record procdisc
(text(11) procdiscname;
array(1:8) procdiscclaim of word
)
);
record prindex (text(11) prname;
word prsegmno);
incode
ref activqfst,activqlst,
batchqfst,batchqlst,
waitqfst,waitqlst,
coreuser:=0,timermess:=0,
firstuser,lastuser;
word maxbuf,minprio,maxtestsegm,syscond,passmode,batchclass:=-8000000;
word register0,register1,register2,register3,exception:=0,ic;
word ownproc;
word basereg;
text(14) procname,timer:="clock";
text(2) att:="
>"; word timeunit:=0,interval;
word micunit:=2;
double micinterval:=600;
byte testop:=5,testmode:=0;
ref testbfst,testblst,testsegm:=0;
ref fstcore,topcore;
ref baseevent:=0,mainconsref,mictimer,psmess;
double starttime,startbase;
byte relintrpt,reldump,idsize,sysstate:=0;
byte childpr,childpk,timerloss,cyclegain,inputgain,freebufs;
text(11) operator:= "'255'";
text (14) tstarea,swname,fpcode,cleartemp,usercat,t_mdul,p_mdul,p_pseudo;
byte fp_rel,cleart_rel;
byte faultop:=2,faultmode:=1;
text(20) faulttext:="***fault";
begin
\f
comment the following piece of code is after initialization used as
buffer for wait answer, and as interrupt routine
in case of internal interrupt or !test
;
ownproc:= w3; ! save own process description address !
interrupt:
w3:=address(interrupt)+2;
w0:=0;
monitor(0); comment set interrupt address;
mainconsref:=w2;
goto initialize;
w1+0;
w1+0;
w1+0;
testout(.w3.,w0:=16,w1:=address(interrupt)+2,w2:=7);
!get 2;
if w0 <> 1 then goto discfault;
opmess(.w3.,w1:=address(faultop),w2:=ownproc);
initialize:
!get 2;
if w0 <> 1 then goto discfault;
init(.w3.);
\f
comment the central logic of the onlineadministrator is this:
a) wait for an event from a terminal, from an internal process
or from the timer
b) take some action corresponding to the kind of the event arrived
- this action may include stopping the running process
c) if the running process is stopped then select new process for
activation (if anyone is ready) and swop
d) take some action corresponding to the state of the process
that is selected for activation (copy input from buffer into
the process etc)
e) start the process, send a message to timer and goto a.
;
continue:
waitevent(.w3.,w0,w1,w2);
userentry:=w1;
message:=w2;
\f
comment actions corresponding to the kind of the event arrived:
1) input message from internal process -
the process is stopped and the input message is sent to the terminal
if it is ready, otherwize the input message is linked to the user-
description, waiting to be sent, when the terminal becomes ready
if the priority class is negative then it is increased
2) output message from internal process -
if the terminal is ready (there is room in the terminal buffer),
the output is copied from the process into the buffer, an answer
is sent to the process, and an output message is sent to the ter-
minal
if the terminal is not ready, the internal process is stopped and
it is given an answer, telling that no bytes are transferred, then
at restart, the process will repeat the outputmessage
3) parent message from internal process -
finis: the process is removed, and the userdescription cleared
break: the process is stopped, and prepared for loading with new abs program
*** any other parent message is rejected for the moment
4) attention from known terminal -
treated as an interrupt. the process is stopped and an inputmessage
is send to the terminal asking for a system command
5) answer from known terminal -
input answer: the process is prepared for restart
output answer: if the process is waiting then it is prepared for
restart otherwize nothing is to be done
6) attention from unknown terminal -
the terminal is linked to a free userdescription and an input is send
to the terminal asking for the users identification
7) answer from timer -
the process running in core has used its time-slice and therefore
it is stopped to make room for other users
the priority class of this process is decreased
8) message from a bastard
at s-replacement sos may take over some unknown children (bastards)
parent messages from these children are written on the main console
9) message to a pseudo process called tem
10) message to be send later
11) message to a pseudo process called primo
12) message to be send to primo later
;
\f
actioncase:
case w3:=w0 of
begin
! action 1 !
begin comment input message from internal process;
if w3:=syscond onemask 2'010 then
if w3:=(w1).intervent = -1 then goto timeout;
if w3:=(w1).state<0 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end else
if w3>0 then
begin
(w1).state:=w0:=5;
end else
begin
(w1).procbuf1:= w0:= (w2).mbfst;
(w1).state:= w0:= 1;
if w0:=(w1).state2=-1 then
begin ! fp command ready !
if w1=coreuser then
begin
if w2:=timermess<>0 then
begin
monitor(82); ! regret !
w2:= 0;
timermess:= w2;
end;
end;
(w1).state2:= w0:= 0;
if w0:= (w1).intervent=0 then goto repeatmaybe else
(w1).intervent:= w0:= 0; ! no fp command in buffer at restart after break !
end;
w3:= (w2).mblst;
w3-w0+2;
if w3>maxbuf then w3:= maxbuf;
(w1).buflength:= w3;
send(.w3.,w0:=0,w1,w2:=12288);
end;
link(.w3.,w1,w2:=address(waitqfst));
startstop(.w3.,w0:=0,w1);
end;
\f
! action 2 !
begin comment output message from internal process;
if w0:=(w1).state<0 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
goto continue;
end else
if w0=0 then
begin
if w1 = coreuser then
begin
w3:=(w1).internal+11;
w3:=(w3).byte;
if w3 and 2'10100000=2'10100000 then ! stopped !
begin
(w1).state:=w0:=6;
startstop(.w3.,w0:=1,w1);
end;
idsize:=w0:=(w1).primio;
w0:=(w2).mblst-(w2).mbfst+2;
if w0>=maxbuf then w0:=maxbuf-idsize;
(w1).buflength:=w0+idsize;
w3:=w0-idsize-2;
w1:=(w1).buffer+idsize;
w3+w1;
monitor(70); ! copy !
if w0<>0 then ! unintelligible !
unintelligible(.w3.,w1:=userentry)
else
begin
w0:=w1;
w1:=userentry;
w2:=(w1).buffer;
if w3:=idsize > 0 then
(w2).word:=w3:=(w1).currlocid;
testout(.w3.,w0+idsize,w1:=w2,w2:=0);
send(.w3.,w0:=0,w1:=userentry,w2:=20480+message.mode);
(w1).buflength:= w0:= (w1).buflength-idsize;
send(.w3.,w0:=1,w1,w2:=0);
if w0:=6=(w3:=(w1).state) then startstop(.w3.,w0:=0,w1);
(w1).state:=w0:=2;
end; ! message ok !
if w0:=6=(w3:=(w1).state) then ! stop it again !
begin
(w1).state:=w0:=0;
startstop(.w3.,w0:=0,w1)
end
end else
begin
emptyanswer:
(w1).buflength:=w0:=0;
(w1).state:=w0;
send(.w3.,w0:=1,w1,w2:=0);
goto a_ready;
end;
if w0:=timermess <> 0 then goto continue;
end else goto emptyanswer;
end;
\f
! action 3 !
begin comment parent message from internal process;
if w0:=(w1).state<0 then
begin
send(.w3.,w0:=2,w1,w2:=0);
goto continue;
end;
if w1:=coreuser > 0 then startstop(.w3.,w0:=0,w1);
swop(.w3.,w1:=0);
!get 2;
if w0 <> 1 then goto discfault;
parentmess(.w3.,w1:=userentry,w2:=message);
end;
! action 4 !
begin comment attention from known terminal;
send(.w3.,w0:=1,w1,w2:=0);
if w0:=(w1).state2>0 then goto continue;
if w0:=(w1).state < 0 then goto continue;
(w1).state:=w0:=-1;
startstop(.w3.,w0:=0,w1);
link(.w3.,w1,w2:=address(waitqfst));
w2:=(w1).buffer;
(w1).buflength:=w0:=2;
copy(.w3.,w0,w1:=address(att),w2);
testout(.w3.,w0,w1,w2:=0);
send(.w3.,w0:=0,w1:=userentry,w2:=20480);
(w1).buflength:=w0:=maxbuf;
send(.w3.,w0:=0,w1,w2:=12288);
if w1 = coreuser then goto regrettimer else goto continue;
end;
\f
! action 5 !
begin comment answer from known terminal;
w2:=address(interrupt);
case w3:=(w1).state+4 of
begin
! -3 ! begin comment invisible password;
w3:= (w1).messsend; ! result !
if w3 or (w2).status or (w2).bytes = 1 then
begin ! repeat invisible input, if normal answer and
bytes transferred = 0 !
(w1).buflength:= w0:= maxbuf - (w1).bufrel;
w0:= (w1).bufrel;
-(w0);
send (.w3., w0, w1, w2:=12288+passmode);
goto continue;
end;
end;
! -2 ! begin comment login information;
goto repeatmaybe;
end;
! -1 ! begin comment system command;
goto repeatmaybe;
end;
! 0 ! begin comment communication via pseudo process;
w0:=(w1).messsend;
w2:=(w1).messgot;
if w2 > 10 then
if w3:=(w2).operation extract 2 <> 3 then
begin
(w1).messgot:=w0;
w1:=address(interrupt);
monitor(22); ! send answer !
testout(.w3.,w0:=16,w1,w2:=61);
end;
end;
! 1 ! begin comment waiting for input answer;
(w1).currlocid:= w0:= (w3:=(w1).buffer).word;
repeatmaybe:
w3:=(w1).messsend; comment w3 := result;
if w3 or (w2).status or (w2).bytes = 1 then
begin comment repeat input if normal answer, bytes trans-
ferred = 0;
(w1).buflength:=w0:=maxbuf;
send(.w3.,w0:=0,w1,w2:=12288);
goto continue;
end;
end;
! 2 ! begin comment waiting for output answer;
(w1).state:=w0:=0;
goto continue;
end;
! 3 ! begin comment waiting for load with new abs program - state not possible here;
end;
! 4 ! begin comment suspended because of output buffer full;
(w1).state:=w0:=0;
end;
! 5 ! begin comment message waiting to be send;
link(.w3.,w1,w2:=address(activqfst));
message:=w2:=(w1).messgot;
(w1).state:=w0:=0;
if w3:=(w2).receiver+ownproc <> 0 then w0:=9 else
if w3:=(w2).operation = 3 then w0:=1 else
if w3 = 5 then w0:=2 else w0:=3;
goto actioncase;
end;
! 6 ! begin ! waiting answer from primo !
end;
! 7 ! begin ! message waiting to be send to primo !
link(.w3.,w1,w2:=address(activqfst));
message:=w2:=(w1).messgot;
(w1).state:=w0:=0;
w0:=11;
goto actioncase
end;
end;
link(.w3.,w1:=userentry,w2:=address(activqfst));
a_ready:
if w0:=timermess<>0 then
begin
if w0:=coreuser.class+timerloss < minprio
then goto stopcoreuser
else goto continue;
end;
end;
\f
! action 6 !
begin comment attention from unknown terminal;
send(.w3.,w0:=1,w1,w2:=0);
(w1).state:=w0:=-2;
(w1).buflength:=w0:=2;
w2:=(w1).buffer;
copy(.w3.,w0,w1:=address(att),w2);
testout(.w3.,w0,w1,w2:=0);
send(.w3.,w0:=0,w1:=userentry,w2:=20480);
(w1).buflength:=w0:=maxbuf;
send(.w3.,w0:=0,w1,w2:=12288);
goto continue;
end;
! action 7 !
begin comment answer from timer;
stopcoreuser:
userentry:=w1:=coreuser;
startstop(.w3.,w0:=0,w1);
if w0:=(w1).class+timerloss < batchclass then (w1).prio:=w0:=0 ! batch !
else
begin ! go/run-jobs !
link(.w3.,w1,w2:=address(activqfst));
(w1).class:=w0:=(w1).class-timerloss;
(w1).prio:=w0;
if w3:=syscond onemask 2'001 then
if w0 < minprio then
begin comment break process;
timeout:
swop(.w3.,w1:=0);
!get 2;
if w0 <> 1 then goto discfault;
break(.w3.,w1:=userentry);
(w1).intervent:=w0:=5;
end;
end;
end;
! action 8 !
begin comment parent message from a bastard;
swop(.w3.,w1:=0);
!get 2;
if w0 <> 1 then goto discfault;
opmess(.w3.,w1:=address((w2).operation),w2:=(w2).sender);
end;
\f
! action 9 !
begin comment message to a pseudo process;
if w1:=(w2).receiver < 0 then -(w1);
copy(.w3.,w0:=8,w1+2,w2:=address(procname));
copy(.w3.,w0:=16,w1:=message+8,w2:=lastuser);
w2:=message;
if w0:=(w2).operation onemask 1 then
begin ! io - use sos buffer !
w1:=userentry;
if w1 <> coreuser then goto emptyanswer;
w3:=lastuser-8;
(w3).mode:=w0:=(w2).mode extract 6;
(w3).mbfst:=w0:=(w1).buffer;
w0:=(w2).mblst-(w2).mbfst+2;
if w0 > maxbuf then w0:=maxbuf;
(w1).buflength:=w0;
(w3).mblst:=w0+(w3).mbfst-2;
(w1).procbuf1:=w0:=(w2).mbfst;
if w0:=(w2).operation <> 3 then
begin ! some kind of output assumed !
if w0:=(w2).mode onemask 8'100 then
begin
(w3).mblst:=w2:=(w3).mblst+2;
(w2:=(w1).buffer).word:=w3:=(w1).currlocid;
w2+2;
end else w2:=(w1).buffer;
copy(.w3.,w0:=(w1).buflength,w1:=(w1).procbuf1,w2);
testout(.w3.,w0,w1,w2:=0);
send(.w3.,w0:=1,w1:=userentry,w2:=0);
end;
end;
begin ! message to tem !
copy(.w3.,w0:=6,w1:=userentry.internal+2,w2:=address(procname)+2);
w3:=address(procname);
mictimer:=w3;
if w0:=message.operation >= 90 then
if w0 < 100 then
begin ! message concerning a pool !
w0:=0;
mictimer:=w0;
baseevent:=w0;
copy(.w3.,w0:=8,w1:=address(procname),w2:=lastuser+8);
w3:=address(t_mdul);
end;
end;
w1:=lastuser;
monitor(16); ! send message !
userentry.messsend:=w2;
psmess:=w2;
if w0:=mictimer > 0 then
begin
w3:=address(timer);
w1:=address(micunit);
monitor(16); ! send timer message !
mictimer:=w2;
end;
w2:=baseevent;
semibusy:
monitor(24); ! wait next event !
if w2 = psmess then
begin
w1:=lastuser;
monitor(18); ! wait answer !
w3:=userentry;
(w3).messsend:=w0;
(w3).statusinf:=w0:=(w1).word;
w2:=(w3).messgot;
if w0:=(w2).operation extract 2 = 3 then
begin
copy(.w3.,w0:=(w1).bytes,w1:=userentry.buffer,w2:=userentry.procbuf1);
testout(.w3.,w0,w1,w2:=0);
w3:=userentry;
userentry.currlocid:=w0:=(w1).word;
w0:=(w3).messsend;
w1:=lastuser;
w2:=(w3).messgot;
end else w0:=(w3).messsend;
if w2 > 10 then
begin
if w3:=(w3).statusinf or w0 or 8'10200001 <> 8'10200001 then
if w3:=(w2).operation onemask 1 then
begin
swop(.w3.,w1:=0);
!get 2;
if w0 <> 1 then goto discfault;
logout(.w3.,w1:=userentry);
end;
userentry.messgot:=w0;
monitor(22); ! send answer !
testout(.w3.,w0:=16,w1,w2:=61);
end;
if w2:=mictimer > 0 then monitor(82); ! regret timer message !
if w0:=timermess <> 0 then goto continue;
end else
if w2 = mictimer then
begin
startstop(.w3.,w0:=0,w1:=userentry);
link(.w3.,w1,w2:=address(waitqfst));
end else goto semibusy;
end;
\f
! action 10 !
begin comment wait for previous message to be answered;
w2:=5;
messwait:
if w0:=(w1).state < 0 then
begin
(w1).buflength:=w0:=0;
send(.w3.,w0:=1,w1,w2:=8'200000);
end else
begin
startstop(.w3.,w0:=0,w1);
(w1).state:=w2;
link(.w3.,w1,w2:=address(waitqfst));
end;
if w1 <> coreuser then goto continue;
end;
! action 11 !
primess(.w3.); ! messsage to primo !
! action 12 !
begin ! message to be send later to primo !
w2:=7; goto messwait;
end;
end;
regrettimer:
if w2:=timermess<>0 then
begin
monitor(82); comment regret message;
w2:=0;
timermess:=w2;
end;
\f
comment selection of the next process to be activated
the system deals with two different queues:
1) the active-queue processes ready for running (input has arrived etc)
2) the waiting-queue processes suspended or not used at all
at activation the first user in the activequeue (if any) is tested for
his priority - is it zero then the process is selected for activation
- otherwize the priority is increased, and the user is removed from the
activequeue and then put back on the queue again
;
activate:
userentry:=w1:=activqfst;
if w0:=address(activqfst) <> w1 then ! activequeue not empty !
begin
if w0:=(w1).state = 0 then
if w0:=(w1).class+timerloss < batchclass then ! job is batch !
begin
link(.w3.,w1,w2:=address(batchqfst));
goto activate;
end;
end else
begin ! activequeue empty !
userentry:=w1:=batchqfst;
if w0:=address(batchqfst) = w1 then goto continue; ! batchqueue also empty !
end;
if w0:=(w1).state<0 then
begin ! systemcommand !
swop(.w3.,w1:=0);
!get 2;
if w0 <> 1 then goto discfault;
syscommand(.w3.,w1:=userentry);
end else
if w0:=(w1).prio<0 then
begin
if w0+cyclegain > 0 then w0:=0;
(w1).prio:=w0;
link(.w3.,w1,w2:=address(activqfst));
end else
begin
if w0:= (w1).class > b.batchclass then
(w1).prio:= w0:= (w1).class;
prepare(.w3.);
w1:= address(timeunit);
w3:= address(timer);
monitor(16);
timermess:= w2;
startstop(.w3.,w0:=1,w1:=coreuser);
goto continue;
end;
goto activate;
\f
comment in case of a disc fault disturbing the overlay transports, this piece
of code will be activated -
the octal status, result of the transport and the name of the program area
will be written on the main console and the "sos process" will die;
discfault:
register0:=w0;
register3:=w3;
w1:=firstuser;
(w1).peripheral:=w2:=mainconsref;
(w1).buflength:=w2:=44;
(w1).buffer:=w2:=address(faulttext);
(w2+14).word:=w0:=2111527; ! " 8'" !
for w1:=-21 step 3 upto 0 do
begin
w2+2;
(w2).word:=w0:=register0 lshift (w1) extract 3 + 48;
end;
(w2+2).word:=w0:=32;
copy(.w3.,w0:=8,w1:=register3,w2+2);
(w2+8).word:=w0:=10;
send(.w3.,w0:=0,w1:=firstuser,w2:=20480);
w3:=0;
monitor(0); ! set interrupt !
!halt 1; ! provoke running after error !
end;
\f
comment preparation of process waiting to be activated
first of all the process image in core is possibly written back into the
swoparea and the image of the new process is loaded
then one of the following actions are taken corresponding to the state of
the selected process
0) the process is ready for running -
no actions
1) input has arrived from the terminal -
the input is copied from the terminal buffer into the process and
an answer is sent to the process
2) terminal has become ready after output (term buffer has been full)
no actions
3) the process is to be started with new abs program
the process description is modified according to the conventions for
start of an abs program
;
body of prepare
begin
label inputready;
incode
word return;
word c_funct:=2'01101;
ref c_first,
c_last;
word c_rel:=0;
begin
return:=w3;
swop(.w3.,w1);
case w3:=(w1).state+1 of
begin
begin comment 0: no io or communication via pseudo process;
if w3:=(w1).messgot > 10 then goto inputready;
end;
begin comment 1: input ready;
inputready:
w0:=(w1).messsend;
w3:=(w1).messgot;
if w3:=(w3).operation onemask 1 then
if w0 or (w1).statusinf or 8'10200001 <> 8'10200001 then
begin
swop(.w3.,w1:=0);
!get 2;
if w0 <> 1 then goto b.discfault;
logout(.w3.,w1:=b.userentry);
end;
if w0:=(w1).procbuf1<w3:=b.fstcore then unintelligible(.w3.,w1)
else if w0+(w1).buflength>(w3+(w1).procsize) then unintelligible(.w3.,w1)
else
begin
w2:=b.coreuser;
copy(.w3.,w0:=(w1).buflength,w1:=(w1).buffer,w2:=(w2).procbuf1);
testout(.w3.,w0,w1,w2:=0);
(w3:=b.userentry).currlocid:=w0:=(w1).word;
w1:= b.userentry;
send(.w3.,w0:=(w1).messsend,w1,w2:=(w1).statusinf);
end;
(w1).state:=w0:=0;
if w0:=(w1).class+b.timerloss > b.batchclass then
begin
if w0:=(w1).class+b.inputgain > 0 then w0:=0;
(w1).class:=w0;
(w1).prio:=w0;
end;
end;
begin comment 2: waiting for output answer;
end;
begin comment 3: waiting for loading with new abs program;
w3:=address(b.procname);
w0:=address((w1).pr_out);
w0+b.basereg;
b.register2:=w0;
w0:=address((w1).pr_in);
b.register0:=w0+b.basereg;
w2:=(w1).internal;
b.register3:=w2;
if w0:=(w1).state2<1
then w0:=b.fstcore+b.fp_rel
else
begin
(w1).class:=w0:=0;
w0:=b.fstcore+b.cleart_rel;
end;
b.ic:= w0;
w2+2;
(w3).name1:=f1:=(w2).name1;
(w3).name2:=f1:=(w2).name2;
w1:=address(b.register0);
monitor(62); comment modify internal process;
w1:=b.coreuser;
(w1).state:=w0:=0;
(w1).prio:=w0;
end;
begin ! 4: suspended because of output buffer full !
end;
begin ! 5: message waiting to be send !
end;
begin ! 6: waiting for answer from primo !
startstop(.w3.,w0:=1,w1);
c_first:=w0:=(w1).buffer;
w3:=(w1).buflength-2+w0;
c_last:=w3;
w2:=(w1).messgot;
w1:=address(c_funct);
if w3>=w0 then
monitor(84) ! general copy !
else
w0:=0;
w1:=b.userentry;
if w0<>0 then (w1).messsend:=w0;
send(.w3.,w0:=(w1).messsend,w1,w2:=(w1).statusinf);
startstop(.w3.,w0:=0,w1);
(w1).state:=w0:=0;
end;
begin ! 7: message waiting to be send to primo !
end;
end;
w3:=return
end
end; ! prepare !
\f
comment waitevent
this procedure awaits the first event queued up to the onlineadministrator
according to the kind of this event it proceeds as follows:
answer: an answer is expected to come from the timer or from a terminal
logged in, so the userentries are scanned to find the one matching this
message buffer (the buffer addresses of messages sent to terminals are
saved in the userentries), if no entry is found, and it is not an answer
from the timer, then the answer is neglected and the procedure awaits the
next event.
message: a message is expected to be an i-o message or a parent message
from an internal process or an attention message from a terminal. the
userentries are scanned to find the sender of the message. if no entry
does match the sender (neither internal nor peripheral process belonging
to any user) then the message may be:
1) an attention message from an unknown terminal, the sender is then saved
in a free userentry (if any)
2) a message from an unknown process, the message is rejected
thus at exit the procedure always delivers:
an event (w2)
a userentry (w1)
an event kind (w0) these kinds are: 1 = input message from internal
2 = output message from internal
3 = parent message from internal
4 = attention from known terminal
5 = answer from known terminal
6 = attention from unknown terminal
7 = answer from timer
8 = message from a bastard
9 = message to a pseudo process (tem)
10 = message to be send later
11 = message to a pseudo process (primo)
12 = message to be send later to primo
;
\f
body of waitevent
begin
label wait,exit,reject;
incode
word save0,savew1,zero:=0;
ref return,currmess,entryref;
begin
return:=w3;
wait:
w2:=b.baseevent;;
monitor(24); comment wait first event;
currmess:=w2;
w1:=b.lastuser;
if w0 = 1 then comment answer;
begin
(w1).messsend:=w2;
w1:=address(b.interrupt);
monitor(18); comment wait answer;
if w2 = b.timermess then
begin
w0:=0;
b.timermess:=w0;
w0:=7;
goto exit;
end;
w1:=b.firstuser;
while w2 <> (w1).messsend do w1+!length(userentry);
if w1 = b.lastuser then ! answer from unknown is neglected !
begin
testout(.w3.,w0:=24,w1:=currmess,w2:=6);
goto wait;
end;
(w1).messsend:=w0;
if w0=1 then w0:=(w3:=address(b.interrupt)).bytes else w0:=4;
(w1).buflength:= w0;
(w1).statusinf:=w0:=(w3).status;
w0:=5;
goto exit;
end else
begin comment message;
if w0:=(w2).operation<0 then
begin ! skip if dummy message from term.module !
w3:= address(b.t_mdul);
monitor(4); ! process description !
if w0=(w2).sender then
begin
b.baseevent:= w2;
testout(.w3.,w0:=24,w1:=currmess,w2:=6);
goto wait;
end;
end;
monitor(26); comment get event;
w3:=(w2).sender;
(w1).internal:=w3;
(w1).peripheral:=w3;
w1:=b.firstuser;
while w3<>(w1).internal do w1+!length(userentry);
if w1=b.lastuser then comment sender is not child;
begin
if w0:=(w2).operation<>0 then
begin
w3+50;
if w0:=(w3).word = b.ownproc then
begin
w0:=8;
goto exit;
end else goto reject;
end;
w1:=b.firstuser;
while w3<>(w1).peripheral do w1+!length(userentry);
if w1<b.lastuser then comment the terminal is known;
begin
if w3:=(w1).messgot>10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
w0:=4;
end
else comment attention from unknown terminal;
begin
w0:=0;
(w1).peripheral:=w0;
w1:=b.firstuser;
while w0<>(w1).peripheral do w1+!length(userentry);
if w3<0 then w1:=b.lastuser;
if w1=b.lastuser then
begin
reject:
(w1).messgot:=w2;
(w1).buflength:=w2:=0;
send(.w3.,w0:=2,w1,w2);
goto wait;
end;
(w1).internal:=w3;
(w1).peripheral:=w3; comment link terminal to entry;
w0:=6;
end;
(w1).messgot:=w2:=currmess;
goto exit;
end
else comment sender=internal;
begin
if w3:=(w1).messgot>10 then
begin
w0:=2;
monitor(22); ! send answer - reject !
goto wait;
end;
savew1:=w1;
w1:=(w1).internal+76;
f1:=(w1).double;
w3:=address(zero);
monitor(72); ! set catalog base to that of child !
w3:=address(b.p_mdul);
monitor(4); ! process description of primo pseudo process !
w1:=savew1;
(w1).messgot:=w2;
if w3:=(w1).messsend > 10 then
begin
if w3:=(w2).receiver+w0=0 then w0:=12
else w0:=10
end
else
if w3:=(w2).receiver+w0=0 then
begin
if w0:=7 <> w3:=(w2).operation then ! reject !
begin
w0:=2;
(w1).messgot:=w0;
monitor(22); ! send answer !
goto wait;
end else w0:=11
end else
if w3:=(w2).receiver+b.ownproc <> 0 then w0:=9 else
if w3:=(w2).operation=3 then w0:=1 else
if w3=5 then w0:=2 else w0:=3;
end;
end;
exit:
entryref:=w1;
b.userentry:=w1;
save0:=w0;
comment * testout (.w3., w0:=!length(userentry), w1:=entryref, w2:=68);
comment *; testout (.w3., w0:=12, w1:=address(save0), w2:=26);
testout(.w3.,w0:=24,w1:=currmess,w2:=6);
f1:=b.startbase;
w3:=address(zero);
monitor(72); ! reset catalog base !
w0:=save0; w1:=entryref; w2:=currmess; w3:=return;
end;
end; ! waitevent !
\f
comment link (userentry)
this procedure links off the userentry pointed out by w1 from wherever it
it is chained up, and then links it up immediately after the userentry pointed
out by w2. the heads of the queues (active- and waiting-queue) are of the
same format as the chainelements in the userentries so that the chainheads
may be used just like other elements in the chains.
;
body of link
begin
incode
double w01, w23;
begin
w01:=f1;
w23:=f3;
comment link off userentry;
w3:=(w1).prevuser;
(w3).nextuser:=w0:=(w1).nextuser;
w3:=(w1).nextuser;
(w3).prevuser:=w0:=(w1).prevuser;
comment link userentry(w1) after userentry(w2);
(w1).prevuser:=w3:=(w2).prevuser;
(w1).nextuser:=w0:=(w3).nextuser;
(w2).prevuser:=w1;
(w3).nextuser:=w1;
comment * testout (.w3., w0:=20, w1:=address(b.activqfst), w2:=9);
f1:=w01;
f3:=w23;
end;
end; ! link !
\f
comment copy
this procedure just moves w0 bytes from the address of w1 (and onwards) to
the address of w2 (and onwards)
;
body of copy
begin
incode
double w01,w23;
begin
w01:=f1; w23:=f3;
w3:=w1+w0;
while w1<w3 do
begin
(w2).word:=w0:=(w1).word;
w1+2; w2+2;
end;
f1:=w01; f3:=w23;
end;
end;
\f
comment swop
this procedure makes sure, that the core image of the userentry pointed
out by w1 is brought into core (if it was not there already). if the state
is waiting for start with new abs program, swop loads a process image containing a
new abs program. if the process was in core already and there is not asked for a
new abs program - then nothing is done.
;
body of swop
begin
label exitswop;
incode
double w01,w23;
word opmode;
ref corefst,coretop;
word segmsw;
begin
w01:=f1; w23:=f3;
corefst:=w0:=b.fstcore;
if w2:=b.coreuser=w1 then
if w3:=(w1).state<>3 then goto exitswop;
if w2>0 then comment core not free;
begin
startstop(.w3.,w0:=0,w1:=w2); ! stop coreuser !
opmode:=w0:=5 ashift 12;
coretop:=w0:=corefst+(w2).procsize;
segmsw:=w0:=(w2).swopsegm;
w1:=address(opmode);
w3:=address(b.swname);
transport(.w2.,w1,w3);
end;
f1:=w01;
if w1<>0 then
begin
coretop:=w0:=corefst+(w1).procsize;
opmode:=w0:=3 ashift 12;
if w0:=(w1).state=3 then
begin
segmsw:=w0:=0;
if w0:=(w1).state2<1
then w3:=address(b.fpcode)
else w3:=address(b.cleartemp);
end
else begin
segmsw:=w0:=(w1).swopsegm;
w3:=address(b.swname);
end;
w1:=address(opmode);
transport(.w2.,w1,w3);
end;
f1:=w01;
b.coreuser:=w1;
testout(.w3.,w0:=!length(userentry),w1,w2:=3);
exitswop:
f1:=w01;
f3:=w23;
end;
end; ! swop !
\f
body of unintelligible
begin
incode
double w01,w23;
word op,fst,lst;
begin
w01:=f1; w23:=f3;
!test 99;
op:=w0:=0;
fst:=w0:=2;
lst:=w0:=3;
w2:=(w1).messgot;
w0:=3;
(w1).messgot:=w0;
w1:=address(op);
monitor(22); ! send answer !
testout(.w3.,w0:=6,w1:=address(op),w2:=60);
f1:=w01; f3:=w23
end
end; ! unintelligible !
\f
comment send message to primo
w1 = userentry
w2 = messbuf address of buffer sent to primo (pseudo process)
at return w2 = messbuf address of message sent to primo (real process)
w3 = old w2
;
body of send_primo
begin
incode
word savew2;
double savef1;
ref return;
word op;
ref ofirst,
olast,
ifirst,
ilast;
begin
savef1:=f1;
return:=w3;
savew2:=w2;
op:=w0:=28672; ! 7<12 !
ofirst:=w0:=(w1).buffer;
ifirst:=w0;
olast:=w3:=(w2).mblst-(w2).mbfst+w0;
ilast:=w3:=(w2).mbilast-(w2).segmno+w0;
w1:=address(op);
w3:=address(b.p_pseudo);
monitor(16); ! send message to pseudo process created by primo !
f1:=savef1;
(w1).messsend:=w2;
(w1).state:=w0:=6;
testout(.w3.,w0:=10,w1:=address(op),w2:=2);
f1:=savef1;
w2:=(w1).messsend;
w3:=savew2;
call w0 return
end
end; ! send_primo !
\f
body of primess
begin
label stopped;
incode
ref return;
word savew0;
word zero:=0;
word c_funct:=2'00100;
ref c_first,
c_last;
word c_rel:=0;
begin
return:=w3;
if w0:=(w1).state<0 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2:=256); ! stopped !
goto b.continue;
end else
begin
if w0=0 then
begin
if w1=b.coreuser then
begin
w3:=(w1).internal+11;
if w3:=(w3).byte and 2'10100000=2'10100000 then ! stopped !
begin
(w1).state:=w0:=6;
startstop(.w3.,w0:=1,w1);
end;
c_first:=w0:=(w1).buffer;
c_last:=w3:=(w2).mblst-(w2).mbfst+w0;
w1:=address(c_funct);
if w3>=w0 then
monitor(84) ! general copy !
else
w0:=0;
savew0:=w0;
w1:=b.userentry;
if w0:=6=(w3:=(w1).state) then startstop(.w3.,w0:=0,w1);
if w0:=savew0<>0 then
unintelligble(.w3.,w1)
else
begin
w3:=(w1).buffer;
w0:=(w3).word;
w3+2; w3:=(w3).word;
if w0=4'2000000 then
begin
if w3=4'1010010 then
begin ! define transport !
w1:=(w1).internal+76;
f1:=(w1).double;
w3:=address(zero);
monitor(72); ! set catalog base to that of child !
send_primo(.w3.,w1:=b.userentry,w2);
w1:=address(b.interrupt);
monitor(18); ! wait answer !
w3:=w1;
w1:=b.userentry;
(w1).messsend:=w0; ! result !
(w1).buflength:=w0:=(w3).bytes;
(w1).statusinf:=w0:=(w3).status;
f1:=b.startbase;
w3:=address(zero);
monitor(72); ! reset catalog base !
w1:=b.userentry;
w0:=5; ! answer, w1=userentry, w2=messbufaddr !
if w2:=b.timermess<>0 then
begin
monitor(82); ! regret message !
w2:=0;
b.timermess:=w2
end;
goto b.actioncase;
end
else
unintelligible(.w3.,w1)
end ! define transport !
else
begin
send_primo(.w3.,w1,w2);
if w2:=b.timermess<>0 then
begin
monitor(82); ! regret message !
w2:=0; b.timermess:=w2
end;
link(.w3.,w1,w2:=address(b.waitqfst));
startstop(.w3.,w0:=0,w1);
end
end ! message ok !
end
else
goto stopped
end ! state=0 and in core !
else
begin ! state>0 or not coreuser !
stopped: (w1).buflength:=w0:=0;
(w1).state:=w0;
send(.w3.,w0:=1,w1,w2:=256); ! stopped !
end; ! state>0 or not coreuser !
if w0:=b.timermess<>0 then goto b.continue;
end; ! state>=0 !
w3:=return
end
end; ! primess !
\f
comment send (message or answer)
according to the content of w0 this procedure sends a message or an answer
to the peripheral or the internal process referenced by the userentry(w1).
w0 > 0 answer is sent to internal process (w2 = status, w0 = result)
w0 <= 0 message is sent to peripheral process (w2 = operation < 12 + mode)
at i-o messages to the terminal, the terminal buffer is used for this ope-
ration. at communication with internal processes, data is copied to-from some in-
ternal buffer from-to the terminal buffer. this copying must be done before
calling this procedure.
when w0 < 0 only a part of the terminal buffer is used for the operation,
-w0 giving the relative start address in the buffer.
;
body of send
begin
incode
double w01,w23;
word op,fst,lst;
begin
w01:=f1; w23:=f3;
op:=w2;
if w0>0 then comment send answer;
begin
w2:=(w1).buflength; ! op=status, fst=no.of hw.s, lst=no of chars !
fst:=w2;
lst:=w2+(w3:=w2 ashift -1);
w2:=(w1).messgot;
(w1).messgot:=w0;
w1:=address(op);
monitor(22); comment send answer;
end
else comment send message;
begin
w2:=(w1).peripheral;
if w2 < 0 then -(w2);
w2+2;
w3:=address(b.procname);
(w3).name1:=f1:=(w2).name1;
(w3).name2:=f1:=(w2).name2;
f1:=w01;
if w0<0 then -(w0);
w0 + (w1).buffer;
fst:=w0;
lst:=w0+(w1).buflength-2;
w1:=address(op);
monitor(16); comment send message;
f1:=w01;
(w1).messsend:=w2;
end;
testout(.w3.,w0:=14,w1:=address(w01),w2:=2);
f1:=w01; f3:=w23;
end;
end; ! send !
\f
comment startstop (internal process)
this procedure just starts or stops the internal process referenced by the
userentry (w1).
w0 = 0 stop process
1 start process
;
body of startstop
begin
incode
double w01,w23;
begin
w01:=f1; w23:=f3;
w3:=address(b.procname);
w2:=(w1).internal+2;
(w3).name1:=f1:=(w2).name1;
(w3).name2:=f1:=(w2).name2;
f1:=w01;
if w0=0 then
begin
w1:=b.lastuser;
monitor(60); comment stop internal process;
monitor(18); comment wait answer;
if w0<>1 then key(w01):=w0;
end else
begin
monitor(58); comment start internal process;
if w0<>0 then key(w01):=w0;
end;
f1:=w01;
w2:=w0+4;
testout(.w3.,w0:=!length(userentry),w1,w2);
f1:=w01; f3:=w23;
end;
end; ! startstop !
\f
body of testout
begin
record testhead(byte length,kind;
word time,user,tailfst);
record dump (
word reg0,reg1,reg2,reg3,exreg,instr,cause,sbreg);
incode
ref return;
word bufrel:=0;
double w01,w23;
begin
w01:=f1; w23:=f3;
if w3:=b.testbfst<b.testblst then
begin
if w0+bufrel+8>510 then comment change buffer segment;
begin
if w0 > 1024 then w0:=-2 else w0:=-1;
(w3:=b.testbfst+bufrel).word:=w0;
w1:=address(b.testop);
w3:=address(b.tstarea);
transport(.w2.,w1,w3);
if w1:=b.testsegm+1=b.maxtestsegm then w1:=1;
b.testsegm:=w1;
bufrel:=w0:=0;
end;
f1:=w01; f3:=w23;
w3:=b.testbfst+bufrel;
(w3).length:=w0+6;
bufrel:=w1:=bufrel+w0;
w1:=108; comment abs ref current time;
f1:=(w1).double-b.starttime lshift -7;
(w3).time:=w1;
(w3).kind:=w2;
f1:=w01;
w1:=b.userentry;
w2:=(w1).internal;
(w3).user:=w2;
f1:=w01;
copy(.w3.,w0,w1,w2:=(w3+6));
end;
f3:=w23;
if w2=7 then comment fault;
begin
w3:= (w1).instr-2;
if w0:=(w3).word lshift -12=(51*64) ! key store ! then
begin ! reestablish registers and continue !
w3+1;
(w1).cause:= w0:= (w3).byte;
w0:= (w1).instr;
return:= w0;
w0:= (w1).reg0;
w2:= (w1).reg2;
w3:= (w1).reg3;
w1:= (w1).reg1;
call w0 return;
end
else
begin
f1:=w01;
f3:=w23;
end;
end;
end;
end; ! testout !
\f
comment transport
;
body of transport
begin
incode
byte optr:=2,modetr:=8'1001;
text (6) stars:="status";
word trstatus, trbytes, chars, a4, a5, a6, a7, a8;
word savew0, savew1;
double savef1,savef3;
begin
savew0:=w0; savew1:=w1;
savef3:=f3;
w0:=0;
while w0=0 do
begin
monitor(16);
w1:=address(trstatus);
monitor(18);
w2:=1 ashift w0;
if w0=1 then w2+trstatus;
trbytes :=w0;
if w2<>2 then
begin
trstatus:= w2;
copy(.w3.,w0:=8,w1:=w3,w2:=address(trbytes));
!get 2;
if w0 <> 1 then goto b.discfault;
opmess(.w3.,w1:=address(optr),w2:=b.ownproc);
end;
w0:=trbytes;
w1:=savew1;
f3:=savef3;
end;
w0:=savew0;
end;
end; ! transport !
\f
!branch 1,2;
comment init
this procedure initializes the userentries (being all free) reserves area
for terminal buffer, testbuffer, computes absolute addresses (creating
the chains of the queues, references to buffers and process-area etc),
creates swop- and test-area-processes - and after execution it is over-
written (used as buffer area for execution of child process)
;
body of init
begin
incode
word childstart,swopno:=0;
byte vop:=16,vmode:=8'140;
text(14) verstxt:=
! *** sos *** ! "release: 4.0";
word sosversion := 850801,
comment ===trimstart;
comment date of option version; optionid := 0,
comment rc4000/rc8000 (rc4000=4000,rc8000=8000); rc := 8000,
comment minimum no of active childs at the same time;minusers := 1,
comment terminals performing os-commands; comndusers:= 2,
comment min. no of bufs reserved for childs; minbufs := 4,
comment min. no of areas reserved for childs; minareas := 7,
comment min. core size for childs; minsize := 12800,
comment size of testoutput area; testsegmnt:= 168,
comment size of i-o buffer for a terminal (bytes); bufl := 104,
comment length of a timeslice (seconds); timeslice := 3,
comment max no of timeslices used in cpu (no input); cpulimit := 100,
comment loss of priority class when timed out; classloss := 1,
comment priority class gain at input (if class<0); classgain := 1,
comment priority gain when first in activequeue; priogain := 1,
comment reaction on time exceeded/break; conditions := 2'000011,
comment 2'000001 = abort job at time exceeded;
comment 2'000010 = abort job after break command;
trimtexts; text(11)
comment operator key; oprkey := "opr",
comment document for swoparea; swopdoc := "",
comment document for testarea; testdoc := "",
comment ===trimfinis;
keytext :="key",
inttext :="internal",
buftext :="buf",
areatext:="area",
sizetext:="size";
ref return,currentry,prevchain:=0;
word zero:=0;
array (1:10) tail of word := 0 0 0 0 0 0 0 0 0 0;
byte op1:=16, mode1:=8'40;
word alarm;
text(11) resource;
word filler:=0;
word stdvalue;
text(21) functext:="***function 1,2,3,4,5",
bufltext:="***buflength >= 94";
word stop;
byte op2:= 16, mode2:= 0;
text (20) childres:="child resources";
byte opstop:= 2, modestop:= 1;
text (20) inittr:= "***init troubles";
byte op3:=16, mode3:=0;
text (20) started:="started";
word childareas, users, swopsize;
text(11) swoparea:="swp",testarea:="tst",
fparea:="fp",cleararea:="cleartemp",soscat:="soscat",
t_module:="tem",p_module:="primo",
p_msys:="primosys",console1:="console1";
begin
return:=w3;
w3:=108;
b.starttime:=f1:=(w3).double;
if w2:=rc = 4000 then
begin
b.relintrpt:=w0:=36;
b.reldump:=w0:=38;
end else
begin
b.relintrpt:=w0:=36;
b.reldump:=w0:=80;
end;
copy(.w3.,w0:=8,w1:=address(oprkey),w2:=address(b.operator));
b.maxbuf:=w0:=bufl;
bufl:=w0:=bufl+2;
b.minprio:=-(w1:=cpulimit);
b.interval:=w1:=timeslice;
b.timerloss:=w1:=classloss;
b.cyclegain:=w1:=priogain;
b.inputgain:=w1:=classgain;
b.syscond:=w1:=conditions;
w3:= b.ownproc+32;
w0:= (w3).word;
f1 lshift -12; w1 lshift -12;
if w2:=rc <> 4000 then
begin
b.childpr:= w0;
b.childpk:= w1;
end
else
begin
-(w1);
b.childpr:= w2:= 128 lshift w1 + w0;
if w2 extract 8=127 then ! no key available for child !
begin
stdvalue:= w0:= 2;
copy(.w3.,w0:=8,w1:=address(keytext),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
w2:=b.childpr extract 8;
w1:= 1;
while w2 lshift 1 onemask 128 do w1+1;
b.childpk:= w1;
end;
opmess(.w3.,w1:=address(vop),w2:=b.ownproc);
w3:=b.ownproc+29; ! test function mask !
if w0:=(w3).byte onemask 8'3700 then else
begin
copy(.w3.,w0:=14,w1:=address(functext),w2:=address(started));
stop:=w0:=1;
opmess(.w3.,w1:=address(op3),w2:=b.ownproc);
end;
if w0:=bufl < 94 then ! buffer size too small for sos' private use !
begin
copy(.w3.,w0:=14,w1:=address(bufltext),w2:=address(started));
stop:=w0:=1;
opmess(.w3.,w1:=address(op3),w2:=b.ownproc);
end;
w3:= b.ownproc+28;
w0:= (w3).byte;
if w0<minusers then ! too few internals available !
begin
stdvalue:= w0:= minusers;
copy(.w3.,w0:=8,w1:=address(inttext),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
w0:= minusers;
end;
users:= w0+comndusers;
w0*2; ! compute free bufs !
w0+4;
w3:= b.ownproc+26;
-(w0-(w3).byte);
b.freebufs:= w0;
if w0<minbufs then ! too few buffers !
begin
-(w0-minbufs-(w3).byte);
stdvalue:= w0;
copy(.w3.,w0:=8,w1:=address(buftext),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
w3:= b.ownproc+27;
if w0:=testsegmnts=0 then w0:=4 else w0:= 5;
w0+users-comndusers;
w2:= (w3).byte;
childarea:= w3:= w2-w0;
w0+minareas;
if w2<w0 then ! too few areas !
begin
stdvalue:= w0+1;
copy(.w3.,w0:=8,w1:=address(areatext),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
w3:= b.ownproc+22;
w0:= (w3).word; b.fstcore:= w0;
w3+2;
w0:= (w3).word; b.topcore:= w0;
w0:= bufl+!length(userentry)*users;
w0+!length(userentry);
if w3:=testsegmnts<>0 then w0+512;
w3:= address(childstart); -(w3);
w3+b.topcore; w3-w0;
if w3<minsize then ! size too small !
begin
-(w3-minsize);
w3+b.topcore-b.fstcore; stdvalue:= w3;
copy(.w3.,w0:=8,w1:=address(sizetext),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
swopsize:= w3 ashift -9;
w3 ashift 9;
b.fstcore:= w1:= address (childstart); ! user process is placed instead of branch 2 !
w1+w3; b.topcore:= w1;
b.testbfst:= w1;
w2:= testsegmnts;
if w2>0 then ! prepare testoutput !
begin
w1+510; b.testblst:= w1;
copy(.w3.,w0:=6,w1:=b.ownproc+2,w2:=address(testarea)+2);
tail(w2:=2);
copy(.w3.,w0:=8,w1:=address(testdoc),w2);
if w0:=(w2).word = 0 then (w2).word:=w0:=1;
w3:= address(testarea);
monitor(48); ! remove entry !
(tail(w1:=1)).word:= w2:=testsegmnts;
b.maxtestsegm:= w2;
monitor(40); ! create testoutput area !
monitor(52); ! create area process !
monitor(8); ! reserve area process !
if w0<>0 then
begin
stdvalue:= w2;
copy(.w3.,w0:=8,w1:=address(testarea),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
w1:= 3;
monitor(50); ! permanent entry !
copy(.w3.,w0:=8,w1:=address(testarea),w2:=address(b.tstarea));
end
else
b.testblst:= w1;
! prepare swoparea !
copy(.w3.,w0:=6,w1:=b.ownproc+2,w2:=address(swoparea)+2); ! name = "swp<sos>" !
tail(w2:=2);
copy(.w3.,w0:=8,w1:=address(swopdoc),w2);
if w0:=(w2).word = 0 then (w2).word:=w0:=1;
w3:= address(swoparea);
monitor(48); ! remove entry !
w2:= users*swopsize;
(tail(w1:=1)).word:= w2;
monitor(40); ! create swop area !
monitor(52); ! create area process !
monitor( 8); ! reserve area process !
if w0<>0 then
begin
stdvalue:= w2;
copy(.w3.,w0:=8,w1:=address(swoparea),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:= address(op1),w2:=b.ownproc);
end;
copy(.w3.,w0:=8,w1:=address(swoparea),w2:=address(b.swname));
w3:= address(fparea); ! "fp" !
tail(w1:=1);
monitor(42); ! lookup entry !
w1+17;
b.fp_rel:= w0:= (w1).byte;
monitor(52); ! create area process !
if w0<>0 then
begin
stdvalue:= w0;
copy(.w3.,w0:=8,w1:=address(fparea),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
copy(.w3.,w0:=8,w1:=address(fparea),w2:=address(b.fpcode));
w3:= address(cleararea); ! "cleartemp" !
tail(w1:=1);
monitor(42); ! lookup entry !
w1+17;
b.cleart_rel:= w0:= (w1).byte;
monitor(52); ! create area process !
if w0<>0 then
begin
stdvalue:= w0;
copy(.w3.,w0:=8,w1:=address(cleararea),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
copy(.w3.,w0:=8,w1:=address(cleararea),w2:=address(b.cleartemp));
w3:=b.ownproc+68;
b.startbase:=f1:=(w3).double;
w3:=address(zero);
w0:=w1;
monitor(72); ! set sos own cat base !
w3:= address(soscat); ! "soscat" !
tail(w1:=1);
monitor(52); ! create area process !
if w0<>0 then
begin
stdvalue:= w0;
copy(.w3.,w0:=8,w1:=address(soscat),w2:=address(resource));
alarm:= w0:= 2763306;
stop:= w0;
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
end;
copy(.w3.,w0:=8,w1:=address(soscat),w2:=address(b.usercat)); ! "soscat" !
copy(.w3.,w0:=8,w1:=address(t_module),w2:=address(b.t_mdul)); ! "tem" !
copy(.w3.,w0:=8,w1:=address(p_module),w2:=address(b.p_mdul)); ! "primo" !
copy(.w3.,w0:=8,w1:=address(p_msys),w2:=address(b.p_pseudo)); ! "primosys" !
if w0:=stop<>0 then
begin ! resources not available for start up !
opmess(.w3.,w1:= address(opstop),w2:=b.ownproc);
end;
opmess(.w3.,w1:=address(op2),w2:=b.ownproc);
alarm:= w0:= 2105376; ! " " !
stdvalue:= w0:= users-comndusers;
copy(.w3.,w0:=8,w1:=address(inttext),w2:=address(resource));
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
stdvalue:= w0:= b.freebufs;
copy(.w3.,w0:=8,w1:=address(buftext),w2:=address(resource));
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
stdvalue:= w0:= childareas;
copy(.w3.,w0:=8,w1:=address(areatext),w2:=address(resource));
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
w0:= b.topcore-b.fstcore; stdvalue:= w0;
copy(.w3.,w0:=8,w1:=address(sizetext),w2:=address(resource));
opmess(.w3.,w1:=address(op1),w2:=b.ownproc);
opmess(.w3.,w1:=address(op3),w2:=b.ownproc);
comment reserve space for i/o-buffers for terminals;
w1:= b.testblst+2;
w0:=bufl*users;
w2:=w0+w1;
currentry:=w2;
b.firstuser:=w2;
swopno:=w3:=swopno-swopsize;
w3:=0;
while w3+1<=users do ! initialize all user entries as empty !
begin
(w2).prevuser:=w0:=prevchain;
prevchain:=w2;
swopno:=w0:=swopno+swopsize;
(w2).swopsegm:=w0:=swopno;
w0:=0;
(w2).internal:=w0;
(w2).peripheral:=w0;
(w2).messsend:=w0;
(w2).messgot:=w0;
(w2).bufrel:=w0;
(w2).buffer:=w1;
w1+bufl;
w0:=w2+!length(userentry);
(w2).nextuser:=w0;
w2:=w0;
end;
b.lastuser:=w2;
w2:=(w0-!length(userentry));
w0-!length(userentry);
(w2).prevuser:=w0;
(w2).nextuser:=w0:=address(b.waitqfst);
b.waitqlst:=w2;
w2:=b.firstuser;
(w2).prevuser:=w0:=address(b.waitqfst);
b.activqfst:=w0:=address(b.activqfst);
b.activqlst:=w0;
b.batchqfst:=w0:=address(b.batchqfst);
b.batchqlst:=w0;
b.waitqfst:=w2;
testout(.w3.,w0:=60,w1:=address(sosversion),w2:=69);
w3:=address(zero);
f1:=b.startbase;
monitor(72); ! set own cat base !
w0:=b.fstcore;
b.register1:=w0;
w0:=b.fstcore+2;
testout(.w3.,w0:=150,w1:=b.ownproc-4,w2:=8);
comment *; testout (.w3., w0:=20, w1:=address(b.activqfst), w2:=9);
w3:=b.ownproc+98;
b.basereg:=w3:=(w3).word;
w3:=return;
end;
end; ! init !
\f
body of opmess
begin
procedure outinteger(.w3.;w1;w2);
incode
text(11) pause:=" pause ",mess:=" message ";
text(14) maincons;
word clock1,clock2;
text(11) sysname;
text(11) messtype;
text(14) procname:=" ";
array(1:70) linebuffer of word;
word nl:=10;
byte op:=5,mode:=0;
ref first,last;
double savef1,savef3;
begin
savef1:=f1;
savef3:=f3;
outtime(.w3.,w2:=address(clock1));
w3:=address(sysname);
w2:=b.ownproc+2;
(w3).name1:=f1:=(w2).name1;
f1:=(w2).name2;
w1+58;
(w3).name2:=f1;
f3:=savef3;
copy(.w3.,w0:=8,w1:=w2+2,w2:=address(procname));
f1:=savef1;
if w0:=(w1).word extract 1 = 1 then w1:=address(pause)
else w1:=address(mess);
copy(.w3.,w0:=8,w1,w2:=address(messtype));
f1:=savef1;
w0:=-1 lshift 12 or (w1).word lshift -5;
w1+14;
linebuffer(w2:=70);
while w0 onemask 8'10000 do
begin
if w0 onemask 1 then
outinteger(.w3.,w1,w2) else
(w2).word:=w3:=(w1).word;
w2-2;
w1-2;
w0 lshift -1;
end;
w0:=0;
linebuffer(w1:=1);
while w1 <= w2 do
begin
(w1).word:=w0;
w1+2;
end;
first:=w1:=address(clock1);
last:=w1:=address(nl);
copy(.w3.,w0:=8,w1:=b.mainconsref+2,w2:=address(maincons));
w1:=address(op);
w3:=address(maincons);
monitor(16); ! send message !
linebuffer(w1:=1);
monitor(18); ! wait answer !
f1:=savef1;
f3:=savef3;
if w2 = b.ownproc then
if w0:=(w1).word onemask 1 then
begin ! pause message from sos itself !
w0:=0;
w3:=0;
monitor(0); ! set interrupt !
testout(.w3.,w0:=1024,w1:=-2,w2);
end else f1:=savef1;
end;
body of outinteger
begin
incode
double savef1;
word savew3;
begin
savef1:=f1;
savew3:=w3;
(w2).word:=w0:=32;
w2-2;
w0:=(w1).word;
if w0 = 0 then
begin
(w2).word:=w3:=48;
w2-2;
end;
while w0 <> 0 do
begin
w3:=0;
f0 // 10;
(w2).word:=w3+48;
w2-2;
end;
(w2).word:=w0:=32;
f1:=savef1;
w3:=savew3;
end;
end; ! outinteger !
end; ! opmess !
\f
body of logout
begin
incode
double savef1,savef3;
byte op1,mode1:=0;
ref fst,lst;
byte op2:=102,mode2:=0;
word locid;
text(14) simtext:="'2''2' hard error'10'";
text(14) poolname;
begin
savef1:=f1;
savef3:=f3;
startstop(.w3.,w0:=0,w1);
(w1).buflength:=w0:=0;
if w0:=(w1).messgot > 10 then send(.w3.,w0:=1,w1,w2:=0);
locid:=w0:=(w3:=(w1).buffer).word;
copy(.w3.,w0:=6,w1:=(w1).internal+2,w2:=address(poolname)+2);
copy(.w3.,w0:=2,w1:=address(b.t_mdul),w2:=address(poolname));
w3:=address(poolname);
op1:=w0:=9; ! simulate input !
fst:=w0:=address(locid);
lst:=w0:=address(simtext)+8;
w1:=address(op1);
monitor(16); ! send message !
w1:=b.lastuser;
monitor(18); ! wait answer !
if w0 or (w1).word = 1 then
begin ! terminal on transparent pool !
w1:=address(op2);
monitor(16); ! send message (remove link soft) !
w1:=b.lastuser;
monitor(18); ! wait answer !
end else
begin ! other kind of hard error - kill job !
f1:=savef1;
clean(.w3.,w1);
(w1).intervent:=w0:=6;
end;
f1:=savef1;
w0:=1;
(w1).messsend:=w0;
goto b.activate;
end;
end; ! logout !
\f
body of outtext
begin
incode
text(29)
t0 :="command unknown'10'",
t1 :="ready'10'",
t2 :="syntax'10'",
t3 :="identification illegal'10'",
t4 :="no room in primary store'10'",
t5 :="bs claims exceeded'10'",
t6 :="process creation not ok'10'",
t7 :="forbidden'10'",
t8 :="terminal busy'10'",
t9 :="terminal connection not ok'10'",
t10:="jobfile does not exist'10'",
t11:="terminal connected'10'",
t12:="terminal disconnected'10'",
t13:="bad password'10'",
t14:="terminal not connected'10'",
t15:="process unknown'10'",
t16:="disconnection not ok'10'",
t17:="call not ok'10'",
t18:="include not ok'10'",
t19:="enrolled'10'",
t20:="removed after break'10'",
t21:="removed after finis'10'",
t22:="removed after user kill'10'",
t23:="removed after operator kill'10'",
t24:="removed after time exceeded'10'",
t25:="removed after terminal error'10'",
t26:="removed after user break'10'",
t27:="removed after operator break'10'",
t28:="user conflict'10'",
t29:="forbidden - system locked'10'",
t30:="user catalog reserved'10'",
t99:="***";
double savef3;
word savew0,savew1;
ref bufpointer;
begin
savef3:=f3;
savew0:=w0;
savew1:=w1;
bufpointer:=w3:=(w1).buffer;
(w3).word:=w2:=0;
w3+2;
bufpointer:=w3;
if w0 onemask 8'10 then
begin ! write time !
outtime(.w3.,w2:=bufpointer);
bufpointer:=w2:=bufpointer+4;
end;
w3:=bufpointer;
case w2:=savew0 extract 3 + 1 of
begin
(w3).word:=w0:=0;
(w3).word:=w0:=2763306; comment "***" ;
(w3).word:=w0:=2171169; comment "!!!" ;
(w3).word:=w0:=2960685; comment "---" ;
(w3).word:=w0:=2105376; comment " " ;
(w3).word:=w0:=0;
(w3).word:=w0:=0;
(w3).word:=w0:=0;
end;
bufpointer:=w0:=bufpointer+2;
if w0:=savew0 onemask 8'20 then
begin ! write system name !
w3:=bufpointer;
w2:=b.ownproc+2;
(w3).name1:=f1:=(w2).name1;
f1:=(w2).name2;
w1+14880; ! ": " !
(w3).name2:=f1;
bufpointer:=w0:=bufpointer+8;
end;
if w0:=savew0 onemask 8'40 then
begin ! write process name !
w3:=bufpointer;
w1:=savew1;
w1:=savew1;
w2:=(w1).internal+2;
(w3).name1:=f1:=(w2).name1;
f1:=(w2).name2;
w1+32;
(w3).name2:=f1;
bufpointer:=w0:=bufpointer+8;
end;
f3:=savef3;
w2*20;
copy(.w3.,w0:=20,w1:=address(t0)+w2,w2:=bufpointer);
w1:=savew1;
w0:=(w1).buffer;
w2+20-w0;
(w1).buflength:=w2;
testout(.w3.,w0:=w2,w1:=(w1).buffer,w2:=0);
w1:=savew1;
send(.w3.,w0:=0,w1,w2:=20480);
w0:=savew0;
w1:=savew1;
f3:=savef3;
end;
end; ! outtext !
\f
body of outtime
begin
record timetext(word hourtxt,minutetxt);
incode
ref systime:=108;
word daysize:=1687500,hoursize:=70313,minutesize:=1172;
ref return,bufref;
double savef1;
begin
savef1:=f1;
bufref:=w2;
return:=w3;
f3:=systime.name1 lshift -9 // daysize; ! w3:=dayno !
f1 lshift -100;
f2 // hoursize; ! w2:=hour !
f1 // minutesize; ! w1:=minute !
w0:=0;
f1 // 10;
bufref.minutetxt:=w1 + 48 lshift 8 + w0 + 48 lshift 8 + 32;
w1:=0;
f2 // 10;
bufref.hourtxt:=w2 + 48 lshift 8 + w1 + 48 lshift 8 + 46;
f1:=savef1;
w2:=bufref;
w3:=return;
end;
end; ! outtime !
\f
comment syscommand
this procedure checks the user identification typed at login. if it is
ok, a process is created with standard bs claims and with catalog bases
corresponding to the user identification.
the user is answered with a message telling, wheather or not the attemp
to login was succesfull.
;
body of syscommand
begin
procedure login(.w3.;w0;w1);
comment call: w0 kind of start command
w1 abs ref string1
return: w1 abs ref error message or zero
;
procedure out(.w3.;w1);
comment call: w1 abs ref string1
return: w1 abs ref error message or zero
;
procedure control(.w3.;w0;w1);
comment call: w0 control operation (1,2,3,4 = kill,break,stop,start)
w1 abs ref string1
return: w1 abs ref error message or zero
;
procedure empty(.w3.;w1);
comment call: w1 abs ref userentry
return: w1 abs ref error message or zero
;
procedure include(.w3.;w1);
comment call: w1 abs ref string1
return: w1 abs ref error message or zero
;
label newstring,aftername,commfound,error,accept;
incode
double savef1,savef3;
word logstop,radix,offset,char,savew1,savew2,savew3,count,comm,proc_no;
ref namepointer,next;
text(11) emptytext:="";
text(11) string1, string2, string3,
string4, string5, string6,
string7,string8,string9;
text(11)oscomm1 :="in",
oscomm2 :="out",
oscomm3 :="kill",
oscomm4 :="",
oscomm5 :="run",
oscomm6 :="go",
oscomm7 :="batch",
oscomm8 :="break",
oscomm9 :="stop",
oscomm10:="start",
oscomm11:="call",
oscomm12:="include",
oscomm13:="lock",
oscomm14:="open",
oscomm15:="halt";
begin
savef1:=f1; savef3:=f3;
testout(.w3.,w0:=!length(userentry),w1,w2:=68);
testout(.w3.,w0:= (w1).bufrel + (w1).buflength,w1:=(w1).buffer,w2:=0);
! read strings !
w0:=0;
w1:=address(emptytext);
w2:=address(string1);
w3:=0;
while w3+1<=9 do ! zeroset string1 - string9 !
begin
savew3:=w3;
copy(.w3., w0:=8, w1, w2);
w3:=savew3;
w2+8;
end;
comment transfer commands from terminal buffer to the text
variables string1 - string 8
;
count:=w0:=1;
namepointer:=w0:=address(string1);
next:=w0:=namepointer+8;
w3:=b.userentry;
w2:=(w3).buffer;
comm:= w0:= (w3).state;
w1:=0;
logstop:=w0:= (w3).bufrel + (w3).buflength+w2;
(w3).bufrel:= w1;
newstring:
w0:=32;
while w0=32 do nextchar(.w3.,w3:=logstop,w0,w1,w2);
if w0 = 10 then goto aftername;
if w0 = 62 then ! '>' is start of password line !
begin
comm:= w0:= 0;
goto newstring;
end;
if w0 < 97 then
begin ! integer param !
offset:=w3:=48;
radix:=w3:=10;
word(namepointer):=w3:=-1;
namepointer:=w3:=namepointer+2;
end else
begin ! name param !
offset:=w3:=0;
radix:=w3:=256;
end;
while w0<>32 do
begin
if w3:=next=namepointer
then goto aftername;
if w0=10 then goto aftername;
char:=w0;
if w0:=offset = 0 then
begin
if w0:=char >= 97 then
if w0 < 126 then goto accept;
end;
if w0:=char >= 48 then
if w0 < 58 then goto accept;
!test 1;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
accept:
w0:=word(namepointer)*radix; ! pack text or number !
word(namepointer):=w0+char-offset;
if w0>65535 then namepointer:=w3:=namepointer+2;
nextchar(.w3.,w3:=logstop,w0,w1,w2);
end;
aftername:
! more than 11 chars or w0=32 or w0=10 !
if w3:=next=namepointer then
begin
!test 2;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
end;
if w0=32 then
begin
count:=w3:=count+1;
if w3>8 then ! max 8 params in command line !
begin
while w0=32 do nextchar(.w3.,w3:=logstop,w0,w1,w2);
if w0<>10 then
begin
!test 3;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
end;
end;
end;
if w3:=offset = 0 then ! fill textparam with null-chars !
if w3:=next>namepointer then
begin
w3:=word(namepointer);
if w3<>0 then
while w3<65535 do w3 lshift 8;
word(namepointer):=w3;
end;
namepointer:=w3:=next;
next:=w3:=next+8;
if w0=32 then goto newstring;
if w0:= comm = -3 then goto newstring;
! first newline blind, when reading invisible password !
comment now all parameters have been read;
w1:=address(oscomm1);
w2:=address(string1);
comm:=w3:=1;
while w3:=comm<16 do
begin
compare(.w3.,w0:=4,w1,w2);
if w0=0 then goto commfound;
w1+8;
comm:=w3:=comm+1;
end;
!test 4;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=0); ! what !
goto error;
commfound:
w1:=address(string1);
case w3:=comm of
begin
login(.w3.,w0:=3,w1); ! in (connection to pool) !
out(.w3.,w1); ! out (disconnect) !
control(.w3.,w0:=1,w1); ! kill !
empty(.w3.,w1:=b.userentry);
login(.w3.,w0:=2,w1); ! run (connection via tem)!
login(.w3.,w0:=0,w1); ! go !
login(.w3.,w0:=1,w1); ! batch !
control(.w3.,w0:=2,w1); ! break !
control(.w3.,w0:=3,w1); ! stop !
control(.w3.,w0:=4,w1); ! start !
calldev(.w3.,w1); ! call (name device) !
include(.w3.,w1); ! include users(device) !
control(.w3.,w0:=-1,w1); ! lock (block logins) !
control(.w3.,w0:=-2,w1); ! open (accept login) !
control(.w3.,w0:=-3,w1); ! halt !
end;
if w1 <> 0 then
begin
error:
if w1 = -1 then
begin
!test 5;
if w0:= (w1:=b.userentry).messsend < 10 then
outtext(.w3.,w0:=8'30,w1,w2:=1); ! ready !
if w0:=(w1).state = -1 then (w1).state:=w0:=0;
end;
w1:=b.userentry;
(w1).bufrel:= w0:= 0;
if w0:=(w1).state = -1 then
begin
link(.w3.,w1,w2:=address(b.waitqfst));
(w1).state:=w0:=0;
end else
if w0 < -1 then
begin
w0:=0;
(w1).messsend:=w0;
(w1).peripheral:=w0;
(w1).internal:=w0;
link(.w3.,w1,w2:=address(b.waitqfst));
end else ;
end;
w0:=1;
w1:=b.userentry;
(w1).messsend:=w0;
w3:=address(emptytext);
f1:=b.startbase;
monitor(72); ! set sos own catalog base !
f1:=savef1;
f3:=savef3;
end; ! syscommand !
\f
body of login
begin
procedure checkprot(.w3.;w1;w2);
comment call: w1 abs ref "pass"-parameter
w2 abs ref password from catalog
return: w1 abs ref error message or zero
w2 boolean rewrite catalog segment
;
procedure checkdevice(.w3.;w0;w1);
comment call: w1 abs ref userentry
return: w0 mode for reading of password:
0: console (deviceno=2)
2: other terminal (dev<>2)
other registers unchanged
;
label error,error1,error2,error2_1,error3,error4,freefound,
release;
incode
! process description for create internal process !
double corelimits;
byte buffers,areas,
internals:=0,fncmask:=1792, ! .111........ !
protreg,protkey;
double maxbase,stdbase;
double claim0,claim1,claim2,claim3;
byte logop:=5,logmode:=0;
ref first,last;
word segm,zero:=0,rewrite;
word savew0,savew1,savew2,savew3;
ref jobfile:=0,procentry;
double savef3;
text(11) emptytext:="",jobf:="jobfile";
ref string1,string2,string3,string4,string5,string6,
string7,string8;
array(1:10) tail of word;
array(1:8)answ of word;
byte simop,simmode:=0;
ref simfirst,simlast;
word simlocid;
text(9) simtext:="'1''1' att ";
text(11)trmname;
word nl:=10;
byte temop,temmode:=0;
word localid;
ref termpda;
byte bufs,timers;
text(14) poolname;
word help;
comment format of login command is:
s1 s2 s3 s4
( go )
( run ) <procname> ( jobfile <filename> )(.)
( batch )
s3/5 s4/6 s5/7 s6/8
( pass <passname> (newpass <passname>)(.) )(.)
( >password <passname> )
or:
s1 s2 s3 s4 s5 s6 s7
in <procname> <termname> ( pass <passname> (newpass <passname>)(.) )(.)
( >password <passname> )
;
begin
savew0:=w0; ! login-kind: 0=go, 1=batch, 2=run, 3=in !
savef3:=f3;
w3:=b.userentry;
if w0:=b.sysstate <> 0 then if w0:=b.mainconsref<>(w3).peripheral then
begin
!test 6;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=29); ! forbidden - system locked !
goto error;
end;
string1:=w1; w1+8;
string2:=w1; w1+8;
string3:=w1; w1+8;
string4:=w1; w1+8;
string5:=w1; w1+8;
string6:=w1; w1+8;
string7:=w1; w1+8;
string8:=w1;
compare(.w3.,w0:=8,w1:=string3,w2:=address(jobf));
if w0 = 0 then jobfile:=w3:=string4;
w1:=b.userentry;
if w3:=(w1).state = -1 then ! known terminal creating new job !
begin
if w0:=jobfile = 0 then ! at most one job without jobfile !
begin
!test 7;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=7); ! forbidden !
link (.w3., w1:= b.userentry, w2:= address(b.activqfst));
w1:= -1;
goto error;
end;
w1:=b.lastuser;
while w1-!length(userentry) >= b.firstuser do
begin
if w0:=(w1).internal = 0 then goto freefound;
end;
!test 8;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=6); ! process creation !
link (.w3., w1:= b.userentry, w2:= address(b.activqfst));
w1:= -1;
goto error;
freefound:
procentry:=w2:=b.userentry; ! old entry !
b.userentry:=w1; ! new entry !
(w2).state:=w0:=0;
(w1).peripheral:=w0:=(w2).peripheral;
(w1).internal:=w0;
(w1).state:=w0:=-2;
(w1).buflength:=w0:=(w2).buflength;
copy (.w3., w0, w1:=(w2).buffer, w2:=(w2:=b.userentry).buffer);
link(.w3.,w1:=procentry,w2:=address(b.activqfst));
end;
procentry:=w1:=b.userentry; ! new entry !
(w1).primdevi:=w0:=(w1).peripheral;
w0:=savew0;
if w0 = 3 then w2:=string3 else w2:=0;
scancat(.w3.,w0,w1:=string2,w2);
if w0 < 0 then
begin
if w0 = -3 then w2:=30 ! user catalog reserved !
else w2:=3; ! identification illegal !
!test 9;
outtext(.w3.,w0:=8'31,w1:=procentry,w2);
goto error1;
end else segm:=w0;
b.procdescr:=w1;
b.termdescr:=w2;
if w0:=savew0 < 3 then ! go, run or batch !
begin
if w1:=jobfile = 0 then w1:=string3
else w1:=string5;
checkprot(.w3.,w1,w2:=b.procdescr+!position(ppass));
if w1 <> 0 then goto error1;
rewrite:=w2;
if w1:=jobfile > 0 then
begin
w1:=procentry;
w2:=(w1).peripheral;
-(w2);
(w1).peripheral:=w2; ! jobfile is marked by negative peripheral !
w2:=address((w1).pr_in);
(w2).word:=w0:=4;
copy(.w3.,w0:=8,w1:=jobfile,w2+2); ! insert jobfile name in i/o-buffer !
end else
begin
w1:=procentry;
w2:=address((w1).pr_in);
(w2).word:=w0:=8;
copy(.w3.,w0:=8,w1:=b.ownproc+2,w2+2); ! sos-name in i/o-buffer !
end;
w2:=address((w1:=procentry).pr_out);
(w2).word:=w0:=8;
copy(.w3.,w0:=8,w1:=b.ownproc+2,w2+2);
w3:=b.procdescr;
buffers:=w0:=(w3).procbuffers;
areas:=w0:=(w3).procareas;
w0:=(w3).procsb1;
w1:=(w3).procsb2;
stdbase:=f1;
w0:=(w3).procmb1;
w1:=(w3).procmb2;
maxbase:=f1;
w0:=b.fstcore;
if w1:=b.topcore-b.fstcore > (w3).pmaxsize
then w1:=(w3).pmaxsize+511 lshift -9 lshift 9;
if w1 < (w3).pminsize then
begin
!test 10;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=4); ! no room in primary store !
goto error1;
end;
procentry.procsize:=w1;
w1+w0;
corelimits:=f1;
protreg:=w1:=b.childpr;
protkey:=w1:=b.childpk;
w3:=address(zero);
f1:=stdbase;
monitor(72);! set sos own cat base !
!test 445;
if w3:=jobfile > 0 then
begin
tail(w1:=1);
w3:=jobfile;
monitor(42); ! lookup jobfile !
if w0 <> 0 then
begin
!test 11;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=10); ! no jobfile !
goto error1;
end;
end;
w3:=address(b.t_mdul);
monitor(80); ! create pseudo process "tem" !
if w0 <> 0 then
begin
!test 12;
if w0 = 3 then outtext(.w3.,w0:=8'31,w1:=procentry,w2:=28) ! user conflict !
else outtext(.w3.,w0:=8'31,w1:=procentry,w2:=6); ! process creation !
goto error1;
end;
w3:=address(b.p_mdul);
monitor(80); ! create pseudo process "primo" !
if w0<>0 then
begin
!test 14;
if w0 = 3 then outtext(.w3.,w0:=8'31,w1:=procentry,w2:=28)
else outtext(.w3.,w0:=8'31,w1:=procentry,w2:=6);
goto error2_1;
end;
f1:=b.startbase;
w3:=address(zero);
monitor(72); ! reset sos own cat base !
!test 447;
if w0:=b.freebufs-buffers<0 then
begin
!test 16;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=6); ! process creation !
goto error2;
end
else b.freebufs:=w0;
w1:=address(corelimits);
w3:=string2;
monitor(56); ! create internal process !
if w0<>0 then
begin
!test 17;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=6); ! process creation !
goto error3;
end;
w3:=b.procdescr;
w0:=(w3).procub1;
w1:=(w3).procub2;
w3:= string2;
monitor(72); ! set catalog base = user base !
if w0<>0 then
begin
!test 18;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=6); ! process creation !
goto error4;
end;
monitor(4); ! get process description address in w0 !
w1:=procentry;
(w1).internal:=w0;
w3:=b.procdescr;
w2:=w3+!position(procdiscs);
w1:=0;
while w1+1<13 do
begin
w2+!length(procdisc);
savew1:=w1;
testout(.w3.,w0:=!length(procdisc),w1:=w2,w2:=68);
w2:=w1; w1:=savew1;
if w3:=(w2).word=0 then w1:=13
else
begin
savew1:=w1;
savew2:=w2;
w1:=w2+8;
w2:=address(claim0);
copy(.w3.,w0:=16,w1,w2);
w1:=w2;
w2:=savew2;
w3:=string2;
monitor(78); ! set bs claims !
if w0<>0 then
begin
!test 19;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=5); ! claims exceeded !
goto error4;
end;
w1:=savew1;
w2:=savew2;
end;
end;
if w0:=savew0 = 2 then ! run - connect terminal via tem !
begin
! generate poolname: char 1-3 of sos-name, char 4-11 of procname !
copy(.w3.,w0:=2,w1:=b.ownproc+2,w2:=address(poolname));
copy(.w3.,w0:=6,w1:=procentry.internal+2,w2+2);
temop:=w0:=90; ! create pool !
w1:=address(temop);
w3:=address(b.t_mdul);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
if w0 or (w1).word <> 1 then
begin
!test 20;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=9); ! terminal connection error !
goto error4;
end;
w3:=address(poolname);
monitor(4); ! get process description !
if w2:=jobfile > 0 then -(w0);
procentry.peripheral:=w0;
termpda:=w0:=procentry.primdevi;
localid:=w0:=0;
bufs:=w0:=1;
timers:=w0:=5;
temop:=w0:=100; ! create link !
temmode:=w0:=2; ! transparent link !
w3:=address(poolname);
w1:=address(temop);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
if w0 or (w1).word <> 1 then
begin
temmode:=w0:=0;
temop:=w0:=92;
w1:=address(temop);
w3:=address(b.t_mdul);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
procentry.peripheral:=w0:=procentry.primdevi;
!test 21;
outtext(.w3.,w0:=8'31,w1:=procentry,w2:=9); ! terminal connection error !
goto error4;
end;
procentry.primio:=w0:=0;
procentry.currlocid:=w0:=0;
end
else procentry.primio:=w0:=0; ! go/batch login !
w1:=procentry;
link(.w3.,w1,w2:=address(b.activqfst));
comment the new job is linked into the activequeue independent
of the job type. a batchjob is later on moved to the
batchqueue (at "activate:" in the main program) because
of the priority class
;
w0:=1;
(w1).messsend:=w0;
(w1).statusinf:=w0:=0;
w2:=(w1).buffer;
w1:=b.procdescr+!position(procfp);
copy(.w3.,w0:=40,w1,w2);
w1:=procentry;
if w0:=savew0 = 1
then ! batch ! (w1).class:=w0:=b.batchclass-b.timerloss-1
else (w1).class:=w0:=0;
(w1).state:=w0:=3;
(w1).state2:=w0:=-1;
(w1).prio:=w0:=0;
(w1).intervent:=w0;
w1:=procentry;
(w1).buffer:=w0:=(w1).buffer+50;
!test 22;
outtext(.w3.,w0:=8'70,w1,w2:=19); ! enrolled !
(w1).buffer:=w0:=(w1).buffer-50;
(w1).buflength:=w0:=40;
w0:=1;
(w1).messsend:=w0;
w1:=0;
end ! go/run/batch !
else
if w0 = 3 then ! in - connect terminal to pool !
begin
checkprot(.w3.,w1:=string4,w2:=b.termdescr+!position(userkey));
if w1 <> 0 then goto error1;
rewrite:=w2;
! generate poolname: "tem<termname>" !
copy(.w3.,w0:=2,w1:=address(b.t_mdul),w2:=address(poolname));
copy(.w3.,w0:=6,w1:=string2,w2+2);
termpda:=w0:=(w1:=b.userentry).peripheral;
localid:=w0:=(w3:=b.termdescr).intid;
simlocid:=w0;
bufs:=w0:=(w3).tbufs;
timers:=w0:=(w3).ttimers;
temop:=w0:=100; ! create link !
w1:=address(temop);
w3:=address(poolname);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
if w0 or (w1).word <> 1 then
begin
if w1:=w0 and 8'1020 <> 0 then w2:=8 ! busy !
else w2:=9; ! terminal connection error !
!test 23;
outtext(.w3.,w0:=8'31,w1:=procentry,w2);
goto error1;
end;
copy(.w3.,w0:=8,w1:=termpda+2,w2:=address(trmname));
simfirst:=w1:=address(simlocid);
simlast:=w1:=address(nl);
simop:= w0:= 9;
w1:=address(simop);
w3:=address(poolname);
monitor(16); ! send message (simulate input) !
answ(w1:=1);
monitor(18); ! wait answer !
!test 24;
outtext(.w3.,w0:=8'30,w1:=procentry,w2:=11); ! terminal connected !
end else;
if w2:=rewrite <> 0 then
begin
help:=w1;
first:=w0:=b.topcore-512;
last:=w0:=b.topcore-2;
transport(.w2.,w1:=address(logop),w3:=address(b.usercat));
w1:=help;
end;
goto release;
error4:
w3:=string2;
monitor(64); ! remove child process !
error3:
b.freebufs:=w0:=b.freebufs+buffers;
error2:
help:=w1;
f1:=stdbase;
w3:=address(zero);
monitor(72); ! set own catalog base !
w3:=address(b.p_mdul);
monitor(64); ! remove process !
w1:=help;
error2_1:
help:=w1;
f1:=stdbase;
w3:=address(zero);
monitor(72); ! set sos catalog base !
w3:=address(b.t_mdul);
monitor(64); ! remove pseudo process !
w1:=help;
release:
error1:
w3:=address(b.usercat);
monitor(10); ! release usercat !
error:
w0:=savew0;
f3:=savef3;
end; ! login !
\f
body of scancat
begin
label procfound,newsegm,termfound,exit;
incode
ref procname,termname,return;
array(1:!length(procdescr)) process of byte;
byte logop,logmode:=0;
ref first,last;
word segm,proc_no,savew1,logstop,zero:=0;
begin
procname:=w1;
termname:=w2;
return:=w3;
w3:=address(zero);
f1:=b.startbase;
w0:=w1;
monitor(72); ! set own cat base !
w3:=address(b.usercat);
monitor(8); ! reserve process, i.e. open(z,4,<:soscat:>,0) !
if w0 <> 0 then
begin
w0:=-3;
goto exit;
end;
first:=w0:=b.topcore-512;
last:=w0:=b.topcore-2;
logop:=w0:=3;
segm:=w0:=0;
w1:=address(logop);
transport(.w2.,w1,w3);
w3:=b.topcore-2;
proc_no:=w3:=(w3-4).word;
w1:=0;
w2:=b.topcore-512-!length(prindex);
while w1+1<=proc_no do
begin
w3:=0;
w0:=w1;
if f0 mod 50=1 then
if w1<>1 then
begin
segm:=w0;
savew1:=w1;
w1:=address(logop);
w3:=address(b.usercat);
transport(.w2.,w1,w3);
w1:=savew1;
w2:=b.topcore-512-!length(prindex);
end;
w2+!length(prindex);
savew1:=w1;
compare(.w3.,w0:=8,w1:=procname,w2);
if w0 = 0 then goto procfound;
w1:=savew1;
end;
w0:=-1;
goto exit;
procfound:
segm:=w1:=(w2).prsegmno;
w1:=address(logop);
w3:=address(b.usercat);
transport(.w2.,w1,w3);
w1:=b.topcore-512;
process(w2:=1);
copy(.w3.,w0:=!length(procdescr),w1,w2);
testout(.w3.,w0,w1,w2:=68);
! find terminal in soscat !
if w2:=termname = 0 then
begin
w0:=segm;
goto exit;
end;
w2:=b.topcore-512;
w2+!length(procdescr);
w2-!length(termdescr);
w3:=b.topcore-!length(termdescr);
logstop:=w3;
newsegm:
!test 540;
while w2+!length(termdescr)<logstop do
begin
if w1:=(w2).word=-1 then w2:=logstop
else begin
compare(.w3.,w0:=8,w1:=termname,w2);
if w0=0 then goto termfound;
end;
end;
w2:=b.topcore-2;
if w0:=(w2).word<>-1 then
begin
segm:=w0;
w1:=address(logop);
w3:=address(b.usercat);
transport(.w2.,w1,w3);
w2:=b.topcore-512;
w2-!length(termdescr);
goto newsegm;
end;
w0:=-2;
goto exit;
termfound:
b.termdescr:=w2;
testout(.w3.,w0:=!length(termdescr),w1:=w2,w2:=68);
process(w1:=1);
w2:=b.termdescr;
w0:=segm;
exit:
w3:=return;
end;
end; ! scancat !
\f
body of checkprot
begin
label bad_passw, exit, found;
incode
text(11) pass:="pass",newpass:="newpass",emptytext:="",
pass2:="password", passtxt:=">password ";
ref password,return;
begin
return:=w3;
password:=w2; ! addr of correct password !
compare(.w3.,w0:=8,w1,w2:=address(pass));
if w0 <> 0 then
begin
compare (.w3., w0:=8, w1, w2:=address(pass2));
if w0=0 then goto found;
compare(.w3.,w0:=8,w1,w2:=address(emptytext));
if w0 <> 0 then
begin
!test 25;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto exit;
end;
w2:=w1; ! addr of read passw:= addr of empty param !
end else
begin
found:
w2:= w1+8; ! addr of password param !
end;
w1:=password;
compare(.w3.,w0:=8,w1,w2);
if w0 <> 0 then
begin
compare (.w3., w0:=8, w1:=address(emptytext), w2);
w1:= b.userentry;
if w0<>0 then ! password param <> empty !
begin
bad_passw:
!test 26;
outtext(.w3.,w0:=8'31,w1,w2:=13); ! bad password !
goto exit;
end else
if w0:=(w1).state = -3 then goto bad_passw
else
begin ! password must be typed invisible !
(w1).state:= w0:= -3; ! awaiting password !
(w1).bufrel:= w0:= (w1).buflength;
w2:= (w1).buffer + w0; ! start addr !
(w1).buflength:= w0:= 8;
copy (.w3., w0, w1:=address(passtxt), w2);
testout (.w3., w0, w1, w2:=0);
checkdevice (.w3., w0, w1:=b.userentry);
b.passmode:= w0; ! 0 = console (deviceno=2)
2 = other terminal !
w0:= (w1).bufrel;
-(w0);
send (.w3., w0, w1, w2:=20480);
(w1).bufrel:= w0:= (w1).bufrel + 8;
-(w0);
(w1).buflength:= w3:= b.maxbuf - (w1).bufrel;
send (.w3., w0, w1, w2:=12288+b.passmode);
! read password without echo, mode=2 !
link(.w3.,w1,w2:=address(b.waitqfst));
w3:= address(b.usercat);
monitor(10); ! release usercat !
goto b.continue;
end;
end;
compare(.w3.,w0:=8,w1:=address(newpass),w2+8);
if w0 <> 0 then
begin
compare(.w3.,w0:=8,w1:=address(emptytext),w2);
if w0 <> 0 then
begin
!test 27;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto exit;
end;
w2:=0; ! rewrite:= false !
end else
begin
w1:=w2+8;
if w0:=(w1).word < 0 then
begin
!test 28;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto exit;
end;
copy(.w3.,w0:=8,w1:=w2+8,w2:=password);
w2:=1; ! rewrite:= true !
end;
w1:=0;
exit:
w3:=return;
end;
end; ! checkprot !
\f
body of checkdevice
begin
incode
double w12;
word return;
begin
w12:= f2;
return:= w3;
w3:=74; ! ref to name table !
w3:=(w3).word+4; ! ref to proc.descr. of device 2 !
w2:=(w3).word+2; ! - - - name - - !
w1:=(w1).peripheral;
if w1<0 then -(w1); ! ref to proc.descr. of terminal !
w1+2; ! - - - name - - !
compare(.w3., w0:=8, w1, w2);
if w0<>0 then w0:=2;
f2:=w12;
w3:=return;
end;
end; ! checkdevice !
end; ! login !
\f
body of out
begin
label return;
record cont_ans ( word stat,l_id,perif,buftimer,pool);
incode
word savew0;
double savef3;
byte temop,temmode:=0;
ref first,last;
word simlocid;
text(28) simtxt:="'2''2' out '10'";
array(1:8) answ of word;
text(14) emptytext:="",namebuf:="";
byte op1:=106,mode1:=0; ! lookup term !
word locid,peri;
begin
savew0:= w0;
savef3:= f3;
compare(.w3.,w0:=8,w1+8,w2:=address(emptytext));
if w0<>0 then
begin
!test 29;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto return;
end;
w0:= (w1:=b.userentry).peripheral;
peri:=w0;
w1:= address(op1);
w3:= address(b.t_mdul);
monitor(16); ! send message !
w1:= b.lastuser;
monitor(18); ! wait answer !
if w0 or (w1).stat<>1 then
begin ! terminal not known !
!test 30;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=14); ! not connected !
goto return;
end;
locid:= w0:= (w1).l_id;
simlocid:=w0;
copy(.w3.,w0:=8,w1:=(w1).pool+2,w2:=address(namebuf));
temop:=w0:=9; ! simulate input !
first:=w0:=address(simlocid);
w0+8;
last:=w0;
w1:=address(temop);
w3:=address(namebuf);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
!test 901;
op1:=w0:=102; ! remove link (soft) !
w1:=address(op1);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
!test 31;
if w0 or (w1).word = 1
then outtext(.w3.,w0:=8'30,w1:=b.userentry,w2:=12) ! terminal disconnected !
else outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=16); ! disconnection not ok !
return:
w0:= savew0;
f3:= savef3;
end;
end; ! out !
\f
body of control
begin
label error,found;
incode
ref string1,string2,string3,string4;
word savew0,savew1;
double savef3;
text(11) emptytext:="",all:="all";
byte temop,temmode;
word localid;
ref termpda;
byte bufs,timers;
ref poolpda;
word recfull,bytesfree,dummy,allcommand:=0;
byte stopop:=16,stopmode:=1;
text(20) stoptxt:="system closed";
byte empop:=16,empmode:=0;
text(20) emptxt:="system empty";
begin
savew0:=w0; ! control operation: 1=kill -1=lock
2=break -2=open
3=stop -3=halt
4=start !
savef3:=f3;
string1:=w1; w1+8;
string2:=w1; w1+8;
string3:=w1; w1+8;
string4:=w1;
!test 700;
w1:=address(b.operator);
w2:=string2;
compare(.w3.,w0:=8,w1,w2);
if w0<>0 then
begin
w1:=address(emptytext);
compare(.w3.,w0:=8,w1,w2);
if w0<>0 then
begin
compare(.w3.,w0:=8,w1,w2:=string3);
if w0 <> 0 then
begin
!test 33;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
end;
w3:=string2;
monitor(4); ! get process description !
!test 995;
if w0 = 0 then
begin
!test 34;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=15); ! process unknown !
goto error;
end;
w1:=b.lastuser;
w3:=b.userentry;
while w1-!length(userentry) >= b.firstuser do
begin
if w0 = (w1).internal then
if w2:=(w1).primdevi = (w3).peripheral then goto found;
end;
!test 35;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=15); ! process unknown !
goto error;
end;
! controlled by own terminal !
w1:=b.userentry;
if w0:=(w1).state = -1 then
begin
found:
if w3:=savew0 <= 0 then
begin
!test 36;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=7); ! forbidden !
link(.w3.,w1,w2:=address(b.activqfst));
w1:= -1;
goto error;
end;
case w3:=savew0 of
begin
begin ! user kill !
(w1).intervent:=w0:=3;
clean(.w3.,w1);
end;
begin ! user break !
break(.w3.,w1);
if w3:= b.syscond zeromask 2'010 then
begin
if w3:= (w1).peripheral>0 then w0:= -1
else w0:= 7;
end else w0:= 7;
(w1).intervent:=w0;
end;
begin ! stop !
link(.w3.,w1,w2:=address(b.waitqfst));
if w0:=(w1).messgot > 10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
(w1).messsend:=w0;
(w1).state:=w0:=0;
end;
begin ! start !
link(.w3.,w1,w2:=address(b.activqfst));
if w0:=(w1).messgot > 10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
(w1).messsend:=w0;
(w1).state:=w0:=0;
end;
end;
w1:=-1;
goto error;
end;
temop:=w0:=106; ! lookup terminal !
temmode:=w0:=0;
termpda:=w0:=(w1:=b.userentry).peripheral;
w1:=address(temop);
w3:=address(b.t_mdul);
monitor(16); ! send message !
monitor(18); ! wait answer !
if w0 or (w1).word <> 1 then
begin
!test 37;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=14); ! not connected !
goto error;
end;
w0:=poolpda;
w1:=b.firstuser-!length(userentry);
while w1+!length(userentry) < b.lastuser do
begin
if w0 = (w1).peripheral then goto found;
end;
!test 38;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=15); ! process unknown !
goto error;
end
else begin
! controlled by operator !
if w0:=(w1:=b.userentry).peripheral <> b.mainconsref then
begin
!test 39;
outtext(.w3.,w0:=8'31,w1,w2:=7); ! forbidden !
goto error;
end;
w1:=address(emptytext);
compare(.w3.,w0:=8,w1,w2:=string4);
if w0 <> 0 then
begin
!test 40;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
end;
if w0:=savew0 <= 0 then
begin
compare(.w3.,w0:=8,w1:=address(emptytext),w2:=string3);
if w0 <> 0 then
begin
!test 41;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
end;
if w0:=savew0 = -1 then ! lock !
begin
b.sysstate:=w0:=1;
w1:=b.lastuser;
w0:=0;
while w1-!length(userentry) >= b.firstuser do
begin
if w3:=(w1).internal > 0 then
if w3:=(w3).word = 0 then w0+1;
end;
if w0 = 0 then opmess(.w3.,w1:=address(empop),w2:=b.ownproc);
end else
if w0 = -2 then ! open !
begin
b.sysstate:=w0:=0;
end else
if w0 = -3 then ! halt !
begin
opmess(.w3.,w1:=address(stopop),w2:=b.ownproc);
end else
;
w1:=-1;
goto error;
end;
compare(.w3.,w0:=8,w1,w2:=string3);
if w0 = 0 then
begin
!test 42;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto error;
end;
w1:=b.firstuser-!length(userentry);
while w1+!length(userentry)<b.lastuser do
begin
!test 710;
savew1 :=w1;
w1:=(w1).internal+2;
compare(.w3.,w0:=8,w1,w2:=string3);
if w0 <> 0 then
begin
compare(.w3.,w0:=8,w1:=address(all),w2);
if w0 = 0 then allcommand:=w3:=1;
end;
w1:=savew1;
if w0=0 then
begin
if w3:=(w1).internal > 0 then
if w0:=(w3).word = 0 then
case w3:=savew0 of
begin
begin ! operator kill !
(w1).intervent:=w0:=4;
clean(.w3.,w1);
end;
begin ! operator break !
break(.w3.,w1);
if w3:= b.syscond zeromask 2'010 then
begin
if w3:= (w1).peripheral>0 then w0:= -1
else w0:= 8;
end else w0:= 8;
(w1).intervent:=w0;
end;
begin ! stop !
link(.w3.,w1,w2:=address(b.waitqfst));
if w0:=(w1).messgot > 10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
(w1).messsend:=w0;
(w1).state:=w0:=0;
end;
begin ! start !
if w0:=(w1).class+b.timerloss < b.batchclass then
begin ! link to front of batch queue !
if w1 <> b.batchqfst then link(.w3.,w1,w2:=address(b.batchqfst));
end else link(.w3.,w1,w2:=address(b.activqfst));
if w0:=(w1).messgot > 10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
(w1).messsend:=w0;
(w1).state:=w0:=0;
end;
end;
w1:=-1;
if w0:=allcommand <> 1 then goto error;
w1:=savew1;
end;
end;
!test 43;
if w0:=allcommand <> 1
then outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=15) ! process unknown !
else w1:=-1;
goto error;
end;
w1:=-1;
error:
w0:=savew0;
f3:=savef3;
end;
end; ! control !
\f
body of empty
begin
incode
word savew0;
double savef3;
begin
savew0:=w0;
savef3:=f3;
w1:=-1;
w0:=savew0;
f3:=savef3;
end;
end; ! empty !
\f
body of calldev
begin
label syntaxerror,exit;
record callparam (word pkind,pvalue);
incode
word savew0,work;
double savef3;
ref string1,string2,string3,string4,string5,string6;
text(11) emptytext:="",start:="start",proc;
begin
savew0:=w0;
savef3:=f3;
string1:=w1; w1+8;
string2:=w1; w1+8;
string3:=w1; w1+8;
string4:=w1; w1+8;
string5:=w1; w1+8;
string6:=w1;
if w0:=string2.pkind <> -1 then goto syntaxerror;
compare(.w3.,w0:=8,w1:=string3,w2:=address(emptytext));
if w0 = 0 then goto syntaxerror;
w1:=string2.pvalue;
w3:=string3;
monitor(54); ! create peripheral process !
!test 111;
if w0 <> 0 then
if w0 <> 3 then
begin
!test 44;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=17); ! call not accepted !
goto exit;
end;
copy(.w3.,w0:=8,w1:=address(emptytext),w2:=string3);
include(.w3.,w1:=string1);
if w1 <> -1 then goto exit;
compare(.w3.,w0:=8,w1:=string4,w2:=address(emptytext));
if w0 = 0 then
begin
w1:=-1;
goto exit;
end;
compare(.w3.,w0:=8,w1,w2:=address(start));
if w0 = 0 then
begin
copy(.w3.,w0:=8,w1:=string4,w2:=string1);
copy(.w3.,w0,w1:=string5,w2:=string2);
copy(.w3.,w0,w1:=string6,w2:=string3);
copy(.w3.,w0,w1:=address(emptytext),w2:=string4);
control(.w3.,w0:=4,w1:=string1);
goto exit;
end;
syntaxerror:
!test 45;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
exit:
w0:=savew0;
f3:=savef3;
end;
end; ! calldev !
\f
body of include
begin
label exit;
record param(word pkind,pvalue);
incode
text(11) proc,emptytext:="";
double savef3;
ref string1,string2,string3;
word work,savew0;
begin
savew0:=w0;
savef3:=f3;
string1:=w1; w1+8;
string2:=w1; w1+8;
string3:=w1;
compare(.w3.,w0:=8,w1,w2:=address(emptytext));
if w0 <> 0 then
begin
!test 46;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto exit;
end;
w1:=string2;
if w0:=(w1).pkind <> -1 then
begin
!test 47;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=2); ! syntax !
goto exit;
end;
w3:=b.lastuser;
w2:=address(proc);
while w3-!length(userentry) >= b.firstuser do
begin
if w1:=(w3).internal > 0 then
begin
work:=w3;
if w0:=(w1).word = 0 then
begin
copy(.w3.,w0:=8,w1+2,w2);
w3:=w2;
w1:=string2.pvalue;
monitor(12); ! include user !
if w0 <> 0 then
begin
!test 48;
outtext(.w3.,w0:=8'31,w1:=b.userentry,w2:=18); ! include not accepted !
goto exit;
end;
end;
w3:=work;
end;
end;
w1:=-1;
exit:
w0:=savew0;
f3:=savef3;
end;
end; ! include !
end; ! syscommand !
\f
comment break
when a process is too cpu bound or when the terminal operator asks for
it, the system will provoke a break of the process (break 8 = parent break)
this is done by modifying the process using the dumped registers in the
process description and then restart the process in its break routine
;
body of break
begin
label exit;
record dumparea(word r0,r1,r2,r3,exep,instr,cause);
incode
double savef1,savef3;
word bufferrel,savedic;
text(14) childname,terminal;
byte ioop,iomode:=0;
word first,last,segmnt;
begin
savef1:=f1;
savef3:=f3;
if w0:=(w1).intervent = 0 then
begin
if w0:=(w1).messgot > 10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
if w0:=b.syscond zeromask 2'010 then
if w0:=(w1).peripheral > 0 then
begin
(w1).state:= w0:= 3;
(w1).state2:= w0:= -1;
startstop (.w3., w0:=0, w1); ! stop !
w1:= (w1).internal+2; ! ref process name !
scancat (.w3., w0, w1, w2:=0);
if w0 < 0 then
begin
if w0 = -3 then w2:=30 ! usercat reserv !
else w2:=3; ! ident illegal !
!test 50;
outtext (.w3., w0:=8'31, w1:=b.userentry, w2);
(w1).state2:= w0:= 1; ! waiting for remove process !
goto exit;
end;
b.procdescr:= w1;
w3:= address(childname);
f1:= savef1;
w2:= (w1).internal + 2; ! ref process name !
(w3).name1:= f1:= (w2).name1;
(w3).name2:= f1:= (w2).name2;
w2:= b.procdescr;
w0:= (w2).procub1; ! user base from soscat !
w1:= (w2).procub2;
monitor(72); ! reset catalog base = user base !
link (.w3., w1:=b.userentry, w2:=address(b.activqfst));
goto exit;
end;
(w1).intervent:=w0:=-1;
w2:=(w1).internal+b.relintrpt;
if w0:=(w2).word >= b.fstcore then
begin comment interrupt address is set;
savedic:=w0+16;
w0:=(w2).word;
w0-b.fstcore;
bufferrel:=w3:=w0 extract 9;
segmnt:=w0 lshift -9 + (w1).swopsegm;
ioop:=w0:=3;
w1:=address(ioop);
w3:=address(b.swname);
w0:=b.topcore;
last:=w0;
w0-1022;
first:=w0;
monitor(16); comment send message;
w1:=b.lastuser;
monitor(18); comment wait answer;
key (0):= w0; ! test 0 !
f1:=savef1;
w3:=address(childname);
w2:=(w1).internal+2;
(w3).name1:=f1:=(w2).name1;
(w3).name2:=f1:=(w2).name2;
f1:=savef1;
w1:=(w1).internal+b.reldump;
w2:=first+bufferrel;
copy(.w3.,w0:=16,w1,w2);
(w2).cause:=w0:=8;
(w2).exep:=w0:=0;
w0:=savedic;
savedic:=w1:=(w2).instr;
(w2).instr:=w0;
testout(.w3.,w0:=16,w1:=w2,w2:=1);
w3:=address(childname);
monitor(62); comment modify process;
(w1).instr:=w0:=savedic;
ioop:=w0:=5;
w1:=address(ioop);
w3:=address(b.swname);
monitor(16); comment send message;
w1:=b.lastuser;
monitor(18); comment wait answer;
f1:=savef1;
(w1).state:=w0:=0;
link(.w3.,w1,w2:=address(b.activqfst));
goto exit;
end;
end;
comment kill because of no reaction after break;
startstop(.w3.,w0:=0,w1);
clean(.w3.,w1);
exit:
w3:= address(b.usercat);
monitor(10); ! release usercat !
f1:=savef1;
f3:=savef3;
end;
end; ! break !
\f
comment parentmess
the use of devices (not accessible directly from the user-processes)
and the control of the processes themselves is partially based on parent
messages. this procedure takes the actions corresponding to the possible kinds
of parent messages - these possible kinds are:
break
finis terminates the current processing and removes the process
mount
;
body of parentmessage
begin
label unknown,mounted,mountmess;
record cont_ans ( word stat,l_id,perif);
incode
double w01,w23;
text(11) string1;
ref firstdev:=74,lastdev:=76;
byte temop,temmode;
word locid,dum1,dum2;
text(14) poolname;
array (1:8) answ of word;
word zero:=0;
byte emptyop:=16,emptymode:=0;
text(20) emptytxt:="system empty";
begin
w01:=f1; w23:=f3;
w0:=0;
b.timermess:=w0;
startstop(.w3.,w0:=0,w1);
if w0:=(w2).operation=2 then comment finismessage;
begin
send(.w3.,w0:=1,w1,w2:=0);
if w0:=(w1).state2<=0 then
begin
(w1).intervent:=w0:=2;
clean(.w3.,w1);
end
else begin
!test 49;
outtext(.w3.,w0:=8'70,w1,w2:=(w1).intervent+19);
! removed after break / finis / user kill / opt.kill /
time exc. / term.error / user break / opt.break !
copy(.w3.,w0:=8,w1:=(w1).internal+2,w2:=address(b.procname));
w1:=(w1:=b.userentry).internal+76;
f1:=(w1).double;
w3:=address(zero);
monitor(72); ! set sos catalog base to stdbase of child !
!test 440;
w3:=address(b.t_mdul);
monitor(64); ! remove pseudo process !
w3:=address(b.p_mdul);
monitor(64); ! remove pseudo process !
!test 441;
w3:=address(zero);
f1:=b.startbase;
monitor(72); ! reset sos own cat base !
w1:=b.ownproc+26;
b.freebufs:=w0:=b.freebufs-(w1).byte;
w3:=address(b.procname);
monitor(64); comment remove internal process;
!test 110;
b.freebufs:=w0:=b.freebufs+(w1).byte;
copy(.w3.,w0:=6,w1:=address(b.procname),w2:=address(poolname)+2);
w0:= 0;
b.baseevent:= w0;
copy(.w3.,w0:=2,w1:=b.ownproc+2,w2:=address(poolname));
temop:=w0:=102; ! remove link (soft) !
locid:=w1:=0;
w3:=address(poolname);
w1:=address(temop);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
temop:=w0:=92; ! remove pool !
w3:=address(b.t_mdul);
w1:=address(temop);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
copy(.w3.,w0:=2,w1:=address(b.t_mdul),w2:=address(poolname));
w1:=address(temop);
w3:=address(b.t_mdul);
monitor(16); ! send message !
answ(w1:=1);
monitor(18); ! wait answer !
w1:=b.userentry;
link(.w3.,w1,w2:=address(b.waitqfst));
w0:=0;
(w1).peripheral:=w0;
(w1).internal:=w0;
(w1).messsend:=w0;
(w1).messgot:=w0;
(w1).intervent:=w0;
if w0:=b.sysstate = 1 then
begin
w1:=b.lastuser;
w0:=0;
while w1-!length(userentry) >= b.firstuser do
begin
if w3:=(w1).internal > 0 then
if w3:=(w3).word = 0 then w0+1;
end;
if w0 = 0 then opmess(.w3.,w1:=address(emptyop),w2:=b.ownproc);
end;
end;
end else
if w0=4 then comment break message;
begin
send(.w3.,w0:=1,w1,w2:=0);
if w0:=(w1).intervent = -1 then (w1).intervent:=w0:=1;
if w0 = 0 then (w1).intervent:=w0:=1;
clean(.w3.,w1);
end else
if w0 = 14 then comment mount message;
begin
mountmess:
copy(.w3.,w0:=8,w1:=w2+16,w2:=address(string1));
w3:=address(string1);
monitor(4); ! get process description !
if w0 <> 0 then
begin
w1:=word(firstdev);
while w1+2 <= word(lastdev) do
begin
if w0 = (w1).word then
begin
w3:=address(b.procname);
w1-word(firstdev) lshift -1;
monitor(12); ! include user !
if w0 = 0 then
begin
f1:=w01;
(w1).state:=w0:=0;
link(.w3.,w1,w2:=address(b.activqfst));
send(.w3.,w0:=1,w1,w2:=0);
goto mounted;
end;
end;
end;
end;
f1:=w01;
f3:=w23;
goto unknown;
mounted:
end else
if w0 = 32 then goto mountmess
else
begin comment parent message unknown;
unknown:
(w1).state:=w0:=0;
w2:=(w1).internal;
opmess(.w3.,w1:=b.message+8,w2);
if w0:=(w1).word onemask 1 then w2:=address(b.waitqfst)
else w2:=address(b.activqfst);
f1:=w01;
link(.w3.,w1,w2);
send(.w3.,w0:=1,w1,w2:=0);
end;
w3:=address(zero);
f1:=b.startbase;
monitor(72); ! rset sos own catalog base !
f1:=w01; f3:=w23;
end;
end; ! parentmessage !
\f
comment clean
;
body of clean
begin
incode
double savef1, savef3;
double corelimits;
byte buffers, areas;
byte internals:=0, fncmask:=1792;
byte protreg, protkey;
double maxbase, stdbase;
begin
savef1:=f1; savef3:=f3;
if w0:=(w1).messgot > 10 then
begin
(w1).buflength:=w2:=0;
send(.w3.,w0:=1,w1,w2);
end;
copy(.w3.,w0:=8,w1:=(w1).internal+2,w2:=address(b.procname));
w2:=b.fstcore; w3:=b.topcore;
corelimits:=f3;
protreg:=w3:=b.childpr;
protkey:=w3:=b.childpk;
w2:= b.ownproc;
buffers:= -(w3:=(w1:=w2+26).byte);
areas:= -(w3:=(w1:=w2+27).byte);
f1:= savef1;
w0:= (w1).internal;
maxbase:=f3:=(w1:=w0+72).double;
stdbase:=f3:=(w1:=w0+76).double;
w3:=address(b.procname);
monitor(64); comment remove internal;
!test 100;
w2:= b.ownproc;
buffers:= w0:= buffers+(w1:=w2+26).byte;
areas:= w0:= areas+(w1:=w2+27).byte;
w1:=address(corelimits);
monitor(56); comment create internal;
!test 102;
f1:=savef1;
monitor(4); comment lookup process;
(w1).internal:=w0;
(w1).state:=w0:=3;
(w1).state2:=w0:=1;
(w1).prio:=w0:=0;
(w1).class:=w0;
(w1).messsend:=w0;
(w1).messgot:=w0;
link(.w3.,w1,w2:=address(b.activqfst));
f1:=savef1;
f3:=savef3;
end;
end; ! clean !
\f
comment compare
;
body of compare
begin
incode
word savew1;
double savef3;
begin
savew1:=w1; savef3:=f3;
w3:=w1+w0;
w0:=0;
while w1<w3 do
begin
w0:=(w1).word;
w0-(w2).word;
w1+2;
w2+2;
if w0<>0 then w1:=w3;
end;
w1:=savew1;
f3:=savef3;
end;
end; ! compare !
\f
comment nextchar
;
body of nextchar
begin
label dummy1;
begin
if w1=0 then
if w2=(w3).stp then w1:=10 ashift 16 ! simulate 'nl' at end of buffer !
else begin
w1:=(w2).word;
w2+2;
end;
w0:=0;
f1 lshift 8;
if w0=13 then w0:= 10; ! convert <cr> to <nl> to avoid !
! syntax error reading in mode 2 !
end;
end;
end.
▶EOF◀