Language Extensions for Gnosis
These facilities require the following concepts and knowledge on the part of the user:
What it means to invoke the particular keys that are required to do the job.
How to put and update a program in a segment (such as using an editor)
Access to and knowledge of some command system sufficient to invoke the keys described here.
Knowledge of PL/I sufficient for the job
Meanings of Compiler diagnostics (and other retributions).
If there is no compilation with an “OPTIONS(MAN)” included or if the compilation of that module was suppressed due to errors, a DDT without symbol tables will pop up trapped about 02c00 in GNOIBM.
If you specify no RCTO in your KALL and a nonzero return code comes along, you will be thrown into DDT {(ddtdoc,)} at an execute of an SVC. “1r;x4;” will provide the order code and “key x,080000000;” will return the alleged type of the thing that returned the code. Here x is bits 8 thru 11 of reg 0 gotten by “0r;x4;”. “plistack;” will display the stack with source code line numbers if you compiled with the GONUMBER option.
Expressions such as “UNSPEC(SUBSTR(sv,4,11))” can be used to retrieve the binary values that are held in string parameters sv. Use “BINARY(UNSPEC(SUBSTR(sv, 4,11)))” if you are worried about PL/I's secret conversions surprising you. These expressions produce fairly efficient inline code.
If you need to do arithmetic on long binary values in the character string you may use “SI(SUBSTR(sv,4,11))”. SI {S inverse} returns a FLOAT BIN(109) and is declared “DCL SI EXTERNAL ENTRY(CHAR(*)) RETURNS(FLOAT BIN(109))”. The value will not be negative.
The external routine SHEX is a routine that converts a character value to hexadecimal representation suitable for printing. It has nothing to do with Gnosis per se. It should be declared: “DCL SHEX EXT ENTRY(CHAR(*)) RETURNS(CHAR(80) VAR);”
The entry KLEAN is declared EXTERNAL ENTRY KLEAN(FIXED BIN). Its effect is to save the expense of copying a value from the cache to the super-node when the value is not required. The result is that the key value may be replaced by an older value.
The SORT interface is not supported.
Dynamic loading (FETCH/RELEASE) is not supported.
CHECKPOINT/RESTART is not supported.
DELAY doesn't delay.
VSAM files are not yet supported.
Regional 2 and regional 3 datasets must have keys of 252 or fewer characters.
The Checkout Compiler is not currently supported {except under CMS}.
See (p3,osiorestrict) for further hints about file support.
See the PLIXOPT feature of PL/I about setting execution parameters such as “NOSPIE”.
Unfortunately this mode breaks support for the DXR ;instruction; that may not be implemented on your machine. OS has arranged to simulate this instruction upon interrupt if the processor does not understand it. PL/I compiles this instruction to divide floating point numbers with more than 56 bits.
The PL/I run-time and transient libraries are built in and shared, including the standard versions of IBMBEEF and IBMBEER.
PLILOAD(kt; ==> X'80F0D';)
{spec}Some Unsolved Problems
A complete solution to this problem seems to require modifying a compiler so as to allocate and free frames for keys as it now allocates and frees stack frames.
Instructing new domains
SHOW: PROC; ... CALL CREATE_DOMAIN (INSTRUCTIONS, REF_ENTRY_KEY); ... INSTRUCTIONS: PROC; /* CODE TO BE EXECUTED BY THE NEW DOMAIN */ END INSTRUCTIONS; END SHOW;
If we write such a program the routine CREATE_DOMAIN gets access to a stack frame address and the address of the code compiled for INSTRUCTIONS. The PL/I environment is prepared at this point for INSTRUCTIONS to be called with access to that stack frame. Such access will be used in case of variables referenced within INSTRUCTIONS and declared outside. We shall require that the block where the call was executed remain active while the domain exists if there are such references.
The effect of the call is to create a domain that shares storage with the existing domain {like two cpu's sharing main storage} and starting the domain with PSW pointing at the code of INSTRUCTIONS and the display register pointing at the stack. An start key to the new domain would be returned to REF_ENTRY_KEY
The new domain would have a {virtual} copy of the keys of the creator. The effect of a return in the new domain would be to delete the new domain.
The meaning of “CALL CREATE_DOMAIN(INSTRUCTIONS);” is thus very much like that of “CALL INSTRUCTIONS TASK;”.
The domain would remain busy for its duration unless it executes a KRETURN statement. In such a case the start key to that domain would become useful for communicating with the domain.
Whether to share keys
If two domains share a FIXED BIN(15) variable in a slot-defining context the semantics are strange at best and perhaps fatal. If we were to share slots as well as storage we would have all of the key cache problems that designers of multiprocessor 370's have with storage caches.
Such a design would require that the supernode be shared and also that either the cache be shared or that there be cache coordination logic between the caches. Neither of these ideas seem attractive to me.
I think a less accurate and quicker LRU algorithm would win.
Program interrupts in Gnosis
PL/I normally issues a SPIE macro requesting control upon interrupts. When the program reaches a breakpoint set by DDT the interrupt is given to this PL/I error handler instead of DDT.
The PLIXOPT feature referred to in (osparm) disables the SPIE macro and gives all interrupts to DDT.
When a key invocation resulting from a KALL instruction traps due to a rejected return code, the OS simulator knows that no real OS program will understand this kind of interrupt and so it gives it to DDT even when SPIE has been issued.
Thus the statement “KALL (RETR, 1);” will cause a DDT to appear over the program even if the PLIXOPT has not been used. Breakpoints will not work without PLIXOPT because the interrupts they cause are thought by the OS simulator to belong to the PL/I runtime stuff.
If DC is the domain creator for the domain executing the compiled and X is a start key to that domain then:
“plistack;”; shows the stack indicating stack frame location and the subroutine name when available and line number if the program was compiled with the GN option. The compiler output gives the address of automatic variables within the stack frame. Those variables may thus be displayed.
See (kjumpadebug) about finding keys in the key cache.