; -*- MIDAS -*- subttl MSGS -- format of the MSGS file .begin MSGS .auxil .tyo6 .ifnm1 .tyo 40 .tyo6 .ifnm2 printx / INCLUDED IN THIS ASSEMBLY / comment|  File: MSGS, Node: Top, Up: (LIB) Next: Routines MSGS is a library for accessing and setting the date of the last system message a user has viewed. The date of the last message used is stored in the file SYS;:MSGS TIMES, which is mapped in and modified rather than read and written. It is used by the GMSGS program and the :MSGS command in DDT. This is used as follows: To access a user, call USRGET, if you're going to access only one user. If you're going to do multiple accesses, call MAPMSG first, then call USRGT1 for each user you wish to look up. When done, call UNMAP Restriction: This cannot be used inside interrupt routines, since it assumes that the proper states of .DF1 and .DF2 are 0, rather than saving and restoring. This is fixable if needed. * Menu: Here's more info * Routines:: Routines contained in this file * Format:: Format of the database file  File: MSGS, Node: Routines, Up: Top, Previous: Top, Next: Format All user-level routines skip unless there's been an error. AC's A, B, C, and D are assumed to exist, but not assumed consecutive. No AC's are clobbered unless they contain arguments to the routines. A macro CRITIC is provided to include in the critical routines table. It ** MUST ** be included in the range of the AOBJN ptr to the table. (see *Note LOCKS: (LOCKS)*, for info on ITS LOCKS) USRGET: A/ UNAME to look up B/ channel on which to open file C/ AOBJN ptr to pages in which to map the file The address in core of the user's entry is returned in A If the entry is freshly created, it will have a 0 in ME$MDT MAPMSG: B/ channel on which to open the file C/ AOBJN ptr to pages in which to map the file UNMAP B/ channel to do a DSKUPD and close. C/ AOBJN ptr to pages to flush UNMAP should always be called when the file isn't needed any more. The ITS locks feature is used to prevent simultaneous addition of users to the table. For this to work, %OPLOK and %OPLKF should be set in the job's .OPTION word, a .CALL UNLOCK should be done in the event of quits and the like, and the critical pieces of code in this package *MUST* be included in the job's critical routines table, via the macro MSGS"CRITIC  File: MSGS, Node: Format, Up: Top, Previous: Routines | ;;; Header info at start of file m$==:,-1 m$init==:0 ;time of system invocation, from start init m$done==:1 ;time of system invocation, from init done m$lock==:2 ;0 means locked m$lokl==:3 ;link/instruction word of lock m$loku==:4 ;uname of locking job m$lokj==:5 ;jname of locking job m$aobj==:6 ;AOBJN ptr to table (-<# entries>,,) m$size==:7 ;size of entries in table ;; Entries in the table me$==:,-1 me$unm==:0 ;UNAME me$mdt==:1 ;MSGS date lock: push p,a .call [setz ? sixbit /RQDATE/ ? %clout,,a ? setz+<%clout,,a>] .lose %lssys jumpl a,[pop p,a ? popj p,] aos -1(p) .suset [.sdf1,,[-1]] .suset [.sdf2,,[-1]] camn a,m$done(c) ;is it initialized? jrst lock0 ; yes, lock it up. init0: exch a,m$init(c) ;claim privilege of init'ing. init1: camn a,m$init(c) ;should we init? jrst initw ; no, someone else is, wait for him setom m$lock(c) ;unlock the lock init2: move a,m$init(c) movem a,m$done(c) ;mark init complete. jrst lock0 ;We're all done. initw: move a,m$init(c) camn a,m$done ;wait till someone else's init is finished. jrst lock0 ; yes, they finished already. movei a,30. ;wait until they finish .sleep a, ;also consider that the job doing the move a,m$init(c) ;init'ing may have aborted. jrst init0 ;so go back to try it again just in case. lock0: skipl m$lock(c) ;wait for switch to be free. .hang aose m$lock(c) ;try to lock it. jrst lock0 ;(somone else grabbed it between ;our .hang and our aose) lock1: push p,b move b,[-4,,[sixbit /UNAME/ ? movem m$loku(c) sixbit /JNAME/ ? movem m$lokj(c)]] .call [setz ? sixbit /USRVAR/ ? %climm,,%jself ? setz b] .lose %lssys .suset [.r40addr,,b] move a,3(b) ;put the switch on the hrli a,(setom) ;locked switch list movem a,m$lokl(c) ;link it in movei a,m$lock(c) ;get address of this lock movem a,3(b) ;and install it in the chain lock2: move a,[-2,,[.sdf1,,[0] ? .sdf2,,[0]]] .suset a pop p,b pop p,a popj p, unlock: push p,b push p,a move a,[-3,,[.sdf1,,[-1] ? .sdf2,,[-1] ? .r40addr,,b]] .suset a ;get address of start of list, etc. unloc0: hrrz a,m$lokl(c) ;remove the switch from the movem a,3(b) ;locked switch list. unloc1: setom m$lock(c) ;then unlock the switch. move a,[-2,,[.sdf1,,[0] ? .sdf2,,[0]]] .suset a pop p,a pop p,b popj p, define critic msgs"init1,,msgs"init2 ;from init1 to init2 the database has been setzm msgs"m$init(b) ;marked as being inited. If killed undo it msgs"unloc0,,msgs"unloc1 ;Here the lock has been removed from chain setom @msgs"m$lock(c) ;but is still locked. msgs"lock1,,msgs"lock2 ;Here, the switch is locked, but we are setom @msgs"m$lock(c) ;still in the process of putting it on the ;chain termin mapmsg: push p,b push p,a push p,d movem c,msgpgn ;remember what pages we're hacking .call [setz ? sixbit /OPEN/ ? %clbit,,.uii ? b ? [sixbit /SYS/] [sixbit /:MSGS/] ? setz [sixbit /TIMES/]] jrst maperr ;Fail! .call [setz ? sixbit /DSKUPD/ ? setz b] jfcl .call [setz ? sixbit /FILLEN/ ? b ? setz+<%clout,,a>] jrst maperr hlre d,c ;get -<# of pages> movns d imuli d,2000 ;Get <# of words> caige d,(a) ;If there's enough room jrst maperr .call [setz ? sixbit /CORBLK/ ? %climm,,%cbndw ? %climm,,%jself ? c setz b] jfcl aos -3(p) maperr: .call [setz ? sixbit /CLOSE/ ? setz b] jfcl pop p,d pop p,a pop p,b popj p, ;; A/ UNAME ;; B/ Channel ;; C/ -<# of pages>,,first page usrget: pushj p,mapmsg popj p, usrgt1: push p,b hrrz c,msgpgn ;get the starting page # imuli c,2000 ;and convert to words move b,m$aobj(c) ;get the AOBJN ptr to our table addi b,(c) ;and point to its location in our core usrgt0: camn a,me$unm(b) ;Is this our user? jrst [movei a,(b) ; return that as the pointer pop p,b aos (p) ; skip return, we've succeeded. popj p,] add b,m$size(c) ;point to next entry sos b ;allow for one added by AOBJN aobjn b,usrgt0 ;next entry pop p,b push p,d pushj p,lock ;must lock it to add a user jrst msgext ; Probably don't know the time. aos -1(p) ;skip when we return hlre d,m$aobj(c) ;get the size of the table in entries sos d ;get new size hrlm d,m$aobj(c) ;store it away movns d ;get positive size imul d,m$size(c) ;in words, not entries push p,a ;remember the UNAME hrrz a,m$aobj(c) ;get start of table addi a,(c) ;make absolute instead of relative to table addi a,(d) ;entry after last sub a,m$size(c) ;last entry pop p,me$unm(a) ;salt away that uname setzm me$mdt(a) ;initially, date is 0 pushj p,unlock ;unlock the table msgext: pop p,d ;restore D popj p, unmap: .call [setz ? sixbit /CORBLK/ ? %climm,,0 ? %climm,,%jself setz msgpgn] ;flush the pages jfcl aos (p) ;skip return popj p, .scalar msgpgn .end MSGS