The Program Stack, SYSOBJ, and Secondary Load (TB #33) (Functions/Subroutines/Programs)
Created at 01 OCT 1996 04:32PM
The Program Stack, SYSOBJ, and Secondary Load
Note: This Technical Buliten was written based on Advanced Revelation 1.15. Some information might not be applicable in later releases. The SECONDARY.LOAD record will exist if your version of Advanced Revelation is 2.12 or above.
Starting with Advanced Revelation 2.12, the VERBS and SYSOBJ were combined. In Advanced Revelation 2.12 this file is called VERBS. In Advanced Revelation 3.x this table is called SYSOBJ. Advanced Revelation treats the contents of the INITIAL_LOAD record as they were located in the SYSOBJ file for the purposes of this article. All programs found in INITIAL_LOAD are placed into the program stack during boot-up. INITIAL_LOAD can be found in the SYSTEM file (Advanced Revelation 2.12) or in the SYSENV table (Advanced Revelation 3.x).
The Program Stack
In many ways Advanced Revelation resembles an operating system. One of these ways is how it loads and executes R/BASIC object code.
When a program is compiled, the end result (object code) consists of a string of instructions called opcodes. When the program is executed, these instructions are loaded into string space (memory) and the Advanced Revelation engine (the AREV.EXE) parses through the codes, executing each instruction in turn.
Because multiple R/BASIC (and C and Assembly Language) programs can be loaded concurrently, Advanced Revelation keeps order among them by maintaining a Program Stack. The Program Stack (PS) is a data structure that contains the names and object code of all programs currently in memory.
This Technical Bulletin discusses the PS, how it is maintained and how a developer can manipulate the PS for efficiency in speed or to optimize memory usage.
Program Stack Structure
The Program Stack consists of two data structures. One is a dimensioned array (of 299 elements) that contains object code strings. These strings are maintained, as are all strings, in string space (RAM).
The second structure is a dynamic array of program names. The position of each program name in the dynamic array corresponds to an element in the dimensioned array. When a program is called, the system scans the dynamic array looking for the program name. If the program name is found, the corresponding object code string is processed. Otherwise the system attempts to load the object code from disk.
It is taken as fact that some programs must always be available. RTP27, the program loader, for example, must always be ready for any process that needs it.
Because the system searches the program stack sequentially to determine whether a program is already in memory, it is desirable to have frequently called programs near the top of the stack. An MFS is a good example of this.
Program Stack Initialization (Loading SYSOBJ)
The Program Stack is created and initialized when the user enters Advanced Revelation. As part of the system initialization, the boot program loads all programs in the SYSOBJ file onto the Program Stack.
Once the programs in SYSOBJ are loaded, the boot program looks for a special record called SECONDARY.LOAD. If this record is found, the programs listed in it are loaded from the VERBS file.
How the Program Stack is Maintained
As new programs are called, the program loader first checks to see whether the program is already loaded. If it is, the proper object code string is executed. If not, the object code is loaded into memory and then executed.
A main program stays in memory until a STOP is executed. At that point the program and all subroutines and functions called by the program are stripped from memory.
There are two exceptions to this procedure. First, any subroutines or functions labeled EXPENDABLE will be stripped from memory when they RETURN to the calling program. Second, filing systems and MFSs (unless EXPENDABLE) are not stripped.
The execution of an ABORT statement will strip all programs loaded since the latest invocation of RTP18, while an ABORT ALL strips everything since the latest RTP17 or RTP2. (RTP2 is responsible for TCL level one; RTP17 is responsible for higher execute levels.)
The Return Stack
As programs call additional programs for instance, subroutines that call further subroutines Advanced Revelation maintains a list of the dependencies between these programs. This list is termed the return stack, and indicates the order in which programs have been called.
The return stack does not indicate load order, since a program recently loaded can call a program that had been loaded previously. When a RETURN is executed, control reverts to the program highest on the return stack.
Insufficient Memory
It is possible that when attempting to load a new program, the system will encounter an insufficient memory condition. When this happens a GARBAGECOLLECT is executed to consolidate unused memory. If this is unsuccessful, a routine is executed that removes only the object code for any program that follows RTP2. That is, the entry in the dimensioned array is nulled while the corresponding entry in the dynamic array is maintained. The routine will continue to remove object code until enough memory has been freed to fill the current need.
The position in the dynamic array must be maintained because the program whose object code is being stripped may be part of the current call chain. In other words, a main program may have called a subroutine, which in turn calls another subroutine. The second subroutine may cause a GARBAGECOLLECT which results in the object code for the main program being stripped from memory. Part of the information necessary to return to the main program is its position on the PS. Any code stripped from memory in this manner is reloaded as needed
.
Querying the Program Stack
Using the debugger, a user or developer can list the contents of the PS and of the return stack. To list the current contents of the PS, enter the command PS at the debugger's exclamation point prompt. To view the contents of the return, enter the command R.
Note: The PS command displays the contents of the dynamic array of programs names. It does not indicate which routines have had their object code stripped from memory.
Using the Program Stack Effectively
The Advanced Revelation method of loading and maintaining the Program Stack has several implications for the developer.
First, there is a limit to how many programs can be loaded in memory at one time. Once all 299 positions in the program stack have been used, any attempt to load another routine will result in the cryptic "RTP27 subscript value out of range error."
This error is most readily rectified by replacing dictionary brace calls with @RECORD references. For example, instead of a symbolic field referring to {ZIP}, which takes an entry on the program stack, the symbolic formula could refer to @RECORD<X>, where X is the appropriate field number. The latter method does not require a program stack entry and is faster.
Second, the developer can add items to SECONDARY.LOAD to ensure that some programs are always high on the stack, thus facilitating rapid access. When names are added to SECONDARY.LOAD, use the program name only, that is, without the '$' prefix. The corresponding object code must be in the VERBS file, with the '$' prefix.
Third, the developer can fine-tune the contents of SYSOBJ to best suit a particular application. This can be done by adding to SYSOBJ, thus ensuring that critical programs are always in memory. The object code record is simply copied into SYSOBJ complete with the '$' prefix.
The developer can also remove some items from SYSOBJ. Figure 1 lists the contents of SYSOBJ as of 1.15, noting which can be moved safely out of SYSOBJ and into VERBS.
Warning! Removing programs from SYSOBJ can prevent the user from logging back in. Always make a backup of the SYSOBJ file before experimenting. Removing programs from SYSOBJ may adversely affect system performance. The developer should thoroughly test his particular application after SYSOBJ has been changed.
Figure 1
Table of Programs in SYSOBJ
Program | Function | Size | Move? |
$BORDER.UP | Border Processor | 1849 | Yes* |
$DICT.MFS | Dictionary MFS | 1882 | Yes |
$MONITOR | Determines monitor type | 96 | Yes** |
$MSG | Message processor | 4058 | Yes* |
$QUICKDEX.MFS | Quickdexing | 669 | Yes |
$RIGHTDEX.MFS | Rightdexing | 669 | Yes |
$RTP11 | Large Readnext | 1077 | Yes |
$RTP11.INDEX | Index Readnext | 2357 | Yes |
$RTP12 | Select | 2838 | Yes |
$RTP15 | Printer Output | 1730 | Yes |
$RTP16 | XLATE | 434 | Yes |
$RTP17 | EXECUTE | 547 | Yes |
$RTP18 | TCL | 5845 | Yes |
$RTP19 | (Format)/ OCONV | 1277 | Yes |
$RTP2 | System Level | 1501 | No |
$RTP20 | WITH processor | 94 | No |
$RTP20.1-9 | WITH processors | 98 | No |
$RTP20.10-17 | WITH processors | 100 | No |
$RTP21 | Multivalue Math | 924 | Yes |
$RTP25 | Debugger | 1428 | Yes*** |
$RTP26 | ICONV | 2389 | Yes |
$RTP27 | Program Loader | 626 | No |
$RTP29 | TCL Options Parser | 715 | Yes |
$RTP31 | SUM | 208 | Yes |
$RTP32 | FIELDSTORE | 320 | Yes |
$RTP33 | LOCATE | 823 | No |
$RTP34 | CLEARFILE | 157 | Yes |
$RTP36 | LOCK | 944 | Yes |
$RTP37 | UNLOCK | 848 | Yes |
$RTP38 | Network Flush | 174 | Yes |
$RTP42 | Labeled Common Loader | 110 | Yes* |
$RTP43 | Multivalue Readnext | 124 | Yes |
$RTP50 | Memory Resident BFS | 1200 | No |
$RTP53A | DOS BFS | 524 | Yes |
$RTP7 | READV | 86 | Yes |
$RTP8 | WRITEV | 97 | Yes |
$RTP9 | OPEN | 380 | No |
$SCROLL.WINDOW | Screen Manipulator | 241 | Yes |
$VIDEO.RW | Video Manager | 912 | Yes* |
* May be removed only if MSG will never be called during login. If MSG must be called to report a login error (eg Network does not respond) or to prompt the user for a password, and these programs are missing, the user will not be able to log in.
May be removed only if Advanced Revelation does not have to determine the monitor type. Revelation will check the monitor type whenever the system is logged into without a user name. *** May be removed, however if the debugger is ever called and there is insufficient memory to load it, the user will be returned to DOS.