|
|
DataMuseum.dkPresents historical artifacts from the history of: RC3500 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC3500 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 29952 (0x7500)
Types: TextFileVerbose
Names: »tssupjob«
└─⟦a41ae585a⟧ Bits:30001842 SW-save af projekt 1000, Alarm-system
└─⟦72244f0ef⟧
└─⟦this⟧ »tssupjob«
job hj 3 200 time 11 0 area 10 size 100000
( message ts supervisor
source = copy 25.1
tssuplst = set 1 disc1
tssuplst = indent source mark lc
listc = cross tssuplst
o errors
message ts supervisor
pascal80 spacing.1200 codesize.1200 alarmenv source
o c
lookup pass6code
if ok.yes
( tssupbin = set 1 disc1
tssupbin = move pass6code
scope user tssupbin
; if ok.yes
; newjob linktssjob
)
tssuplst = copy listc errors
scope user tssuplst
convert errors
finis
)
\f
(*----------------------------------------------------*)
(* *)
(* ts supervisor *)
(* *)
(*----------------------------------------------------*)
process tssupervisor (
opsem: sempointer; (* allocator, operator *)
var sem : !ts_pointer_vector (* ts semaphores *)
);
const
version= "vers 3.06 /";
(*---------------------- externals -------------------------------*)
process timout ( opsem: sempointer;
var tim: !ts_pointer; t, m: integer );
external;
process tsconnector ( opsem: sempointer;
var tss, dc, nc, lam, tim, com : !sempointer;
var net, s1, s2, s3, s4: !ts_pointer );
external;
process at_handler ( opsem: sempointer;
var dca, tsa : macroaddr;
var sem : !ts_pointer_vector );
external;
process vc_handler ( opsem: sempointer;
var dca, tsa : macroaddr;
var sem : !ts_pointer_vector );
external;
process lam ( opsem: sempointer;
pu, level: integer;
var main_sem: !ts_pointer
);
external;
\f
const
maxroute = 12; (* for u3 routing *)
type (*----------------- options ------------------------------*)
grouptable = array (func_grp) of integer;
modulref = ( netc, vch, ath, traffic, nc, dc, tss, dummy, empty );
modulident = array (netc..ath) of byte;
modultable = array (modulref) of integer;
modulstate = array (modulref) of boolean;
modulroute = array (0..maxroute) of modulref;
leveltab = array (0..max_lam+1) of byte;
const (*-------------- options -------------------------------*)
traffic_id = 24; (* for time_out *)
nc_ident = 25;
dc_ident = 26;
microadr = modultable ( netc_mic_addr, vch_mic_addr, ath_mic_addr,
traffic_id, nc_ident, dc_ident, 0, 0, 0 );
book_id = modulident(1,2,3);
interval = modultable(tss_netc_time,tss_vch_time,tss_ath_time,
tss_nc_ltime,tss_nc_stime,tss_dc_stime,-1,-1,-1);
from = modulroute(tss,tss,netc,netc,ath,ath,4***vch,3***tss);
u3val= modulident(netc_route1, netc_route, netc_route);
\f
(*-------------------- op codes ---------------------------------*)
log_code = #h00; (* 0.0 *)
nb_code = #h10; (* 1.0 *)
refuse_code= #h12; (* 1.2 *)
dc_down = #h20; (* 2.0 *)
dc_up = #h21; (* 2.1 *)
nc_down = #h22; (* 2.2 *)
nc_up = #h23; (* 2.3 *)
ts_down = #h24; (* 2.4 *)
ts_up = #h25; (* 2.5 *)
vc_down = #h26; (* 2.6 *)
vc_up = #h27; (* 2.7 *)
at_down = #h28; (* 2.8 *)
at_up = #h29; (* 2.9 *)
newlam_code= #h9c; (* 9.12 *)
anslam_code= #h9d; (* 9.13 *)
new_addr_code= #hb0; (* 11.0 *)
new_ans_code = #hb1; (* 11.1 *)
nodetest_code= #hc0; (* 12.0 *)
nodeans_code= #hc1; (* 12.1 *)
input_code = #hc5; (* 12.5 *)
contest_code= #hc8; (* 12.8 *)
conansw_code= #hc9; (* 12.9 *)
(*---------------------- other constants -------------------------*)
maxno = 2*2*2*2; (* 4 bits *)
read_clock = 2;
write = 2;
by_father = 47; (* break parameter *)
forever = false;
label_length = label_size; (* size in words, length in bytes *)
testlength = label_length+2; (* length of testshape *)
free_sem_no = com_pool; (* free listen buffers are here *)
queue = tssup_int1;
done = tssup_int2;
supp_sem_no = tssup_int3; (* log buffers *)
\f
(*------------------------ message formats --------------------------*)
type
testshape = packed record (* for nodetest *)
head: alarmlabel;
data: array (1..5) of integer
end;
flawshape = packed record (* for 1.0 and 1.2 *)
head : alarmlabel;
data : alarmlabel
end;
note = packed record (* for broadcast *)
head: alarmlabel;
component: alarmnetaddr;
count: integer
end;
lammess = packed record (* for new lam *)
head: alarmlabel;
lam_num,
lam_level : integer
end;
\f
(*----------------------------------------------------------
variables section
----------------------------------------------------------*)
var
here : alarmnetaddr; (* my own addr updated by 11.00 *)
debug : integer:= 1; (* controls testoutput *)
cv, (* value of create *)
lost, (* num of loast messages *)
quelen, (* actual queuelength *)
maxqueue, (* max queuelength *)
queput, (* number of queings *)
nodetest_cnt : integer:=0; (* numb of nodetests send *)
running : modulstate := modulstate(5***true, false, 3***true);
ms1, (* a free buffer *)
ms : reference; (* mess arrived *)
console : zone; (**debug for output **)
(*----------------- for ts modules ----------------------*)
no : array (netc..ath) of integer;
suppool: pool no_req_supp of array (1..size_supp) of integer;
lamname : alfa := "lam00 ";
leveltable : leveltab := leveltab((max_lam+2) *** 0);
proc_lam : array(0..max_lam) of shadow;
proc_timeout,
proc_netcon,
proc_vchan,
proc_athan : shadow;
(*----------------- for timing ---------------------------*)
nc_long, nc_short, (* timeouts from 11.0 *)
cnt : integer;
netaddr: array (nc..dc) of alarmnetaddr;
module: modulref;
t_out, (* module timeouts *)
t_up : array (netc..dc) of reference; (* book and update *)
u_pool: pool no_tss_tim of updates;
t_pool: pool no_tss_tim of timers;
clockpool: pool 1 of ts_time; (**demo **)
clock_msg: reference;
(*---------------- end of data section -----------------------*)
\f
<*q q*>
(*------------------------ display -----------------------------*)
procedure display ( var msg: reference); (* write contents *)
const
lastword = 16;
type
abuf = record w: array(1..lastword) of integer end;
var
i,m : integer;
begin
lock msg as buf: abuf do
with buf do
begin
m:= (w(1)+1) div 2;
if m<7 then m:= 7;
if m>lastword then m:=lastword;
for i:= 1 to m do testout ( console," data ", w(i));
end;
end;
<*q q*>
\f
(*------------------------ gettime -----------------------------*)
function gettime : ts_time;
type
clock_form = record time: ts_time end;
begin
signal ( clock_msg, sem(timeout_sem_no).s^);
wait ( clock_msg, sem(done).w^);
lock clock_msg as buf : clock_form do gettime:= buf.time
end;
\f
(*--------------------- odd ------------------------------------*)
function odd ( number: integer ) : boolean;
begin
odd:= number mod 2 = 1
end;
\f
(*---------------------- send up ---------------------------*)
procedure send_up ( (* signals to net-con *)
var msg : reference; (* mess to be send *)
operation : byte ); (* op code *)
begin
msg^.u1:= write;
msg^.u3:= tss_route;
msg^.u4:= operation;
if ( debug mod 16 ) >= 8 then display ( msg);
signal ( msg, sem(netc_sem_no).s^ );
end;
\f
(*------------------------ to queue ------------------------------*)
procedure to_queue ( var msg : reference );
begin
count ( queput);
quelen:= quelen+1;
if quelen > maxqueue then maxqueue:= quelen;
signal ( msg, sem(queue).s^)
end;
\f
<* -- only used in nc
(*---------------------- nodetest --------------------------*)
procedure nodetest (
node : modulref ); (* node to be tested *)
var
try : reference; (* node test message *)
begin
sensesem ( try, sem(free_sem_no).w^);
if not nil ( try) then
begin
nodetest_cnt:= nodetest_cnt+1;
lock try as buf : testshape do
begin
with buf, head do
begin
no_of_by:= testlength;
rec:= netaddr(node);
send:= here;
result:= 0;
ts_add:= gettime;
end;
buf.data(1):= nodetest_cnt;
end;
send_up ( try, nodetest_code);
timerupdate ( t_up(node), interval(node),
sem(timeout_sem_no).s^, sem(done).w^ )
end
end;
*>
\f
(*---------------------- broadcast -------------------------*)
procedure broadcast ( (* send a broadcast message *)
var msg : reference; (* used for message *)
element : alarmnetaddr; (* unit in question *)
cnt : integer; (* counter in datapart *)
operation: byte; (* op code *)
recip : modulref); (* reveiver *)
const
broadlength = label_length+6;
begin
lock msg as buf : note do
with buf, head do
begin
no_of_by:= broadlength;
if recip = netc then rec:= netaddr(nc) else
begin
rec:= here;
rec.micro:= microadr(recip)
end;
send:= here;
result:= operation mod 2;
op_code:= operation;
ts_add:= gettime;
component:= element;
count:= cnt
end;
msg^.u1:= write;
if recip = netc then msg^.u3:= tss_route else msg^.u3:= netc_route1;
msg^.u4:= operation;
signal ( msg, sem(no(recip)).s^ )
(* end *)
end;
\f
(*--------------------- start timeout -------------------------*)
procedure start_timeout;
begin
if nil ( proc_timeout ) then
begin
cv:= link ("timout ", timout );
cv:= create ( "timout ",
timout ( opsem,
sem(timeout_sem_no), time_out_unit, timeout_l),
proc_timeout, tim_size);
if cv = 0 then start ( proc_timeout, tim_pri)
else
begin
testout ( console,"timeoutstart", cv);
cv:= unlink ( timout)
end
end
end;
\f
(*------------------- start lam --------------------------------*)
procedure start_lam ( nr, level: byte );
begin
if nil ( proc_lam(nr)) then
begin
lamname(4):= chr ( ord("0") + nr div 10);
lamname(5):= chr ( ord("0") + nr mod 10);
cv:= create ( lamname,
lam ( opsem, pu_no, level,
sem(lam_sem_no+nr) ),
proc_lam(nr), lam_size);
if cv = 0 then
begin
start ( proc_lam(nr), lam_pri);
leveltable(nr):= level
end
else testout ( console,"lam start ", cv);
end;
end;
\f
(*------------------- start netcon ----------------------------*)
procedure start_netcon;
begin
if nil ( proc_netcon ) then
begin
(*
cv:= link ("netconnector", netconnector );
*)
cv:= link ("tsconnector ", tsconnector);
cv:= create ( "tsconnector ",
tsconnector (
opsem,
sem(tssup_sem_no).s,
sem(dc_sem_no).s,
sem(nc_sem_no).s,
sem(lam_sem_no).s,
sem(timeout_sem_no).s,
sem(com_pool).w,
sem(netc_sem_no),
sem(net_int1), sem(net_int2), sem(net_int3),
sem(net_int4)
),
proc_netcon, netc_size);
if cv = 0 then start ( proc_netcon, netc_pri)
else
begin
testout ( console,"netcon start", cv );
cv:= unlink ( tsconnector)
end;
end
end;
\f
(*----------------------- start vchandler ---------------------*)
procedure start_vchan;
begin
if nil ( proc_vchan ) then
begin
cv:= link ( "vc_handler ", vc_handler);
cv:= create ( "vc_handler ",
vc_handler ( opsem,
netaddr(dc).macro,
here.macro,
sem
),
proc_vchan, vch_size);
if cv = 0 then start ( proc_vchan, vch_pri)
else
begin
testout ( console, "vc_han start", cv);
cv:= unlink ( vc_handler)
end
end
end;
\f
(*------------------------ start athandler -----------------------*)
procedure start_athan;
begin
if nil ( proc_athan ) then
begin
cv:= link ( "at_handler ", at_handler);
cv:= create ( "at_handler ",
at_handler ( opsem,
netaddr(dc).macro,
here.macro,
sem
),
proc_athan, ath_size);
if cv = 0 then start ( proc_athan, ath_pri )
else
begin
testout ( console, "at_han start", cv);
cv:= unlink ( at_handler )
end
end
end;
\f
(*---------------------- module timeout --------------------*)
procedure module_timeout (
var msg : reference; (* received mess *)
var res : modulref); (* becomes dummy *)
var
cnt,
who : integer;
elem : alarmnetaddr;
bm1, bm2 : reference; (* 2 empty buffers *)
begin
sensesem ( bm1, sem(free_sem_no).w^);
if not nil ( bm1) then
sensesem ( bm2, sem(free_sem_no).w^);
if nil ( bm2 ) then
begin (* try later *)
if not nil ( bm1) then return ( bm1);
to_queue ( msg)
end else
begin
lock msg as buf : timers do who:= buf.object;
elem.macro:= here.macro;
elem.micro:= who;
case who of
<*
netc_mic_addr:
begin (* net-connector stopped, so remove it
and start a new one *)
break ( proc_netcon, by_father);
unlink ( tsconnector);
remove ( proc_netcon);
(* get released buffers. *)
start_netcon;
nodetest ( nc);
timerbook ( t_up(netc), msg, interval(netc), who,
sem(timeout_sem_no).s^, sem(done).w^)
end;
*>
ath_mic_addr:
begin
if running(ath) then
begin
broadcast ( bm1, elem, 0, at_down, netc);
broadcast ( bm2, elem, 0, at_down, vch )
end;
running(ath):= false;
timerbook ( t_up(ath), msg, -1, who,
sem(timeout_sem_no).s^, sem(done).w^)
end;
vch_mic_addr:
begin
if running(vch) then
begin
broadcast ( bm1, elem, 0, vc_down, netc);
broadcast ( bm2, elem, 0, vc_down, ath );
running(vch):= false
end;
timerbook ( t_up(vch), msg, -1, who,
sem(timeout_sem_no).s^, sem(done).w^)
end;
<*
traffic_id:
begin (* nc or paxnet stopped *)
nodetest ( nc);
timerbook ( t_up(traffic), msg, -1, who,
sem(timeout_sem_no).s^, sem(done).w^)
end;
*>
nc_ident:
begin (* nc down *)
if running(nc) then
begin
broadcast ( bm1, elem, 0, nc_down, ath);
broadcast ( bm2, elem, 0, nc_down, vch);
running(dc):= false;
running(nc):= false
end;
timerbook ( t_up(nc), msg, -1, who,
sem(timeout_sem_no).s^, sem(done).w^)
end;
<*
dc_ident:
begin (* dc down *)
if running(dc) then
begin
broadcast ( bm1, elem, dc_down, ath);
broadcast ( bm2, elem, dc_down, vch);
running(dc):= false
end;
timerbook ( t_up(dc), msg, -1, who,
sem(timeout_sem_no).s^, sem(done).w^);
end;
*>
otherwise
begin
return ( bm1);
return ( bm2)
end
end
end;
res:= dummy
end; (* of module timeout *)
\f
(*--------------------- route ---------------------------*)
function route (
microadr : integer (* addr of local module *)
) : modulref; (* the selected module *)
begin
if microadr >= at_addr_limit then route:= ath else
if microadr >= vc_addr_limit then route:= vch else
if microadr = vch_mic_addr then route:= vch else
if microadr = ath_mic_addr then route:= ath else
if microadr = netc_mic_addr then route:= netc else
if microadr = tss_mic_addr then route:= tss else
route:= dc
end;
\f
(*----------------------- waitlog ----------------------------------*)
procedure waitlog ( (* fetch a free logbuffer *)
var msg : reference ); (* a msg for log *)
begin
(* allocator may be used later ! *)
if open ( sem(supp_sem_no).w^) then
begin
wait ( msg, sem(supp_sem_no).w^ );
while msg^.u3 = dummy_route do
begin
return ( msg);
wait ( msg, sem(supp_sem_no).w^ )
end;
end
end;
\f
(*---------------------- make log --------------------------*)
procedure make_log ( var msg : reference );
(* makes a copy of msg.data and send to dc. *)
const
logleng = 2*size_supp - ( 2+label_length);
rawleng = 2*size_listen-2;
type
logshape = packed record
head : alarmlabel;
data : array (1..logleng) of byte;
end;
rawshape = packed record
bytes : integer;
rawdata : array (1..rawleng) of byte;
end;
var
cnt : 1..rawleng;
length : integer;
logm : reference;
begin
lock msg as head : alarmlabel do head.op_code:= msg^.u4;
(* if ( logmin <= msg^.u4) and ( msg^.u4 <= logmax ) then +++++++
begin -------------------------------------------------------*)
waitlog ( logm );
if nil ( logm) then to_queue ( msg) else
begin
if msg^.u4 = refuse_code then (* make copy 1.0 *)
begin
lock logm as copy: flawshape do
lock msg as buf: flawshape do
begin
copy:= buf;
copy.head.rec.macro:= netaddr(dc).macro;
copy.head.rec.micro:= dc_erh_mic_addr;
end;
send_up ( logm, nb_code)
end
else
begin
lock logm as log : logshape do
lock msg as buf : rawshape do
begin
length:= label_length;
if ( buf.bytes > label_length )
and ( buf.bytes <= rawleng )
and ( buf.bytes <= logleng ) then length:= buf.bytes;
with log, head do
begin
no_of_by:= label_length+length;
rec.macro:= netaddr(dc).macro;
rec.micro:= dc_log_mic_addr;
send:= here;
update:= insert_code;
ts_add:= gettime;
end;
for cnt:= 1 to length do log.data(cnt):= buf.rawdata(cnt);
end;
send_up ( logm, log_code)
end
end
(* end --------------------------------------- ++++++++++++++++*)
end;
\f
(*--------------------- refuse --------------------------*)
procedure refuse ( var msg : reference; cause : result_range );
(* send opcode 1.2 back *)
const
newleng = 2*label_length+2;
var
receiver : macroaddr;
who : integer;
begin
lock msg as buf : flawshape do
with buf do
begin
data:= head;
data.op_code:= msg^.u4;
with head do
begin
no_of_by:= newleng;
rec:= send;
receiver:= rec.macro;
who:= rec.micro;
send:= here;
result:= cause;
ts_add:= gettime
end
end;
if receiver <> here.macro then
send_up ( msg, refuse_code)
else
begin
if who < vc_addr_limit then msg^.u3:= netc_route1
else msg^.u3:= netc_route;
msg^.u4:= refuse_code;
case route ( who) of
ath: signal ( msg, sem(ath_sem_no).s^);
vch: signal ( msg, sem(vch_sem_no).s^);
otherwise
send_up ( msg, refuse_code)
end;
end;
end;
\f
(*---------------- downwards ----------------------------*)
procedure downwards (
var msg : reference; (* a msg from net *)
var modul : modulref); (* tells what to do later *)
var
receiver : macroaddr;
from : alarmnetaddr;
xmt_dc : 0..15;
who : integer;
begin
lock msg as head : alarmlabel do
with head do
begin
receiver:= rec.macro;
who := rec.micro;
xmt_dc := send.macro.dc_addr;
from := send;
end;
if ( debug mod 32 ) >= 16 then display ( msg);
if receiver <> here.macro then (* not for me *)
if msg^.u4 = refuse_code then modul:= empty else
begin
refuse ( msg, unknown_receiver);
modul:= dummy
end
else
begin (* addr ok *)
if (xmt_dc <> here.macro.dc_addr) and
( here.macro <> macroaddr(0,0,0) ) and
running(dc) then make_log ( msg );
if from = netaddr(dc) then running(dc):= true;
if nil ( msg) then modul:= dummy else
begin
modul:= route ( who );
if who < vc_addr_limit then msg^.u3:= netc_route1;
end
end
end; (* of downwards *)
\f
(*---------------- upwards -------------------------*)
procedure upwards (
var msg : reference; (* a msg from ath or vch *)
var modul : modulref); (* tells what to do later *)
var
receiver : macroaddr;
who : integer;
begin
lock msg as head : alarmlabel do
begin
head.ts_add:= gettime;
receiver:= head.rec.macro;
who:= head.rec.micro
end;
if receiver <> netaddr(dc).macro then (* log *)
if ( here.macro <> macroaddr(0,0,0) ) and
running(dc) then make_log ( msg );
if nil ( msg) then modul:= dummy else
begin
if receiver = here.macro then
begin
modul:= route ( who );
if modul < tss then
if who < vc_addr_limit then msg^.u3:= netc_route1
else msg^.u3:= netc_route
end
else modul:= netc
end
end;
\f
(*----------------------- rec broadcast ---------------------------*)
procedure rec_broadcast ( var msg : reference );
(* handle received broadcast *)
type
ncaddr = record
dcpart : 0..15;
ncpart : 0..63
end;
var
cnt : integer;
unit : alarmnetaddr;
own_dc, unit_dc : 0..15;
own_nc, unit_nc : ncaddr;
bm1, bm2 : reference;
begin
sensesem ( bm1, sem(free_sem_no).w^);
if nil ( bm1) then
begin (* try later *)
to_queue ( msg)
end else
begin
lock msg as buf: note do
with buf do
begin
unit:= component;
cnt := count
end;
own_dc:= here.macro.dc_addr;
own_nc.dcpart:= own_dc;
own_nc.ncpart:= here.macro.nc_addr;
unit_dc:= unit.macro.dc_addr;
unit_nc.dcpart:= unit_dc;
unit_nc.ncpart:= unit.macro.nc_addr;
case msg^.u4 of
dc_down: if unit_dc = own_dc then running(dc):= false;
dc_up: if unit_dc = own_dc then running(dc):= true;
nc_down: if unit_nc = own_nc then running(nc):= false;
nc_up: if unit_nc = own_nc then running(nc):= true
otherwise
end;
case msg^.u3 of
netc_route,
netc_route1: begin (* from net *)
testout ( console, "from net ", msg^.u3);
broadcast ( bm1, unit, cnt, msg^.u4, vch);
broadcast ( msg, unit, cnt, msg^.u4, ath)
end;
at_route,
at_route1: begin (* from at *)
testout ( console, "from at ", msg^.u3);
broadcast ( bm1, unit, cnt, msg^.u4, netc);
broadcast ( msg, unit, cnt, msg^.u4, vch)
end;
vca_route,
vca_route1,
vci_route,
vci_route1: begin (* from vc *)
testout ( console, "from vc ", msg^.u3);
broadcast ( bm1, unit, cnt, msg^.u4, netc);
broadcast ( msg, unit, cnt, msg^.u4, ath)
end
otherwise
begin
return ( bm1);
return ( msg)
end
end; (* case *)
end
end; (* of rec broadcast *)
\f
(*------------------------ new lam ---------------------------------*)
procedure new_lam ( var msg : reference );
(* start or check lam driver incarnation *)
const
top = max_lam+1;
var nr, level : integer;
index : 0..top;
begin
if msg^.u4 = newlam_code then
begin
(*q if debug >= 1 then testout ( console,"new lam ", msg^.u4); q*)
lock msg as buf: lammess do with buf, head do
begin
result:= rejected;
nr:= lam_num;
level:= lam_level;
index:= 0;
while leveltable(index) <> level do index:= index+1;
if update = start_code then (* start lam driver *)
begin
if index = top then start_lam ( nr, level);
if leveltable(nr) = level then result:= accepted;
end else
begin (* stop lam driver *)
if leveltable(nr) = level then
begin
remove ( proc_lam(nr));
leveltable(nr):= 0;
result:= accepted
end
end;
rec:= send;
send:= here;
ts_add:= gettime;
end;
send_up ( msg, anslam_code)
end else refuse ( msg, unknown_opcode)
end;
\f
(*----------------------- rec returned ----------------------------*)
procedure rec_returned ( var msg : reference );
(* handle op codes 1.0 1.2 *)
begin
(* not yet specified *)
if debug >= 1 then testout ( console, "returned ", msg^.u4);
if debug >= 1 then
lock msg as buf: flawshape do
with buf do
testout ( console, "orig op-code", data.op_code);
count ( lost);
return ( msg )
end;
\f
(*----------------------- tss var update ----------------------------*)
procedure var_update ( var msg : reference );
(* the buffer contains a new ts-macro-address *)
type
table = packed record
head : alarmlabel;
adr : macroaddr;
cn: integer
end;
begin
if msg^.u4 = new_addr_code then
begin
lock msg as buf : table do with buf, head do
begin
here.macro:= adr;
netaddr(dc).macro.dc_addr:= here.macro.dc_addr;
netaddr(nc).macro.dc_addr:= here.macro.dc_addr;
netaddr(nc).macro.nc_addr:= here.macro.nc_addr;
debug:= cn;
(* generate answer *)
rec:= send;
send:= here;
ts_add:= gettime;
result:= accepted;
end;
(*
if debug>=3 then display ( msg);
*)
running(dc):= true;
running(nc):= true;
send_up ( msg, new_ans_code);
end else refuse ( msg, unknown_opcode)
end; (* of table update *)
\f
(*----------------------- watch -----------------------------------*)
procedure watch ( var msg : reference );
(* nodetest received, so send node test answer *)
var
node : modulref;
node_up : byte;
begin
if msg^.u4 = nodetest_code then (* node test *)
begin
lock msg as buf : testshape do
with buf, head do
begin
rec:= send;
send:= here;
result:= accepted;
ts_add:= gettime;
data(2):= quelen;
data(3):= queput;
data(4):= maxqueue;
data(5):= lost;
end;
send_up ( msg, nodeans_code)
end else
if msg^.u4 = nodeans_code then (* node test answer *)
begin
lock msg as buf: testshape do
if buf.head.send.macro.nc_addr = 0 then
begin node_up:= dc_up; node:= dc end else
begin node_up:= nc_up; node:= nc end;
timerupdate ( t_up(node), -1,
sem(timeout_sem_no).s^, sem(done).w^);
if not running(node) then (* node running again *)
begin
(* broadcast ( ms1, netaddr(node), node_up, ath);
broadcast ( msg, netaddr(node), node_up, vch); *)
running(node):= true
end;
return ( msg);
end else refuse ( msg, unknown_opcode)
end; (* of watch *)
\f
(*------------------------- tss function --------------------------*)
procedure tss_function ( var msg : reference );
(* msg : received message for ts-supervisor *)
var
group : func_grp;
begin
(*q if debug>= 3 then testout ( console,"tss gets ", msg^.u4); q*)
group:= msg^.u4 div maxno;
case group of
0: (* returned log *)
begin return ( msg);
testout ( console, "log retur ", lost );
end;
1: (* returns *) rec_returned ( msg );
2: (* broadcast *) rec_broadcast( msg );
9: (* new lam *) new_lam ( msg );
11: (* new addr *) var_update ( msg );
12: (* watch *) watch ( msg )
otherwise (* refuse *) refuse ( msg, unknown_opcode)
end;
end; (* of tss function *)
\f
(*-------------------- exception ---------------------------------*)
procedure exception ( cause : integer);
begin
trace ( cause);
if not nil ( ms1) then return ( ms1);
if not nil ( ms ) then refuse ( ms, breaked);
sensesem ( ms, sem(queue).w^);
while not nil ( ms) do
begin
refuse ( ms, breaked);
sensesem ( ms, sem(queue).w^)
end;
for module:= netc to ath do
begin
wait ( ms, sem(free_sem_no).w^);
broadcast ( ms, here, lost, ts_down, module)
end;
repeat
wait ( ms, sem(tssup_sem_no).w^);
refuse ( ms, breaked)
until false;
end;
\f
(*---------------------------------------------------------------*)
(* *)
(* main program *)
(* *)
(*---------------------------------------------------------------*)
begin
testopen ( console, own.incname, opsem);
if debug>=0 then testout ( console, version, al_env_version);
here.macro:= macroaddr(0,0,0);
here.micro:= tss_mic_addr;
netaddr(dc):= here;
netaddr(nc):= here;
(**demo get buffers for log and clock **)
for cnt:= 1 to no_req_supp do
begin
alloc ( ms, suppool, sem(supp_sem_no).s^);
ms^.u3:= tss_route;
signal ( ms, sem(supp_sem_no).s^ )
end;
alloc ( clock_msg, clockpool, sem(done).s^);
clock_msg^.u1:= read_clock;
clock_msg^.u3:= tss_route;
no(netc):= netc_sem_no;
no( vch):= vch_sem_no;
no( ath):= ath_sem_no;
cv:= link ("lam ", lam);
if cv <> 0 then testout ( console, "link lam = ", cv);
start_lam ( 0, 5);
start_timeout;
(*q if debug>=1 then testout ( console,"timermodul ", 800 ); q*)
for module:= netc to dc do
begin
alloc ( t_out(module), t_pool, sem(tssup_sem_no).s^ );
alloc ( t_up(module), u_pool, sem(done).s^);
t_up(module)^.u3:= tss_route;
timerbook ( t_up(module), t_out(module), -1, microadr(module),
sem(timeout_sem_no).s^, sem(done).w^)
end;
start_netcon;
start_vchan;
start_athan;
(* kun for ts-connector
wait ( ms, sem(free_sem_no).w^);
lock ms as head: alarmlabel do
begin
head.rec:= here;
head.send:= here;
end;
send_up ( ms, new_ans_code); *)
(*q if debug>=1 then testout ( console,"init ok ", 820 ); q*)
\f
(*------------------ main loop -------------------------*)
repeat (* until forever *)
if open ( sem(queue).w^) then sensesem ( ms1, sem(free_sem_no).w^);
if open ( sem(queue).w^) and not nil ( ms1) then (* take queue *)
begin
wait ( ms, sem(queue).w^);
quelen:= quelen-1
end else
begin
(*q if (debug mod 8)>=4 then testout ( console,"wait mysem ", 960 ); q*)
wait ( ms, sem(tssup_sem_no).w^ );
end;
(*q if (debug mod 8)>=4 then testout ( console,"handle ", msg_ready); q*)
case ms^.u3 of
dummy_route: module:= empty;
tim_route,
tim_route1: module_timeout ( ms, module );
netc_route: downwards ( ms, module);
netc_route1:
begin
testout ( console, "netc-route1 ", ms^.u4);
module:= dc;
end;
otherwise upwards ( ms, module );
end;
case module of
dummy: ; (* no action *)
empty: return ( ms ); (* no data *)
tss: tss_function ( ms );
vch: signal ( ms, sem(vch_sem_no).s^ );
ath: signal ( ms, sem(ath_sem_no).s^ );
netc: begin
if ( debug mod 16 ) >= 8 then display ( ms);
signal ( ms, sem(netc_sem_no).s^ );
end
otherwise refuse ( ms, not_found)
end; (* case *)
until forever
end . (* of ts supervisor program *)
«eof»