|
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: 42240 (0xa500) Types: TextFile Names: »tnet2«
└─⟦2c55ea56f⟧ Bits:30001844 SW-save af projekt 1000, Alarm-system └─⟦6b41451d2⟧ └─⟦this⟧ »tnet2«
prefix return_empty; procedure return_empty (var msg: reference; ok: boolean); begin msg^.u1 := input_msg; msg^.u4 := empty_buf; if ok then msg^.u2 := result_ok else msg^.u2 := result_error; return (msg); end; <* ************************************************* *> prefix return_full; procedure return_full (var msg: reference; ok: boolean); begin msg^.u1 := output_msg; msg^.u4 := full_buf; if ok then msg^.u2 := result_ok else msg^.u2 := result_error; return (msg); end; <* ************************************************ *> (* this routine has been incorporated in stdlib revision 6 prefix outnl; procedure outnl (var z: zone); begin outchar (z, nl); outend (z); end; (* *) <* ************************************************ *> prefix outtime; procedure outtime (var z: zone; t: timetype); var min, sec : integer; begin with t do begin outinteger (z, hours, 2); outchar (z, '.'); min := seconds div 60; sec := seconds mod 60; outinteger (z, min div 10, 1); outinteger (z, min mod 10, 1); outchar (z, '.'); outinteger (z, sec div 10, 1); outinteger (z, sec mod 10, 1); end; end; <* ************************************************ *> prefix print_msg; procedure print_msg (var z: zone; var msg: reference; text: alfa); begin lock msg as buf:stdpart do with buf do begin outtext (z, text); outinteger (z, msg^.u1, 2); outinteger (z, msg^.u2, 2); outinteger (z, msg^.u3, 2); outinteger (z, msg^.u4, 2); outinteger (z, msg^.size, 4); outinteger (z, first, 4); outinteger (z, last, 4); outinteger (z, next, 4); outnl (z); end; end; <* print_msg *> <* ************************************************ *> process fpadriver(n: integer; var pdescr: proc_descrs; var sems: sem_arr); const <* definition of control-commands *> reset_contr = 0; repeat_int = 2; start_read = 3; <* definition of status-bits *> st_parity_error = 1; st_reset_received = 2; st_disconnected = 4; st_autoload_received = 8; st_receive_end = 16; st_timeout = 32; st_transmit_end = 64; <* definition of start char *> block_start = #b10000110; <* does not interfere with ncp-chars *> <* definition of timers *> read_period = 15; <* seconds *> write_period = 15; <* seconds *> after_error = 2; <* seconds pause *> var chm : reference; msg : reference; dummy : integer; start_char: integer; mainsem : ^ semaphore; ch_ptr : ^ array (1..maxint) of byte; test : boolean; s : integer; <* last status read *> result : integer; <* suggested result *> zout : zone; out_pool : pool 1 of opbuffer; procedure make_sense; begin sense (s, 0, chm); if (s <> st_receive_end) and (s <> st_transmit_end) then begin result := result_error; control (reset_contr, chm); end else result := result_ok; end; begin openopzone (zout, own.secret_pointer^(opsem), ref(zout.free), 1, out_pool, 2,7,0,0); with pdescr(n) do begin dummy := reservech (chm, first_devno_fpa - 1 + inc, 0); mainsem := ref (sems(sem)); definetimer (true); make_sense; channel chm do repeat <* forever *> wait (msg, mainsem^); test := pdescr(n).testval <> 0; if test then print_msg (zout, msg, 'after wait:'); case msg^.u4 of empty_buf: begin own.timer := read_period; lock msg as buf: stdpart do with buf, header do begin repeat controlclr(start_read, chm); inword (start_char, chm); controlclr (repeat_int, chm); inbyteblock(next, first, last, msg, chm); make_sense; until (own.timer = 0) or ((s and st_reset_received) = 0); last := next - 1; end; if test then print_msg (zout, msg, 'after read:'); return_full (msg, (start_char = block_start) and (result = result_ok) and (not timedout)); end; full_buf: begin own.timer := write_period; ch_ptr := ptraddr(msg^.start); lock msg as buf: stdpart do with buf do begin outwordclr (0 <* irrel start char *>, chm); outbyteblock (next, first, last-1, msg, chm); controlclr (repeat_int, chm); outwordclr (256 + ch_ptr^(last), chm); end; make_sense; if test then print_msg (zout, msg, 'after write:'); return_empty (msg, (result = result_ok) and (not timedout)); if result <> result_ok then begin own.timer := after_error; waitt; end; end; end; <* case *> until doomsday; end; <* with pdescr *> end; <* fpadriver *> <* *********************************************************** *> process hdlcdriver (n: integer; var pdescr: proc_descrs; var sems: sem_arr); const <* control commands *> dma_reset = 0*256; trm_control = 3*256; mode_control = 5*256; datalength = 7*256; setadrl = 8*256; setadrh = 9*256; setcntl = 10*256; setcnth = 11*256; setfll = 12*256; setflh = 13*256; setmsel = 14*256; start_rec = 16*256; start_xmit = 17*256; enable = 18*256; modem_control= 19*256; step_pointer3= 20*256; step_pointer0= 21*256; <* sense registers *> statusreg0 = 0*256; countreg0 = 24*256; <* xmit flags (high) *> set_int = 8; set_teom = 4; clear_tsom = 2; <* xmit flags (low) *> trm_valid = 2; <* rec flags (high) *> exp_reom = 4; <* rec flags (low) *> rec_valid = 2; <* status bits *> rec_errors = #h40fc; xmit_errors = #h1080; <* modem bits *> txe = 2; rxe = 1; <* timer periods *> read_period = 15; <* seconds *> write_period = 10; <* seconds *> var mainsem : ^ semaphore; msg : reference; dev : reference; dummy : integer; ok : boolean; remcount : integer; status : integer; zout : zone; out_pool : pool 1 of opbuffer; procedure dodma (fh, fl, ctrl, period, mask: integer); type word = record h, l: byte end; procedure asgn = asgnintset (var w: word; i: integer); external; var w: word; begin lock msg as buf: stdpart do with buf do begin control (setmsel + msg^.start.base.mem_no, dev); control (fh, dev); asgn (w, first-last-1); control (setcnth + w.h, dev); control (setcntl + w.l, dev); asgn (w, uadd(msg^.start.disp, first)); control (setadrh + w.h, dev); control (setadrl + w.l, dev); control (fl, dev); control (step_pointer3, dev); control (ctrl, dev); own.timer := period; controlclr (enable, dev); if timedout then begin control (dma_reset, dev); ok := false; remcount := 0; end else begin sense (remcount, countreg0, dev); sense (status, statusreg0, dev); control (step_pointer0, dev); ok := (status and mask) = 0; end; last := last + remcount; end; end; <* dodma *> begin <* body of hdlc *> with pdescr(n) do begin openopzone (zout, own.secret_pointer^(opsem), ref(zout.free), 1, out_pool, 2,7,0,0); dummy := reservech (dev, first_devno_hdlc + inc - 1, 0); definetimer (true); mainsem := ref (sems(sem)); control (dma_reset, dev); control (trm_control + 0, dev); control (mode_control + 0, dev); control (datalength + 0, dev); control (modem_control + txe + rxe, dev); channel dev do repeat wait (msg, mainsem^); if testval <> 0 then print_msg (zout, msg, 'after wait:'); case msg^.u4 of empty_buf: begin dodma ( setflh + exp_reom, setfll + rec_valid, setfll + 0-0-0, <* dummy *> read_period, rec_errors); if testval <> 0 then print_msg (zout, msg, 'after read:'); return_full (msg, ok); end; full_buf: begin dodma( setflh + set_int + set_teom + clear_tsom, setfll + 0-0-0, start_xmit + trm_valid, write_period, xmit_errors); if testval <> 0 then print_msg (zout, msg, 'after write:'); return_empty (msg, ok); end; end; until doomsday; end; end; <* hdlc driver *> <* *********************************************************** *> process gcidriver (n: integer; var pdescr: proc_descrs; var sems: sem_arr); const read_period = 15; <* seconds *> write_period = 10; <* seconds *> var mainsem : ^ semaphore; msg : reference; dev : reference; dummy : integer; newlast : integer; ok : boolean; zout : zone; out_pool : pool 1 of opbuffer; procedure get_last (var last: integer); var dummy : integer; begin with pdescr (n) do begin repeat if testval <> 0 then begin outtext (zout, 'wait eoi#'); outnl (zout); end; controlclr (0, dev); inword (dummy, dev); until eoi or (own.timer = 0); if own.timer = 0 then last := 0 else sense (last, 0, dev); if testval <> 0 then begin outtext (zout, 'newlast=#'); outinteger (zout, last, 1); outnl (zout); end; end; end; begin <* body of gci-driver *> with pdescr(n) do begin openopzone (zout, own.secret_pointer^(opsem), ref(zout.free), 1, out_pool, 2,7,0,0); dummy := reservech (dev, first_devno_gci + inc - 2 * ((inc + 1) and 1), 0); definetimer (true); mainsem := ref (sems(sem)); channel dev do repeat <* forever *> wait (msg, mainsem^); if testval <> 0 then print_msg (zout, msg, 'after wait:'); case msg^.u4 of empty_buf: begin repeat own.timer := read_period; <* get into sync *> repeat get_last (newlast); until (own.timer = 0) or (newlast > 0); ok := false; if newlast > 0 then lock msg as buf: stdpart do with buf do begin controlclr (0, dev); inwordblock (next, first, newlast or 1, msg, dev); last := newlast; ok := next > last; end; if testval <> 0 then print_msg (zout, msg, 'after read:'); get_last (newlast); ok := ok and (not timedout); until newlast <> -1; return_full (msg, (newlast = 0) and ok); end; full_buf: begin own.timer := write_period; repeat lock msg as buf: stdpart do with buf do begin controlclr (-1, dev); controlclr (last, dev); outwordblock (next, first, last or 1, msg, dev); <* wait for the last interrupt *> repeat sense (dummy, 0, dev); until ((dummy and 1) = 1) or (own.timer = 0); ok := next > last; end; if testval <> 0 then print_msg (zout, msg, 'after write:'); until ok or (own.timer = 0); controlclr (0, dev); return_empty (msg, (not timedout) and ok); end; end; <* buffer type *> until doomsday; end; <* with pdescr *> end; <* gcidriver *> <* *********************************************************** *> process onteldriver (n: integer; var pdescr: proc_descrs; var sems: sem_arr); const <* control-commands to ontel *> reset = 0; ready = 1; start_read = 4; keyb_locked = 5; start_write = 8; end_write = 10; answer_void = 32; <* status_bits from ontel *> ontel_ready_xmit = 2; <* dummy delay periods *> loop_count = 1000; <* timer-periods *> read_period = 15; <* seconds *> write_period = 10; <* seconds *> var request_sem : ^ semaphore; reply_sem : ^ semaphore; msg : reference; ont_dev : reference; saved_header : net_header; transaction_no : integer; ontel_status : integer; cpu : byte; new_req_demanded: boolean; accepted : boolean; dummy : integer; i : integer; zout : zone; out_pool : pool 1 of opbuffer; procedure busy_loop (count: integer); begin for count := count downto 0 do <* nothing but wait ... *>; end; procedure control_no_ack (c: integer; var dev: reference); begin control (c, dev); busy_loop (loop_count); end; begin <* body of ontel driver *> with pdescr(n) do begin openopzone (zout, own.secret_pointer^(opsem), ref(zout.free), 1, out_pool, 2,7,0,0); dummy := reservech (ont_dev, first_devno_ontel + inc - 1, 0); definetimer (true); request_sem := ref (sems(sem)); reply_sem := ref (sems(sem+1)); transaction_no := 0; control_no_ack (reset, ont_dev); channel ont_dev do repeat <* forever *> repeat <* until acceptable reply *> case ctrwaitis (keyb_locked, msg, reply_sem^) of a_interrupt: begin <* terminal has timed out *> sense (ontel_status, 0, ont_dev); if testval <> 0 then begin outtext (zout, 'ontel void#'); outhex (zout, ontel_status, 6); outnl (zout); end; accepted := (ontel_status and ontel_ready_xmit) <> 0; if accepted then begin <* ontel wants to send a new transaction *> <* I don't know, if ontel really wants the following *> control_no_ack (keyb_locked, ont_dev); control_no_ack (answer_void, ont_dev); new_req_demanded := true; end; end; a_semaphore: begin <* reply has arrived *> lock msg as buf: stdpart do with buf, header do begin if testval <> 0 then begin outtext ( zout, 'reply :#'); outinteger (zout, addr(1), 4); outinteger (zout, transaction_no, 4); outnl (zout); end; accepted := addr(1) = transaction_no; if accepted then begin saved_header := header; own.timer := write_period; controlclr (start_write, ont_dev); outbyteblock (next, size_stdpart, last, msg, ont_dev); outword (255, ont_dev); controlclr (end_write, ont_dev); sense (ontel_status, 0, ont_dev); <* maybe retrans, if wanted *> if timedout then control_no_ack (reset, ont_dev); end; end; return_empty (msg, true); end; <* reply *> end; <* case *> until accepted; repeat controlclr (ready, ont_dev); sense (ontel_status, 0, ont_dev); if testval <> 0 then begin outtext (zout, 'ontel int#'); outhex (zout, ontel_status, 6); outnl (zout); end; until (ontel_status and ontel_ready_xmit) <> 0; wait (msg, request_sem^); lock msg as buf: request_buffer do with buf, req_head, header do begin own.timer := read_period; controlclr (start_read, ont_dev); inbyteblock (next, size_stdpart, last, msg, ont_dev); if timedout then begin control_no_ack (reset, ont_dev); new_req_demanded := true; end else begin if testval <> 0 then begin outtext (zout, 'request:#'); if testval > 1 then for i := 1 to next - size_stdpart do begin if i mod 10 = 1 then if i <> 1 then begin outnl (zout); outfill (zout, sp, 8); end; outinteger (zout, ord(req_buf(i)), 4); end; outnl (zout); end; cpu := ord (req_buf(1)); if (cpu = #h30) or (cpu = #h3f) then begin <* any rc8000 (or master), i.e. new request *> new_req_demanded := false; routing_mode := new_request; service_kind := das_search; req_buf(1) := chr (#h31); <* simulate cpu # 1 *> end else begin <* specific rc8000, i.e. next-request *> header := saved_header; routing_mode := next_request; end; if not new_req_demanded then last := next - 1; cur := 1; transaction_no := (transaction_no + 1) mod 128; addr(1) := transaction_no; end; end; <* lock msg *> if new_req_demanded then signal (msg, request_sem^) else return_full (msg, true); until doomsday; end; <* with pdescr *> end; <* onteldriver *> <* *********************************************************** *> process consdriver (n: integer; var pdescr: proc_descrs; var sems: sem_arr); const textlgth = 20; rc8000_period = 15; <* seconds *> var msg : reference; emptysem : ^ semaphore; fullsem : ^ semaphore; i : integer; transaction_no : integer; rep_count : integer; saved_last : integer; before_first : boolean; expecting_answ : boolean; zin, zout : zone; in_pool : pool 1 of opbuffer; out_pool : pool 1 of opbuffer; in_sem : semaphore; act : activation; latest_time : integer; <* phony function... must be replaced later *> function spec_waitst (var msg: reference; var sem: semaphore): activation; begin repeat sensesem (msg, sem); until (own.timer = latest_time) or (not nil(msg)); if nil(msg) then spec_waitst := a_delay else spec_waitst := a_semaphore; end; label rep_input; procedure alarm (text: array (1..textlgth) of char); var i: integer; begin for i := 1 to textlgth do if text(i) = '#' then i := textlgth else outchar (zout, text(i)); outnl (zout); end; begin openopzone (zin, own.secret_pointer^(opsem), ref(in_sem), 1, in_pool, 1,7,0,0); openopzone (zout, own.secret_pointer^(opsem), ref(zout.free), 1, out_pool, 2,7,0,0); before_first := true; transaction_no := 0; with pdescr(n) do begin emptysem := ref (sems(sem)); fullsem := ref (sems(sem+1)); definetimer(true); expecting_answ := false; rep_count := 0; repeat <* forever *> if expecting_answ then if testval = 0 then act := waitst (msg, fullsem^) else act := spec_waitst (msg, fullsem^) else wait (msg, emptysem^); if not (nil(msg)) then case msg^.u4 of empty_buf: begin lock msg as buf: request_buffer do with buf, req_head, header do rep_input: begin if rep_count <= 0 then begin opin (zin); opwait (zin, in_pool); i := 0; repeat if i < size_request then i := i + 1; inchar (zin, req_buf(i)); until req_buf(i) = nl; saved_last := i + size_stdpart; <* check syntax *> case req_buf(1) of 's': begin if i<3 then begin alarm ('type more data#'); goto rep_input; end; case req_buf(2) of 'a': service_kind := serv_a; 'b': service_kind := serv_b; 'c': service_kind := serv_c; otherwise begin alarm ('no such service#'); goto rep_input; end; end; routing_mode := new_request; before_first := false; i := 3; end; 'p': begin if before_first then begin alarm ("don't start with p#"); goto rep_input; end; routing_mode := next_request; i := 2; end; otherwise begin alarm ('only s or p#'); goto rep_input; end; end; rep_count := 0; while (rep_count <= 3200) and (req_buf(i) in (.'0'..'9'.)) do begin rep_count := rep_count * 10 + ord(req_buf(i)) - ord('0'); i := i + 1; end; own.timer := 32000; <* prepare for time-test *> end; <* if rep_count <= 0 *> <* send request *> last := saved_last; cur := 1; transaction_no := (transaction_no + 1) mod 128; addr(1) := transaction_no; end; return_full (msg, true); if testval = 0 then begin own.timer := rc8000_period; <* expect answer soon *> latest_time := 0; end else latest_time := own.timer - rc8000_period; expecting_answ := true; end; full_buf: begin <* reply arrived *> lock msg as buf: reply_buffer do with buf, reply_head, header do if addr(1) = transaction_no then begin if testval = 0 then own.timer := 0; expecting_answ := false; rep_count := rep_count - 1; if rep_count <= 0 then begin if testval <> 0 then begin outtext (zout, 'time was:#'); outinteger (zout, 32000-own.timer,3); outtext (zout, 'seconds#'); outnl (zout); own.timer := 0; end; for i := 1 to last - size_stdpart do if reply_buf(i) <> nul then outchar (zout, reply_buf(i)); outend (zout); end; end else alarm ('wrong answer#'); return_empty (msg, true); end; end else begin alarm ('time out#'); own.timer := 0; expecting_answ := false; before_first := true; rep_count := 0; end; until doomsday; end; <* with pdescr *> end; <* consdriver *> <* ****************************************************** *> process server (n: integer; var pdescr: proc_descrs; var sems: sem_arr); var msg : reference; answ : reference; emptysem : ^ semaphore; fullsem : ^ semaphore; serv : serv_range; dist : dist_range; rout : routing_modes; begin with pdescr(n) do begin emptysem := ref (sems(sem)); fullsem := ref (sems(sem+1)); wait (answ, emptysem^); lock answ as data: cap_buffer do with data, cap_head, header do begin for serv := 1 to max_serv do for dist := 0 to max_dist do cap(serv, dist) := 0; if testval = 0 then cap(serv_b, 0) := 1 else cap(serv_c, 0) := 1; last := size_cap_buffer - 1; routing_mode := inform; cur := 1; end; return_full (answ, true); repeat <* forever *> wait (msg, fullsem^); lock msg as buf: stdpart do with buf, header do rout := routing_mode; case rout of reply: ; <* nothing *> next_request, new_request: begin wait (answ, emptysem^); lock msg as buf1: request_buffer do lock answ as buf2: request_buffer do begin buf2.req_head.last := buf1.req_head.last; buf2.req_head.header := buf1.req_head.header; buf2.req_buf := buf1.req_buf; end; lock answ as buf: reply_buffer do with buf, reply_head, header do begin routing_mode := reply; cur := cur + 1; end; return_full (answ, true); end; inform: ; <* nothing *> end; return_empty (msg, true); until doomsday; end; end; <* server *> <* ******************************************************* *> process router (var semvect: system_vector); const poll_accuracy = 2; <* number of seconds between poll_update *> poll_period = 10; <* seconds *> no_of_outbufs = 8; var zin, zout: zone; in_pool : pool 1 of opbuffer; out_pool: pool no_of_outbufs of opbuffer; local_time : timetype := timetype (0, 0); var pdescr : proc_descrs; sems : sem_arr; children : array (1..max_process) of record child : shadow; end; code_descr: array (prockinds) of record name : alfa; size : integer; prio : integer; inc_count: integer; end; <* definition of child images *> process fpa(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; process hdlc(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; process gci(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; process cons(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; process ontel(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; process bbm(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; process server(n: integer; var pdescr: proc_descrs; var sems: sem_arr); external; var mainsem : ^ semaphore; msg : reference; test : boolean; ports : array (ports_range) of record insem : ^ semaphore; outsem : ^ semaphore; pp : 0 .. max_port; <* index in 'portx' *> proc_no : 0 .. max_process; <* index in 'pdescr', used only for printouts *> outstandings: integer; <* note: offset by one... *> max_outs : integer; <* note: offset by one... *> last_status : byte; end; portx : array (port_range) of record deliver_status : boolean; <* true, when status must be sent *> busy : boolean; <* true, while status is being sent *> pno : ports_range; <* index in 'ports' *> poll_time : integer; end; capability : array (port_range, serv_range, dist_range) of boolean; dists : array (serv_range) of record last_p : port_range; min_dist: array (port_range) of 0..top_dist+1; end; status_pool : pool max_status of cap_buffer; large_pool : pool max_largepool of reply_buffer; small_pool : pool max_smallpool of request_buffer; procedure testput (text: alfa; var m: reference); var i : integer; begin print_msg (zout, m, text); lock m as buf: stdpart do with buf, header do begin outinteger (zout, receiver, 7); outinteger (zout, routing_mode, 2); outinteger (zout, service_kind, 2); outinteger (zout, cur, 3); if pdescr(0).testval > 1 then for i := 1 to cur do outinteger (zout, -addr(i), 1); end; outnl (zout); end; procedure alarm (text: alfa); begin outtext (zout, '*** error: #'); outtext (zout, text); outnl (zout); exception (0); end; procedure clean_pool (var poo: pool 1); var msg: reference; begin while openpool (poo) do begin alloc (msg, poo, mainsem^); case msg^.u4 of empty_buf: return_full (msg, false); full_buf : return_empty (msg, false); end; end; end; procedure clean_sem (sem: ^ semaphore); var msg : reference; begin sensesem (msg, sem^); while not nil(msg) do begin release (msg); sensesem (msg, sem^); end; end; procedure kill_all (from, upto: integer); var msg : reference; dummy : integer; p : ports_range; begin if upto > max_process then upto := max_process; if (from > 0) and (from <= max_process) then repeat with children(from) do if not nil(child) then begin remove(child); for p := 1 to max_ports do with ports(p) do if proc_no = from then begin clean_sem (insem); clean_sem (outsem); end; end; from := from + 1; until from > upto; <* provoke cleanup of buffers *> dummy := reservech (msg, 0, 0); clean_pool (small_pool); clean_pool (large_pool); end; <* kill_all *> procedure break_all (cause, from, upto: integer); begin if upto > max_process then upto := max_process; if (from > 0) and (from <= max_process) then repeat with children(from) do if not nil(child) then break (child, cause); from := from + 1; until from > upto; end; procedure run_all (from, upto: integer); var res : integer; name_n : alfa; i, n : integer; begin kill_all (from, upto); if upto > max_process then upto := max_process; if (from > 0) and (from <= max_process) then repeat with children(from), pdescr(from), code_descr(kind) do begin name_n := name; i := alfalength; n := inc; repeat name_n(i) := chr (n mod 10 + ord('0')); n := n div 10; i := i - 1; until n = 0; repeat name_n(i) := '_'; i := i-1; until name_n(i) <> sp; case kind of fpa_kind : res := create (name_n, fpa (from, pdescr, sems), child, size); hdlc_kind : res := create (name_n, hdlc (from, pdescr, sems), child, size); gci_kind : res := create (name_n, gci (from, pdescr, sems), child, size); cons_kind : res := create (name_n, cons (from, pdescr, sems), child, size); ontel_kind : res := create (name_n, ontel (from, pdescr, sems), child, size); bbm_kind : res := create (name_n, bbm (from, pdescr, sems), child, size); server_kind: res := create (name_n, server(from, pdescr, sems), child, size); end; if res <> 0 then alarm ('create#'); start (child, prio); end; from := from + 1; until from > upto; end; procedure test_all (t, from, upto: integer); begin if upto > max_process then upto := max_process; if (from > -1) and (from <= max_process) then repeat with pdescr(from) do testval := t; from := from + 1; until from > upto; end; procedure print_portx (from, upto: integer); begin if upto > max_port then upto := max_port; if (from > 0) and (from <= max_port) then begin outtext (zout, 'p port #'); outtext (zout, 'poll st.#'); outtext (zout, ' busy#'); outnl (zout); repeat outinteger (zout, from, 2); outchar (zout, ':'); with portx(from) do begin outinteger (zout, pno, 4); outinteger (zout, poll_time, 5); if deliver_status or busy then begin if deliver_status then outtext (zout, ' true #') else outtext (zout, ' false#'); if busy then outtext (zout, ' true#') else outtext (zout, ' false#'); end; end; outnl (zout); from := from + 1; until from > upto; end; end; procedure print_ports (from, upto: integer); begin if upto > max_ports then upto := max_ports; if (from > 0) and (from <= max_ports) then begin outtext (zout, ' p outs max#'); outtext (zout, ' inp outp#'); outnl (zout); repeat outinteger (zout, from, 2); outchar (zout, ':'); with ports(from) do begin outinteger (zout, outstandings - 1, 4); outinteger (zout, max_outs - 1, 4); outinteger (zout, proc_no, 4); if insem <> outsem then outinteger (zout, proc_no+1, 4); if last_status <> result_ok then outtext (zout, ' down#'); end; outnl (zout); from := from + 1; until from > upto; end; end; procedure print_proc (from, upto: integer); begin if upto > max_process then upto := max_process; if (from > 0) and (from <= max_process) then begin outtext (zout, ' i name #'); outtext (zout, ' #'); outtext (zout, ' inc sem tst#'); outtext (zout, ' state#'); outnl (zout); repeat outinteger (zout, from, 2); outchar (zout, ':'); outchar (zout, sp); with pdescr(from), children(from) do begin outtext (zout, code_descr(kind).name); outinteger (zout, inc, 4); outinteger (zout, sem, 4); outinteger (zout, testval, 4); if nil(child) then outtext (zout, ' removed#'); end; outnl (zout); from := from + 1; until from > upto; end; end; procedure write_all (from, upto: integer); begin if upto > max_sem then upto := max_sem; if (from > -1) and (from <= max_sem) then begin outtext (zout, 'sem state#'); outnl (zout); repeat outinteger(zout, from, 3); if open(sems(from)) then outtext (zout, ' open#') else if locked(sems(from)) then outtext (zout, ' locked#') else outtext (zout, ' passive#'); outnl (zout); from := from + 1; until from > upto; end; end; procedure print_cap (from, upto: integer); var p : port_range; serv : serv_range; dist : dist_range; begin if (upto <= 0) or (upto > max_port) then upto := max_port; if from <= 0 then from := 1; if from <= max_port then for p := from to upto do begin outtext (zout, 'port no =#'); outinteger (zout, p, 2); outtext (zout, ', outstand.=#'); with portx(p), ports(pno) do outinteger (zout, outstandings, 2); outnl (zout); for serv := 1 to max_serv do begin outtext (zout, 'service #'); outchar (zout, chr(64 + serv)); outchar (zout, ','); outinteger (zout, dists(serv).min_dist(p),2); outchar (zout, ':'); for dist := 0 to max_dist do if capability (p, serv, dist) then outtext (zout, ' * #') else outtext (zout, ' . #'); outnl (zout); end; end; end; procedure conversation; var ch : char; val, from, upto : integer; procedure read_from_to; begin ininteger (zin, from); ininteger (zin, upto); end; procedure read_val_from_to; begin ininteger (zin, val); read_from_to; end; procedure print_f_t (text: alfa); begin outtext (zout, text); outtext (zout, ' <from> <to>#'); outnl (zout); end; procedure print_v_f_t (text: alfa); begin outtext (zout, text); outtext (zout, ' <value>#'); outtext (zout, ' <from> <to>#'); outnl (zout); end; begin opanswer (msg, zin); opwait (zin, in_pool); repeat <* next command *> repeat inchar (zin, ch) until ch <> sp; case ch of 'r': <* run <from> <to> *> begin read_from_to; run_all (from, upto); end; 'b': <* break <val> <from> <to> *> begin read_val_from_to; break_all (val, from, upto); end; 'k': <* kill <from> <to> *> begin read_from_to; kill_all (from, upto); end; 't': <* test <val> <from> <to> *> begin read_val_from_to; test_all (val, from, upto); end; 'x': <* print portx <from> <to> *> begin read_from_to; print_portx (from, upto); end; 'p': <* print procs <from> <to> *> begin read_from_to; print_ports (from, upto); end; 'i': <* print pdescr (incarnations) <from> <to> *> begin read_from_to; print_proc (from, upto); end; 'w': <* write <from> <to> *> begin read_from_to; write_all (from, upto); end; 'c': <* capability <from> <to> *> begin read_from_to; print_cap (from, upto); end; 'd': <* date <hour> <min> <sec> *> begin read_val_from_to; if (val >= 0) and (val < 24) and (from >= 0) and (from < 60) and (upto >= 0) and (upto < 60) then if val + from + upto > 0 then with local_time do begin hours := val; seconds := from * 60 + upto; end; outtime (zout, local_time); outnl (zout); end; '?', 'h': <* help *> begin print_f_t ('r: run#'); print_v_f_t ('b: break#'); print_f_t ('k: kill#'); print_v_f_t ('t: test#'); print_f_t ('x: listportx#'); print_f_t ('p: listports#'); print_f_t ('i: listpdescr#'); print_f_t ('w: listsems#'); print_f_t ('c: list capab.#'); outtext (zout, 'd: date #'); outtext (zout, '<hour> <min>#'); outtext (zout, ' <sec>#'); outnl (zout); end; otherwise <* blind command *> end; repeat inchar (zin, ch) until (ch=nl) or (ch=';'); until ch=nl; opin (zin); end; <* conversation *> procedure initialize; var i, p, inc_no, port_no, sem_no: integer; serv : serv_range; dist : dist_range; procedure def_code (k: prockinds; var p: process_descriptor; n: alfa; s: integer; pr: minpriority..maxpriority); var dummy : integer; begin with code_descr(k) do begin name := n; size := s; prio := pr; inc_count := 0; end; dummy := link (n, p); end; procedure def_inc (k: prockinds); begin with pdescr(inc_no) do with code_descr(k) do begin kind := k; inc_count := inc_count + 1; inc := inc_count; testval := 0; sem := sem_no; end; inc_no := inc_no + 1; end; procedure def_port (insems: integer; max: integer; erlang: boolean); begin with ports (port_no) do begin insem := ref (sems(sem_no)); outstandings := 1; <* note: offset by one... *> max_outs := max + 1; <* note: offset by one... *> last_status := result_ok; proc_no := inc_no - 1; sem_no := sem_no + insems; if erlang then begin pp := p; with portx(p) do begin deliver_status := false; busy := false; pno := port_no; poll_time := poll_period; end; p := p + 1; end else pp := 0; end; end; procedure out_port (outsems: integer); begin with ports (port_no) do if outsems <> 0 then outsem := ref (sems(sem_no)) else outsem := insem; sem_no := sem_no + outsems; port_no := port_no + 1; end; procedure alloc_bufs (n: integer; var p: pool 1); var msg : reference; i : integer; begin for i := 1 to n do begin if not openpool (p) then alarm ('no bufs#'); alloc (msg, p, mainsem^); lock msg as buf: stdpart do with buf, header do begin receiver := port_no; first := first_buffer; end; msg^.u3 := 0; return_empty (msg, false); end; end; procedure def_end; begin if p <> max_port + 1 then alarm ('max_port#'); if inc_no <> max_process + 1 then alarm ('max_process#'); if port_no <> max_ports + 1 then alarm ('max_ports#'); if sem_no <> max_sem + 1 then alarm ('max_sem#'); if openpool (small_pool) then alarm ('smallpool#'); if openpool (large_pool) then alarm ('largepool#'); end; begin <* body of initialize *> mainsem := ref (sems(0)); definetimer (true); openopzone (zin , semvect(operatorsem), mainsem, 1, in_pool, 1,7,0,0); openopzone (zout, semvect(operatorsem), ref(zout.free), no_of_outbufs, out_pool, 2,7,0,0); opin (zin); outtext (zout, 'welcome...#'); outnl (zout); def_code (fpa_kind , fpa , fpa_name , fpa_size , fpa_prio); def_code (hdlc_kind , hdlc , hdlc_name , hdlc_size , hdlc_prio); def_code (gci_kind , gci , gci_name , gci_size , gci_prio); def_code (cons_kind , cons , cons_name , cons_size , cons_prio); def_code (ontel_kind , ontel , ontel_name , ontel_size , ontel_prio); def_code (bbm_kind , bbm , bbm_name , bbm_size , bbm_prio); def_code (server_kind, server , server_name , server_size , server_prio); for p := 1 to max_port do for serv := 1 to max_serv do for dist := 0 to max_dist do capability (p, serv, dist) := false; for i := 1 to max_serv do with dists(i) do begin last_p := max_port; for p := 1 to max_port do min_dist(p) := top_dist + 1; end; p := 1; inc_no := 1; port_no := 1; sem_no := 1; for i := 1 to no_of_fpa do begin def_inc (fpa_kind); def_port (1, outbufs_fpa, true); alloc_bufs (inbufs_fpa, large_pool); def_inc (fpa_kind); out_port (1); end; for i := 1 to no_of_hdlc do begin def_inc (hdlc_kind); def_port (1, outbufs_hdlc, true); alloc_bufs (inbufs_hdlc, large_pool); def_inc (hdlc_kind); out_port (1); end; for i := 1 to no_of_gci do begin def_inc (gci_kind); def_port (1, outbufs_gci, true); alloc_bufs (inbufs_gci, large_pool); def_inc (gci_kind); out_port (1); end; for i := 1 to no_of_cons do begin def_inc (cons_kind); def_port (1, 1, false); alloc_bufs (inbufs_cons, small_pool); out_port (1); end; for i := 1 to no_of_ontel do begin def_inc (ontel_kind); def_port (1, 1, false); alloc_bufs (inbufs_ontel, small_pool); out_port (1); end; for i := 1 to no_of_bbm do begin def_inc (bbm_kind); def_port (1, outbufs_bbm, true); alloc_bufs (inbufs_bbm, large_pool); out_port (0); end; for i := 1 to no_of_server do begin def_inc (server_kind); def_port (1, outbufs_server, true); alloc_bufs (inbufs_server, large_pool); out_port (1); end; def_end; test_all (0, 0, 0); <* set test-pattern for router itself *> run_all (1, max_process); end; <* initialize *> procedure deliver (var m: reference; p: integer); begin m^.u3 := p; if p = 0 then return_empty (msg, true) else begin if test then testput ('sent#', m); with ports(p) do begin signal (m, outsem^); outstandings := outstandings + 1; if pp <> 0 then with portx(pp) do poll_time := poll_period; end; end; end; function get_capability (pno: ports_range): boolean; var new_cap : boolean; min : integer; p : port_range; serv : serv_range; dist : dist_range; begin get_capability := false; with ports(pno) do p := pp; lock msg as data: cap_buffer do for serv := 1 to max_serv do begin min := top_dist; for dist := 0 to max_dist do begin new_cap := data.cap(serv, dist) = 1; if capability (p, serv, dist) <> new_cap then begin <* change *> capability (p, serv, dist) := new_cap; get_capability := true; end; if new_cap then if min = top_dist then min := dist; end; with dists(serv) do min_dist (p) := min + 1; end; return_empty (msg, true); end; <* get_capability *> function clear_capability (p: port_range): boolean; var serv: serv_range; dist: dist_range; begin clear_capability := false; for serv := 1 to max_serv do begin for dist := 0 to max_dist do begin if capability (p, serv, dist) then clear_capability := true; capability (p, serv, dist) := false; end; with dists(serv) do min_dist (p) := top_dist + 1; end; end; procedure send_capabilities; var i, p : port_range; serv : serv_range; dist : dist_range; sum : boolean; msg : reference; begin for p := 1 to max_port do with portx(p), ports(pno), children(proc_no) do if deliver_status then if not busy then if not nil (child) then if openpool (status_pool) then begin alloc (msg, status_pool, mainsem^); deliver_status := false; busy := true; lock msg as buf: cap_buffer do with buf, cap_head, header do begin first := first_buffer; last := size_cap_buffer - 1; routing_mode := inform; receiver := -pno; cur := 1; addr(cur) := pno; for serv := 1 to max_serv do for dist := 0 to max_dist do begin sum := false; if dist <> 0 then for i := 1 to max_port do if i <> p then sum := sum or capability (i, serv, dist - 1); cap(serv, dist) := ord(sum); end; end; msg^.u1 := output_msg; msg^.u2 := result_answer; msg^.u4 := full_buf; deliver (msg, pno); end; end; function find_port (serv: serv_range): 0..max_ports; var port_1 , port_2 : integer; mincost_1, mincost_2 : integer; cost : integer; i, p : integer; begin port_1 := 0; mincost_1 := maxint; port_2 := 0; mincost_2 := maxint; with dists(serv) do begin p := last_p; for i := 1 to max_port do begin p := p mod max_port + 1; if min_dist(p) <= top_dist then with portx(p), ports(pno) do begin cost := min_dist(p) * outstandings; if outstandings <= max_outs then begin if cost < mincost_1 then begin port_1 := p; mincost_1 := cost; end; end else begin if cost < mincost_2 then begin port_2 := p; mincost_2 := cost; end; end; end; end; if port_1 = 0 then port_1 := port_2; if port_1 <> 0 then begin last_p := port_1; port_1 := portx(port_1).pno; end; end; find_port := port_1; end; procedure status_change (p: ports_range; new_status: byte); var i : port_range; begin with ports(p) do begin last_status := new_status; if pp <> 0 then if new_status = result_ok then with portx(pp) do begin deliver_status := true; send_capabilities; end else if clear_capability (pp) then begin for i := 1 to max_port do if i <> pp then with portx (i) do deliver_status := true; send_capabilities; end; end; outtime (zout, local_time); outtext (zout, ' *** port #'); outinteger (zout, p, 2); if new_status = result_ok then outtext (zout, ' comming up#') else outtext (zout, ' gone down#'); outnl (zout); end; var rec : integer; p : integer; rout : routing_modes; begin <* main program of router *> initialize; own.timer := poll_accuracy; with pdescr (0) do repeat <* forever *> case waitst (msg, mainsem^) of a_delay: begin <* time for updating poll_timers *> own.timer := poll_accuracy; with local_time do begin seconds := seconds + poll_accuracy; if seconds >= 60*60 then begin seconds := seconds - 60*60; hours := hours + 1; if hours >= 24 then hours := 0; end; end; for p := 1 to max_port do with portx(p) do if poll_time > 0 then begin poll_time := poll_time - poll_accuracy; if poll_time <= 0 then deliver_status := true; end; send_capabilities; end; a_semaphore: begin test := testval <> 0; if ownertest (in_pool, msg) then conversation else case msg^.u4 of empty_buf: begin if test then testput ('empty#', msg); if msg^.u3 <> 0 then begin with ports(msg^.u3) do begin outstandings := outstandings - 1; if last_status <> msg^.u2 then status_change (msg^.u3, msg^.u2); end; msg^.u3 := 0; end; lock msg as buf: stdpart do begin buf.last := msg^.size * 2 - 1; rec := buf.receiver; end; if rec < 0 then begin <* inform-buffer has returned, use it again *> with ports(-rec), portx(pp) do busy := false; release (msg); send_capabilities; end else signal (msg, ports(rec).insem^); end; full_buf: if msg^.u3 <> 0 then return_empty (msg, false) <* driver was removed, and message returned *> else begin <* real message to the router *> if test then testput ('got #', msg); lock msg as buf: stdpart do with buf, header do begin rec := receiver; with ports(rec) do if last_status <> msg^.u2 then status_change (rec, msg^.u2); if msg^.u2 = result_ok then begin rout := routing_mode; case rout of reply : cur := cur - 2; next_request : cur := cur + 2; new_request : begin cur := cur + 2; addr (cur-1) := rec; addr (cur) := find_port (service_kind); end; inform : <* empty *> end; if cur > max_dist*2 then p := 0 else p := addr(cur); end else begin <* bad status *> rout := reply; p := 0; end; end; <* lock *> case rout of reply, next_request, new_request: deliver (msg, p); inform: begin if get_capability (rec) then begin for p := 1 to max_port do with portx(p), ports(pno) do deliver_status := true; send_capabilities; end; end; end; <* case *> end; <* full buf *> end; <* case buffer-type *> end; end; <* case timeout-or-message *> until doomsday; end; <* router *> <* ************************************************** *> process s (var sem_vector: system_vector); type adamtype = record name1 : alfa; name2 : alfa; aux1 : integer; end; opbuffer = record first,last,next : integer; name : alfa; go : array (16..17) of char; databuf : array (20..97) of char; end; var msg : reference; mainsem : semaphore; p : pool 1 of opbuffer; re_run : boolean; procedure adam (fct: byte; i: integer); begin msg^.u1 := fct; lock msg as buf: adamtype do with buf do begin name1 := 'router'; name2 := 'r '; aux1 := i; end; signal (msg, sem_vector(adamsem)^); wait (msg, mainsem); end; begin (*$5 10 512*) <* default create-size := 512 words *> alloc (msg, p, mainsem); adam (1 <* link*> , 0-0-0); repeat adam (2 <* create *>, 2000); adam (3 <* start *> , 0); repeat msg^.u1 := 1; lock msg as buf: opbuffer do with buf do begin first := 18; last := 97; name := 's '; go := '**'; end; signal (msg, sem_vector (operatorsem)^); wait (msg, mainsem); lock msg as buf: opbuffer do with buf do re_run := go = 'go'; until re_run; adam (5 <* remove *>, 0-0-0); until false; end; . ▶EOF◀