// IfsRSMgrInit.bcpl - Rendezvous Socket Manager initialization
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified October 18, 1981  2:42 PM by Taft

get "Ifs.decl"
get "IfsRs.decl"
get "IfsInit.decl"

external
[
// outgoing procedures
InitRSMgr; InitJobPolicyControls

// incoming procedures
Allocate; Zero; MoveBlock; Max
CreateEvent; RsMgrEvent; FlushVitalState; ShiftSwatEvent

// incoming statics
rsQ; ovPBIQ; rsLock; jobT; lenJobT; maxJobs; leafPresent; jpc
isb; numOvXMPages; numPBIs
sysZone; lvAbortFlag
]


// InitRSMgr initializes the RSMgr and related modules.
// numVMemBufs is the total number of VMem buffers expected to be available
// after all initialization is completed.  If the Alto has extended memory,
// this is used to figure out the maximum number of jobs
// that can be supported and to adjust zone sizes and PBI allocations
// accordingly.  The results are left in:
//	lenJobT -- absolute maximum number of jobs
//	numPBIs -- number of PBIs to allocate
//	isb>>ISB.smallZoneIncr -- words to add to smallZone
//	isb>>ISB.bigZoneIncr -- words to add to bigZone

// The initial zone sizes, PBI allocations, etc. (defined in IfsInitRes.bcpl)
// are based on a non-XM, non-Leaf configuration supporting a maximum of 6
// jobs; these numbers have been determined empirically.  Here we compute the
// additional demands placed on memory by jobs in excess of the first 6.

//----------------------------------------------------------------------------
let InitRSMgr(numVMemBufs) be
//----------------------------------------------------------------------------
[
lenJobT = 6
numPBIs = 21  // 3 per job plus 3 extra
isb>>ISB.smallZoneIncr = 0; isb>>ISB.bigZoneIncr = 0

if numOvXMPages ne 0 then
   [  // XM configuration
   manifest
      [  // Assumptions made about memory demand per job
      numVMemBufsPerJob = 3		// 1 ctx + 2 stream buffers
      zoneWordsPerJob = 300 + 10 +	// RTP stack size + UserInfo block
       75 + 25 + 50 +			// BSPStream + one FD + one DiskStream
       3*290 + 100			// 3 PBIs + slop
      totalWordsPerJob = (numVMemBufsPerJob lshift logStdPageLength) +
       zoneWordsPerJob
      ]

   // Note that the zoneWordsPerJob for the first 6 jobs are already
   // accounted for.  Right-shift everything by 1 to keep it positive.
   let numVMemWordsExtra =
    (numVMemBufs - lenJobT*numVMemBufsPerJob) lshift logStdPageLength
   let numJobsExtra =
    (numVMemWordsExtra rshift 1) / (totalWordsPerJob rshift 1)
   lenJobT = lenJobT + numJobsExtra

   // Adjust zone sizes and PBI allocations
   isb>>ISB.bigZoneIncr = numJobsExtra*zoneWordsPerJob
   isb>>ISB.smallZoneIncr = numJobsExtra*50  // number picked out of the air
   numPBIs = numPBIs + 3*numJobsExtra
   ]

if leafPresent then
   [  // back off the job limit and add more space to smallZone
   lenJobT = lenJobT-1
   isb>>ISB.smallZoneIncr = isb>>ISB.smallZoneIncr+1024
   ]

// Default Server-Limit
maxJobs = lenJobT-1

// a little unstructured programming here...
rsQ = Allocate(sysZone, lenJobT+6); Zero(rsQ, lenJobT+6)
ovPBIQ = rsQ+2
rsLock = rsQ+4
jobT = rsQ+6

CreateEvent(RsMgrEvent)
CreateEvent(FlushVitalState)
@lvAbortFlag = @lvAbortFlag +1  //disable user aborts
CreateEvent(ShiftSwatEvent)
]

//----------------------------------------------------------------------------
and InitJobPolicyControls() be
//----------------------------------------------------------------------------
// Sets the job policy control table based on maxJobs.
[
if jpc eq 0 then jpc = Allocate(sysZone, size JPC/16)

MoveBlock(lv jpc>>JPC.typeClass, table
   [ // maps types to job equivalence classes
   0	// FTP
   0	// MTP
   0	// Telnet
   1	// Backup
   2	// Mail
   3	// Miscellaneous
   0	// Leaf
   2	// Press
   4	// NameUpdate
   2	// BootUpdate
   0	// CopyDisk
   ], 11)

MoveBlock(lv jpc>>JPC.classMax, table
   [ // max number of jobs of a given class allowed simultaneously
   0		// 0 FTP+MTP+Telnet+Leaf+CopyDisk -- changed to maxJobs below
   1		// 1 Backup
   1		// 2 Mail+Press+BootUpdate
   2		// 3 Miscellaneous
   1		// 4 NameUpdate
   ], 5)
jpc>>JPC.classMax↑0 = maxJobs

MoveBlock(lv jpc>>JPC.classSystemMax, table
   [ // a job of a given class should not be permitted to run if
     // it would make the number of jobs in the system exceed
     // the limit given in this table.
   999		// 0 FTP+MTP+Telnet+Leaf+CopyDisk
   2		// 1 Backup -- changed below
   5		// 2 Mail+Press+BootUpdate -- changed to maxJobs-1 below
   999		// 3 Miscellaneous
   2		// 4 NameUpdate -- changed below
   ], 5)
jpc>>JPC.classSystemMax↑1 = Max(2, maxJobs/2)  // no Backup if too busy
jpc>>JPC.classSystemMax↑2 = maxJobs-1  // leave one slot for a class 0 job
jpc>>JPC.classSystemMax↑4 = Max(2, maxJobs/2)  // no NameUpdate if too busy
]