DG/L 3.20 Documentation Additions and Changes 1 Routines not Described in the Runtime Manual 1.1 BESTFIT Allow a user to specify that local allocation routines (ALLOCATE or WALLOCATE) use a best fit method in searching the free chain; that is, search for the smallest block that meets the size and alignment demands of the request. Calling Sequence: EXTERNAL INTEGER BESTFIT; If neither BESTFIT or FIRSTFIT is used, the default is EXACTFIT. When a block is freed, it is merged with the blocks before and after it if they are free also, and if it is directly above the stack, the block is remerged with the stack. Also, if the user calls a global allocation routine (GALLOCATE or WGALLOCATE) but uses no multitasking, those allocation routines will also use a BESTFIT method for allocation. Available for all DG/L environments. 1.2 CMCLOSE Close a cache memory file previously opened with ACCESS. Calling Sequence: CMCLOSE () where is an integer expression that specifies the channel number of the file you want to close. When using the shared page cache memory routines, this routine does a ?SCLOSE, and when using the unshared cache library, this routine does a ?GCLOSE/?CLOSE/.CLOSE (depending on the operating system). CMCLOSE also deletes all references to the file in the buffer chain in addition to doing a FLUSH. If you don't use CMCLOSE, but use CLOSE and FLUSH, you get incorrect references if 1.2 CMCLOSE 2 you CLOSE the channel, and ACCESS a different file on the same channel. Available for all DG/L environments. 1.3 CONNECT Become a customer of a server. Calling Sequence: CONNECT (, [,]) where is a string or an integer(1) depending on is integer(1) for AOS and AOS/VS-16 or integer(2) for AOS/VS-32, and is an an optional error label. Note: If bit 0 of is 1, then is a string containing the process name of the server, otherwise it is the PID of the server. If bit 1 of is 1 then in the case that this process dies, the server does not receive the termination message, otherwise it does. Available for AOS, AOS/VS-16, and AOS/VS-32 environments. 1.4 CTERM Terminate a customer. In order to do this, you must be a server. Calling Sequence: CTERM (, , [,]) where is a string or an integer(1) depending on , is an integer(1), is an array or first word of an allocated block and is an optional error label. For size and contents of , consult either your AOS Programmer's Manual or your AOS/VS Programmer's Manual. If is -1 then is a string containing the customer's process name, otherwise is an integer(1) that contains the customer's PID. The IPC message is sent to the customer's father 1.4 CTERM 3 as a termination message. Available for AOS, AOS/VS-16, and AOS/VS-32 environments. 1.5 DCON Break the connection between a customer and a server. Calling Sequence: DCON ( [,]) where is an integer(1) and is an optional error label. Available for AOS, AOS/VS-16, and AOS/VS-32 environments. 1.6 EXACTFIT Allow a user to specify that local allocation routines (ALLOCATE or WALLOCATE) use an exact fit method in searching the free chain; that is, search for the block that meets the size and alignment demands of the request. This is basically how DG/L Rev. 2.10 did allocation, and is the default if neither BESTFIT or FIRSTFIT is used. Calling Sequence: EXTERNAL INTEGER EXACTFIT; Available for all DG/L environments. 1.7 FIRSTFIT Allow a user to specify that local allocation routines (ALLOCATE or WALLOCATE) use a first fit method in searching the free chain; that is, search for the first block that meets the size and alignment demands of the request. If neither FIRSTFIT or BESTFIT is used, the default is EXACTFIT. Calling Sequence: 1.7 FIRSTFIT 4 EXTERNAL INTEGER FIRSTFIT; When a block is freed, it is merged with the blocks before and after it if they are free also, and if it is directly above the stack, the block is remerged with the stack. Blocks are put on the free list in a first-in, first-out (FIFO) manner. Also, if the user calls a global allocation routine (GALLOCATE or WGALLOCATE) but uses no multitasking, those allocation routines will also use a FIRSTFIT method for allocation. Available for all DG/L environments. 1.8 FROMCUSTOMER Move data from a customer's address space to the current address space. In order to use this routine, you must be a server. Calling Sequence: FROMCUSTOMER ( [,]) where is an array or the first word of an allocated block and is an optional error label. See the AOS Programmer's Manual or the AOS/VS Programmer's Manual for the contents of the ?MBFC packet. Available for AOS, AOS/VS-16, and AOS/VS-32 environments. 1.9 GBESTFIT Allow a user to specify that global allocation routines (GALLOCATE or WGALLOCATE) use a best fit method in searching the free chain; that is, search for the smallest block that meets the size and alignment demands of the request. Calling Sequence: EXTERNAL INTEGER GBESTFIT; If GFIRSTFIT is not specified, GBESTFIT is the method used by default. When a block is freed, it is merged with the blocks before and after it if they are free also, and if it is directly above the stack, the block is remerged with the stack. Note, GBESTFIT has no effect if the program is a single-tasked, ring 7 1.9 GBESTFIT 5 program. Available for all DG/L environments. 1.10 GFIRSTFIT Allow a user to specify that global allocation routines (GALLOCATE or WGALLOCATE) use a first fit method in searching the free chain; that is, search for the first block that meets the size and alignment demands of the request. Calling Sequence: EXTERNAL INTEGER GFIRSTFIT; If GFIRSTFIT is not specified, GBESTFIT is the method used by default. When a block is freed, it is merged with the blocks before and after it if they are free also. The free list is ordered in a first in, first out (FIFO) manner. Note that GFIRST- FIT has no effect if the program is a single-tasked ring 7 program. Available for all DG/L environments. 1.11 INTWAIT Suspend the user's task until the user types ^A (control A) on RDOS, DOS, or until the user types ^C^A on AOS and AOS/VS. Calling Sequence: INTWAIT; Available for all DG/L environments except RTOS. 1.12 LASTERROR Return the full error code, instead of using the upper four bits for describing the fatality level and severity of the error. Note that AOS/VS-32 never returns this information, so this routine has the same effect as calling READERROR. 1.12 LASTERROR 6 Calling Sequence: := LASTERROR ( [, [, [, [,]]]]) where is an integer(1), (integer(2) on AOS/VS-32) is an integer(1), (integer(2) on AOS/VS-32) is an integer(1) (integer(2) on AOS/VS-32) is an integer(1), (integer(2) on AOS/VS-32) is an integer(1) and is an integer(1). Available for all DG/L environments. 1.13 NOLABEL This is a dummy label that can be passed in situations where in order to access optional arguments, the user must pass an error label but doesn't want to. The error handler will act as if the label were not passed at all. Calling Sequence: EXTERNAL INTEGER NOLABEL; ... FOO (..., NOLABEL, ...); Available for all DG/L environments. 1.14 PASSCONNECTION Pass the connection between the current process and a customer to another server. In order to use this routine, you must be a server. Calling Sequence: PASSCONNECTION (, [,]) where is an integer(1), is an integer(1) and is an optional error label. 1.14 PASSCONNECTION 7 Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.15 PORTISR Send an Inter-Process Communication message and then wait for the reply. Calling Sequence: PORTISR (
[,]) where
is an array or the first word of an allocated block and is an optional error label. For size and contents of the
array, see either the AOS Programmer's Manual or the AOS/VS Programmer's Manual for the format of the ?IS.R packet. Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.16 PORTLOOKUP Look up the port number of an IPC-type file. Calling Sequence: PORTLOOKUP (, , [,]) where is a string, is an integer(2), is an integer(1) and is an optional error label. This routine does a ?ILKUP on and returns and . Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.17 RESIGN Resign from being a server. 1.17 RESIGN 8 Calling Sequence: RESIGN [()] where is an optional error label. Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.18 RINGLOAD Load a program into another ring. Calling Sequence: RINGLOAD ( [,]) where is a string and is an optional error label. This routine loads the program specified by the string in a user ring (rings 4-6). You cannot load a program into ring 7 because all user programs must start execution in ring 7, and you cannot load a ring that is already loaded. For more details consult the chapter in this document on multiring programs. Available for AOS/VS-32 environment only. 1.19 SERVE Become a server. Calling Sequence: SERVE [()] where is an optional error label. Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.20 SUPERPROCESS 1.20 SUPERPROCESS 9 Set or test Superprocess mode. Calling Sequence: SUPERPROCESS ( [,]) where is an integer(1) and is an optional error label. Mode has the same meaning as the mode argument to the SUPERU- SER routine: -1 -- Turn on superprocess mode 1 -- Turn off superprocess mode 0 -- Return the superprocess mode in -1 -- Superprocess mode is on 1 -- Superprocess mode is off Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.21 TOCUSTOMER Move data to a customer's address space. In order to call this routine, you must be a server. Calling Sequence: TOCUSTOMER ( [,]) where is an array or the first word of an allocated block and is an optional error label. The ?MBTC packet differs from one environment to another, so check either the AOS or the AOS/VS Programmer's Manual. Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.22 UDIV A new routine was added which gives the user the ability to divide a 2 word integer by a 1 word integer, avoiding the overhead of the full double integer arithmetic package in the 16 bit environment. 1.22 UDIV 10 Calling Sequence: UDIV (, , , , ) where is an integer (1) is an integer (1) is an integer (1) is an integer (1) is an integer (1) Available for all environments. 1.23 UNWIRE Allow pages that have been WIRE'd to be swappable to disk and removed from the current working set. Calling Sequence: UNWIRE (, [,]) where is an integer(2) or pointer, is an integer(2) or pointer and is an optional error label. The caller must have the privilege to become a resident process in order to use this routine. Basically, this routine allows the system to remove pages within the range of to from your working set, thus removing the protection set by the WIRE 1.24 VERIFYCUSTOMER Verify that a process is a customer of the current process. In order to use this routine, you must be a server. Calling Sequence: VERIFYCUSTOMER ( [,]) where is an integer(1) and is an optional error label. 1.24 VERIFYCUSTOMER 11 This routine will return an error if the process is not a customer of the server who made the call. Available for AOS, AOS/VS-16 and AOS/VS-32 environments. 1.25 WALLOCATE Reserve a number of words of memory, obtain their location, and initialize the words to zero. This routine is analogous to the ALLOCATE routine, except is a double word quantity by default if is not passed. Calling Sequence: WALLOCATE (, [[,], ]) where is a double word integer or pointer, is an integer(1) if is present or an integer(2) if is not present, is an integer(1), and is an optional error label. The format of is an inclusive OR of the following fields: bits 12-15 (1R8-17R8) - alignment factor, to insure that the block returned is aligned on at least a 2**n boundary. Similar to /ALIGN=n in LINK. bit 10 (40R8) - If this bit is 1, the block is to be zeroed before returning, else it is not zeroed. bit 9 (100R8) - If this bit is 1, the size field is a double word quantity (integer(2)), otherwise it is a single word quantity (integer(1)). bit 8 (200R8) - If this bit is 1, the free list is not searched. Instead, core is taken from the top of the stack. Note: The argument is more optional than and if not present, defaults to 140R8 (i.e. zero the block, size field is a double word, no alignment, and search the free list before allocating from the stack). When using WALLOCATE (or ALLOCATE) in AOS/VS-32, four extra words of overhead are allocated along with the allocation request. When using ALLOCATE in either AOS, AOS/VS-16, or RDOS, the overhead is one word when using the EXACTFIT allocation method and two words when using either BESTFIT or FIRSTFIT methods of allocation. 1.25 WALLOCATE 12 Available for AOS/VS-32 environment only. 1.26 WBUFFER Create a buffer pool area in memory and return its address. This routine is analogous to the BUFFER routine except both the and the arguments are double integers. Calling Sequence: WBUFFER (, [,]) where is an integer(2) or pointer, is an integer(2) and is an integer(2). Note: The argument is ignored if the unshared cache memory routines are used. If the shared page cache memory routines are used (library DGL32SCACHE.LB), then is ignored and is the maximum number of shared pages to use the cache memory routines for this buffer pool. Available for AOS/VS-32 environment only. 1.27 WGALLOCATE Allocate a number of words of memory from the global heap and return a pointer in a multitask environment. This routine is analogous to the GALLOCATE routine except is a double word by default if is not passed. Calling Sequence: WGALLOCATE (, [[,], error]) where is an integer(2) or pointer, is an integer(2) or integer(1) depending on , is an integer(1) and is an optional error label. The format of is an inclusive OR of the following fields: bits 12-15 (1R8-17R8) - alignment factor, to insure that the block returned is aligned on at least a 2**n boundary. Similar to /ALIGN=n in LINK. 1.27 WGALLOCATE 13 bit 10 (40R8) - If this bit is 1, the block is to be zeroed before returning, else it is not zeroed. bit 9 (100R8) - If this bit is 1, the size field is a double word quantity (integer(2)), otherwise it is a single word quantity (integer(1)). Note: The argument is taken to be an integer(2) by default. Available for AOS/VS-32 environment only. 1.28 WIRE Insure that pages within a given range are always in your working set, even if they have not been recently referenced. Calling Sequence: WIRE (, [,]) where is an integer(2) or pointer, is an integer(2) or pointer, and is an optional error label. The caller must have the privilege to become a resident process in order to use this routine. Basically, this call pre- vents the system from removing pages within the range of and from your working set. Available for AOS/VS-32 environment only. 1.29 WQTASK Queue a task for execution after a specified delay. This routine is analogous to the QTASK routine except that the and arguments are double word quantities. Also, as with TASK and RUNTASK, you are forbidden to initiate a task that begins in a different ring. If the current ring is not 7, the default stack base and limits are saved when the task is initiated and restored when the task is terminated, and a stack is allocated from the global heap. Since is a single word quantity, you cannot pass an address to the task. If you specify a zero stack size, you will be given 1000R8 (512.) words by 1.29 WQTASK 14 default. Additionally, we do not support the notion of not giving the task any stack at all; as in the case where a zero stack size was specified and the first instruction was not a save. Calling Sequence: WQTASK (, , , , , , [, [, [, [, [, [,]]]]]]) where is a procedure, is an integer(1), is an integer(1), is an integer(1), is an integer(2), is an integer(1), is an integer(1), is an integer(1), is an integer(1), is an integer(1), is an integer(1), is an integer(2) or pointer, is an error label. Available for AOS/VS-32 environment only. 1.30 WRUNTASK Execute a routine as a task with arguments and error handling. This routine is analogous to RUNTASK except that and are integer(2) quantities. Calling Sequence: WRUNTASK ( [,, , , , ) where is a procedure, are any number of any type, is an integer(1), is an integer(1), is an integer(2), is an integer(2) or pointer, and is an error label or NOLABEL. 1.30 WRUNTASK 15 Note: The is a double word because an errorcode+3 could possibly be returned in it, so if you want to use the WAITFOR feature, you must use the extended WAITFOR call. Also, as with TASK and QTASK, you are forbidden to initiate a task that begins in a different ring. If the current ring is not ring 7, the default stack base and limits are saved, and restored upon task termination, and a stack is allocated from the global heap. If you specify a zero stack size, you will be given 1000R8 (512.) words by default. Available for AOS/VS-32 environment only. 1.31 WTASK Initiate a task. This routine is analogous to TASK except that the optional argument is an integer(2) quantity. Calling Sequence: WTASK (, [, [, [, [,]]]]]) where is a procedure, is an integer(1), is an integer(1), is an integer(1), is an integer(2) and is an error label or NOLABEL. Note: As with TASK and RUNTASK you are forbidden to initiate a task that begins in a different ring. If the current ring is not ring 7 the default stack base and limits are saved, and restored upon task termination, and a stack is allocated from the global heap. If you specify a zero stack size, you will be given 1000R8 (512.) words by default. Available for AOS/VS-32 environment only. 1.32 XCT3 Execute a three-word instruction on the assembly level. Calling Sequence: 1.32 XCT3 16 XCT3 (, , , , , , [,]) where is an array, or the first word of an allocated block of three words, is an integer(2) or pointer, is an integer(2) or pointer, is an integer(2) or pointer, is an integer(2) or pointer, is an integer(1) and is a label. Note: The four accumulator variables are double word quantities. Available for AOS/VS-32 environment only. 1.33 XCT4 Execute a four-word instruction on the assembly level. Calling Sequence: XCT4 (, , , , , , [,]) where is an array, or the first word of an allocated block of four words, is an integer(2) or pointer, is an integer(2) or pointer, is an integer(2) or pointer, is an integer(2) or pointer, is an integer(1) and is a label. Note: The four accumulator variables are double word quantities. Available for AOS/VS-32 environment only. 2 Errors in the AOS & AOS/VS Runtime Manual 1) On page 3-21, it says that system code values are listed in SYSID.SR. This is true if you are running under AOS, if you are running under AOS/VS-16, the file SYSID.16.SR 2 Errors in the AOS & AOS/VS Runtime Manual 17 contains the system code values. 2) See other chapters in this release notice to see how error handling (chapter 4) has changed. 3) On page 4-6 in discussing ERPRINT, the example calls READERROR to check if the error was <> 25 (FILE DOES NOT EXIT), and calls ERPRINT if it isn't. If you use this example as is, it will never print an error message because READERROR will clear the error indication. If you don't want READERROR (or the new LASTERROR) to clear the error indication, you must pass a non 0 argument to READERROR. 4) On page 5-9, the example to SETACL does not work because GETACL returns a final null ("<000>") in the string which terminates the acl. To do the example correctly, you would have to assign the result from GETACL to a normal string and then concatenate the acl you want to all but the last character, using SUBSTR. 5) On page 5-17, the string passed to SETSEARCH must have only one null "<000>" between the names, rather than two as shown in the example. It must have two trailing nulls at the end so that the operating system can determine the end of the search list. 6) On pages 6-1 and 6-18, WRITESTRING is described as being a binary write. Actually under AOS and AOS/VS the routine does a dynamic write, but not binary. It does not set the ?IBIN bit in the ?ISTI field. The difference between a dynamic write and a binary write is that line feed, tabs, etc. are not handled by the PMGR but rather passed direc- tly to a device such as a console. 7) On page 6-16, the example for READSTRING has a constant string for the second argument (that is the string being read in). This will generate an address exception if run. You should only use READSTRING to read in string variables or SUBSTR expressions of string variables. 8) On page 8-5, due to the new error handling, the Runtime Global Table is now 8 words for a task instead of 7. 9) On page 9-1, it should mention that if you only use ATASK, and don't use either TASK, RUNTASK, or QTASK, the DG/L environment looks like the single task environment (that is GALLOCATE is the same as ALLOCATE, and the main program gets all of memory for the stack/heap, and is ID 1 instead of getting a portion of memory and ID 255). Also you cannot initiate DG/L procedures as tasks with ATASK. 2 Errors in the AOS & AOS/VS Runtime Manual 18 10) See other chapters in this release notice to see how memory allocation has changed (pages 3-15, 3-16, 9-20, & 9-21 in the runtime manual). 11) On page 10-2, the /ERR= switch does not exist, it is /E= to list compiler errors on file . 12) On page 10-3, the format of the listing produced by the /V switch has changed, see other portions of this release notice. 3 Errors and Additions - RDOS Runtime Manual The following occur on pages 1-17 and 1-18. 1) In the description of the 3-word string/bit string descriptor, WORD 0 is a byte pointer to the string for character strings and a word pointer to the string for bit strings. 2) Note that the current and maximum length for bit strings are in number of bits. 3) For a substring specifier of a BIT string, WORD 1 is a negative BIT offset, not BYTE offset, into the parent string. 4) (at top of page 1-18) "String AND BIT arrays comprise arrays of three-word string specifiers, each pointing to and giving the size of the string". 5) The examples on page 1-18 fail to include examples of arrays and BIT variables, which are included in the AOS (& AOS/VS) version of the manual and are reproduced below. 6) The following code would define in assembly language the data objects you would declare in DG/L as EXTERNAL BIT(6) BIT1; EXTERNAL INTEGER(2) ARRAY ARR12[5:10]; .ENT BIT1 BIT1: BIT.ST ;word pointer 6 ;maximum size 0 ;current size BIT.ST: .BLK 1 ;6 bit string needs only one word ;------------------------------------- 3 Errors and Additions - RDOS Runtime Manual 19 .ENT ARR12 ARR12: MYNAME ;array name is pointer to array 5 ;low bound 10 ;high bound 1 ;number of dimensions - all precede the MYNAME: .BLK 2*(10.-5+1) ;actual array 4 General Runtime Information 1) All bit strings (except substrings) start on a word boundary. 2) The second word of all substrings is described in runtime manuals as a "negative offset into the parent string". This means a negative number whose absolute value is the byte or bit offset into the parent string. The number MUST be negative, because the sign of this number is how the runtime routines distinguish a substring specifier from a normal string specifier. 3) The bottom example on page 1-19 of revision 0 of the AOS runtime manual reserves a 7 word area to hold a bit string of maximum length 6, when a single word would be sufficient as shown in the version above: (.BIT: .BLK 1). Do not be misled! 5 Shared Page Cache Memory Revision 3.20 of DG/L allows you to use the shared page mechanism for cache memory instead of the default mechanism which uses block I/O for programs which run on AOS or AOS/VS. The advantages of using shared pages are: 1) If the operating system has free pages available that are not used by other programs directly, it will not write the data to the disk, but rather keep it around and map it back into your address space when needed. In effect you have two levels of caching before going to the disk. This can significantly speed up your program. On a 1 Mega-Byte (MB) C330 (AOS revision 3.30), we noticed that jobs that took 12-13 hours, would take about 8 hours when we used a DG/L compiler that used the shared page cache instead of the normal cache. Revision 3.20 AOS DG/L uses the shared page cache. 5 Shared Page Cache Memory 20 2) Files are updated logically the instant data is put in the shared pages, so that if your program aborts, the file(s) will reflect the latest changes made to them. 3) More than one program can access a shared page cache file at a time, and each program will update the file instantly, provided all programs use the shared page cache memory. For example, we have an internal tool called TREDT which we use for looking at the DG/L tree file. We can now look at the files while the compiler is running since we use the shared page cache memory routines ourselves. Some of the disadvantages to using the shared page cache memory are: 1) If you have heavy memory contention, using shared page I/O could cause problems for you. This is especially true on AOS/VS since it is a demand paged operating system and a single program's logical address space is a lot larger than the physical amount of memory. The system cannot store shared pages that have been freed up in unused memory because there is no unused memory. If this is the case, the shared page cache will be slower because the operating system still has to check the system LRU chain before issuing the physical I/O request. Because of the charac- teristics of AOS/VS, the revision 3.20 AOS/VS DG/L compiler uses the unshared cache instead of the shared page cache, except for our own debugging purposes as described above. 2) Buffers are 1,024 words each for the shared page cache, compared to 256 for the unshared cache. For programs with very tight memory requirements, there might not be enough space to use the shared page cache. By cutting down the amount of buffer space, the program would thrash by con- stantly doing system calls to map in different pages. 3) The user has to reserve a number of pages with .NMAX or .VMAX (edit DGLPARAM.SR that is supplied with this revision), so that the initializer does not grab all of the pages to use as the stack and heap. To use the shared page cache memory, do the following: 1) Edit and assemble DGLPARAM.SR to set .NMAX and/or .VMAX so that a number of pages are reserved by the initializer, and include this in your LINK line. An alternative would be to use DEDIT (AOS) or FED (AOS/VS) to change the values before the program is run. Perhaps .VMAX is easier to use since it says to reserve `n' pages for use with the shared page system calls. 5 Shared Page Cache Memory 21 2) Change the call to BUFFER so that it has three arguments. The second argument is ignored if the shared page cache is used, much like the use of the virtual memory cache option in RDOS. The third argument to BUFFER is the number of shared pages to use in the buffer chain. The EXTERNAL INTEGER (1) NUMBUF receives the number of shared pages that were available when the initializer passed control to the main program. 3) Use DGLIBS instead of the normal DGLIB to link your program. 6 Reserving Shared Pages on AOS, AOS/VS In order to use either the shared page I/O routines, or the shared page cache memory routines (AOS, AOS/VS only) you must reserve pages to be used for the actual ?SPAGE system call. The purpose of this chapter is to clarify how to reserve the pages. There are several ways to do so, including the following: 1) The value at location .NMAX tells the initializer the maximum number of unshared pages to take for the stack and heap. If you decrement .NMAX, the initializer will not take as many pages, leaving some for SPAGEing. Note, .NMAX does not count the number of shared pages used to store the program code, so this must be figured in as well. For example, if an AOS program wanted to use 5 pages for shared pages, and the code took 7 pages, .NMAX would be set to 20. (32.-7-5 = 20.). The EXTERNAL INTEGER (1) NUMBUF will receive the number of pages available for SPAGEing. You can change .NMAX by editing the DG/L parameter file DGLPARAM.SR, assembling it, and including it in the LINK line, or you can change it with DEDIT (AOS) or FED (AOS/VS) after the program has been linked. .NMAX is a single word for AOS and 16 bit AOS/VS, and is a double word for 32 bit AOS/VS. Defaults are: AOS: .NMAX: 32. AOS/VS-16: .NMAX: 32. AOS/VS-32: .NMAX: .DWORD 1000 2) The value at location .VMAX tells the initializer how many pages to reserve for use as shared pages. If you increment .VMAX, the initializer will not take as many pages for the stack and heap. Note that the initializer first looks at .NMAX and limits the number of pages it will take to that value. Then it decrements the amount to take by the value in .VMAX. For example, if an AOS program wanted to use 5 6 Reserving Shared Pages on AOS, AOS/VS 22 pages for shared pages, .VMAX would be set to 5. The EXTERNAL INTEGER (1) NUMBUF will receive the number of pages available for SPAGEing. You can change .VMAX by editing the DG/L parameter file DGLPARAM.SR, assembling it, and including it in the LINK line, or you can change it with DEDIT (AOS) or FED (AOS/VS) after the program is linked. .VMAX is a single word for AOS and 16 bit AOS/VS, and is a double word for 32 bit AOS/VS. Defaults are: AOS: .VMAX: 0 AOS/VS-16: .VMAX: 0 AOS/VS-32: .VMAX: .DWORD 0 3) You can use the /SRES=n switch on LINK to reserve `n' shared pages starting at ?SBOT before laying down the data in partitions that are shared (such as program code and constants). You cannot use this option with the shared page cache, but you can use it with shared page I/O (SHOPEN, SHREAD, etc.). First of all you must use the /Q switch on the DG/L compile. The address of the first page can then be found by doing the following: EXTERNAL INTEGER ?SBOT; % bottom of shared partition POINTER PAGE; ..... PAGE := ADDRESS( ?SBOT ); 4) You can reserve the pages manually with assembly language, and then align them on a page boundary at LINK time. The assembly language file would look like: .TITLE SAREA .ENT SAREA .NREL 1 SAREA: .BLK n*1024. ;n is number of pages .END ;to reserve The LINK line would look like: XEQ LINK ... SAREA/ALIGN=10 ... [DGLIB] You cannot use this option with the shared page cache, but you can use it with shared page I/O (SHOPEN, SHREAD, etc.). The address of the first page can be found by the following: 6 Reserving Shared Pages on AOS, AOS/VS 23 EXTERNAL INTEGER SAREA; % bottom of shared partition POINTER PAGE; ..... PAGE := ADDRESS( SAREA ); If you use one of the first two options, and use shared page I/O (SHOPEN, SHREAD, etc.), your program would look something like the following, where the conditional code option X is used for AOS/VS-32 programs and MYRING is used to get the base of the current ring. .... EXTERNAL PROCEDURE GETSHARED, SHPARTITION; EXTERNAL INTEGER NUMBUF; /**X EXTERNAL POINTER MYRING; */ % 16 bit progs don't worry about ring fields /**-X LITERAL MYRING (0); */ POINTER START, SIZE, PAGE; .... % allocate shared pages GETSHARED( START, SIZE ); START := START - NUMBUF; SIZE := SIZE + NUMBUF; SHPARTITION( START, SIZE ); .... % PAGE is first shared page PAGE := START * 1024 + MYRING; ... 7 Passing Strings to System Call Procedures The following routines when passed a string will create a local copy of the string on the stack and append a null ("<000>") to it by calling an internal procedure .SCPY. This means that the string you pass to the routine does not have to end in a null. If you create packets yourself, or call any other routine not listed here (particularly ERROR), you will have to terminate the string explicity with a null. String constants always have a null beyond the current length specified. After each routine name, we have listed in parentheses the environments for which that routine exists (`n' = RDOS Nova, `e' = RDOS Eclipse, `a' = AOS, `16' = AOS/VS-16, and `32' = AOS/VS-32). ACCESS (n,e,a,16,32) ACHAIN (a,16,32) ACREATE (a,16,32) APPEND (n,e,a,16,32) ASEND (a,16,32) ASSIGN (a,16,32) BLOCKPR (a,16,32) BOOT (n,e) 7 Passing Strings to System Call Procedures 24 CCONT (n,e,a,16,32) CDIR (n,e,a,16,32) CHAIN (n,e,a,16,32) CHPRIORITY (a,16,32) CHTYPE (a,16,32) CONNECT (a,16,32) CPART (n,e,a,16,32) CRAND (n,e,a,16,32) CREATE (n,e,a,16,32) CTERM (a,16,32) DATAOPEN (n,e,a,16,32) DEASSIGN (a,16,32) DELETE (n,e,a,16,32) DIR (n,e,a,16,32) ENQUEUE (a,16,32) EOPEN (n,e,a,16,32) EQUIV (n,e) EXBG (n,e) EXFG (n,e) GETCPN (a,16,32) GETDEV (n,e,a,16,32) GETPORT (a,16,32) GLINK (a,16,32) GOPEN (a,16,32) IHIST (a,16,32) INIT (n,e,a,16,32) LINK (n,e,a,16,32) MTOPD (n,e) NCONT (n,e,a,16,32) OPEN (n,e,a,16,32) OVOPN (n,e) PATHNAME (a,16,32) PORTLOOKUP (a,16,32) RELEASE (n,e,a,16,32) RENAME (n,e,a,16,32) RINGLOAD (32) ROPEN (n,e,a,16,32) RUNTIME (a,16,32) SETACL (a,16,32) SETDEV (n,e,a,16,32) SHOPEN (a,16,32) STATUS (n,e,a,16,32) SWAP (n,e,a,16,32) TERM (a,16,32) UNBLOCKPR (a,16,32) UNLINK (n,e,a,16,32) USERNAME (a,16,32) 8 Ring Information DG/L supports the ring architecture of the MV/FAMILY. You can LINK DG/L procedures in inner rings, and you can call inner rings from outer rings with a minimum of hassle. The following qualifi- cations apply to inner rings: 1) DG/L knows nothing about ring environments other than the ring the procedures are loaded in. Programs in other rings could be written in any other language, and have different conventions, as long as the inter-ring calling sequence is the same. 2) The DG/L file numbers are unique to each ring because other rings might not be DG/L programs. 3) The procedures in the DG/L runtime library must not be called directly from an outer ring. You can call a pro- cedure written in DG/L from the outer ring and then have that procedure call the library routine. If a DG/L library procedure is called from a different ring, it will report an error. The main reason for this restriction is that many of the runtimes are passed addresses and/or packets which could contain trojan horse pointers. Also many of the routines modify the global or process tables which are 8 Ring Information 25 maintained on a per ring basis, or they modify the caller's stack. 4) Even though AOS/VS will let you do it, TASK, RUNTASK, and QTASK do not let you initiate a task in a different ring. This is because the stack allocated by these procedures is in the current ring, which couldn't be accessed by a procedure in a higher ring. 5) If you jump to a label which is located in a different ring, an error message will be generated, and the task will continue at the point of the cross ring call's return. 6) The default error message writer always opens up the ring 7 .ST file to determine the location of the error addresses. This is because under AOS/VS 1.20 there exists no way to find out the name of the .PR file loaded into any ring except 7. 7) Scheduling may be turned on during a cross ring call, because under AOS/VS 1.20, there exists no way of finding whether the caller in a different ring had scheduling enabled or disabled. When there is global allocation, (from task initiation, BUFFER, or DATAOPEN from an inner ring), or when it is the first time that a task calls an inner ring DG/L procedure, scheduling will be disabled and will be reenabled when exiting the critical region. 8) You must set up the ring in which the procedures will run with the LINK switch /RING=n, which specifies that the program is to run in ring `n'. Also, the stack requirement must be set at LINK time with the switch /STACK=n, where `n' is the amount of stack each task needs multiplied by the number of tasks. You should also specify 32 tasks unless you know for certain that the outer ring program will never need that many tasks. Because of an AOS/VS 1.20 limitation, you must specify 2 MB, with the /MTOP=2 switch. The unshared area must exist in only the first megabyte of memory, and the shared area must exist in only the second megabyte. 9) The inner ring DG/L environment looks like the multitasking environment. For example, GALLOCATE allocates memory from a separate global heap instead of being the same as ALLOCATE. 10) Because ring 7 DG/L programs keep a count of the number of tasks currently executing and the number of tasks queued up, these counts will not be updated for tasks initiated in inner rings. This is because AOS/VS does not call ?UTSK and ?UKIL for non-ring 7 tasks. This could cause a program 8 Ring Information 26 to terminate when it thinks it is the last task executing, even though there are tasks executing in the inner ring. Also bear in mind that the number of concurrent tasks is limited to the number specified for the ring 7 program. 11) The stack will not be returned to the global heap in the following case: * A task is initiated in ring `B' * It calls ring `A' which does a KILL (?KILL) * ring `A' < ring `B' < ring 7. 12) DG/L procedures that are callable from an outer ring must be compiled with the /INNER switch on the DG/L compiler to initialize the DG/L environment for that ring. Procedures that are only called within the ring do not need the /INNER switch. If you use the /INNER switch on a program that runs in ring 7, you will get a runtime error. 13) The following program illustrates how to build and call inner ring programs. It consists of four files, two of which are used to build the inner ring program, and two of which are bound into ring 7 and call the inner ring program. The files are: * RING5.DG -- ring 5 DG/L procedures * GATE5.SR -- build the ring 5 gate array * PROG.DG -- ring 7 DG/L program * EXTN.SR -- define ring 5 gate addresses % RING5.DG -- ring 5 procedures % % Define 3 procedures to be called from ring 7. % OPEN5 -- Open a channel in the inner ring. % WRITE5 -- Write a DG/L string. % CLOSE5 -- Close the inner ring channel. cluster ring5; begin global procedure OPEN5; begin OPEN( 10, "@OUTPUT" ); end; global procedure WRITE5( str ); string str; begin external procedure WRITESTRING; WRITESTRING( 10, str ); end; 8 Ring Information 27 global procedure CLOSE5; begin CLOSE( 10 ); end; end; % GATE5 -- Define gate array for inner ring procedures. % This defines which procedures can be called from outer % rings, and what is the highest ring that can call it. .TITLE GATE5 .EXTG OPEN5 ;OPEN channel routine .EXTG WRITE5 ;WRITE routine .EXTG CLOSE5 ;CLOSE channel routine .ENABLE ABS,DWORD .LOC 34 .GATE ;address of gate array .NREL 1 .GATE: 3 ;number of gates (7S3)+OPEN5 ;gate 0, callable from ring 7 (7S3)+WRITE5 ;gate 1, callable from ring 7 (7S3)+CLOSE5 ;gate 2, callable from ring 7 .END ******************************************** % PROG -- load ring 5 routines and call them. % this program runs in ring 7. begin external procedure RINGLOAD, OPEN5, CLOSE5, WRITE5; RINGLOAD( "RING5.PR" ); % load the ring OPEN5; WRITE5( "This string printed from ring 5." ); CLOSE5; end; % EXTN -- define the externals for the ring 5 procedures .TITLE EXTN .ENT OPEN5 ;open channel routine .ENT WRITE5 ;write routine .ENT CLOSE5 ;close channel routine 8 Ring Information 28 OPEN5= (5S3)+0 ;ring 5, gate 0 WRITE5= (5S3)+1 ;ring 5, gate 1 CLOSE5= (5S3)+2 ;ring 5, gate 2 .END ******************************************** To build the ring 5 procedures do the following: X DGL/INNER/CODE=32 RING5 X MASM GATE5 X LINK/SYS=VS32/RING=5/MTOP=2/STACK=32000/TASKS=32 & RING5 GATE5 [DGLIB32] To build the ring 7 main program do the following: X DGL/CODE=32 PROG X MASM EXTN X LINK/SYS=VS32 PROG EXTN [DGLIB32] To execute the program, make sure RING5.PR is in your searchlist or in your current directory, then say: X PROG 9 AOS/VS 32 bit environment This chapter explains what the AOS/VS 32 bit runtime environ- ment looks like from assembly language, so that you can write your own assembly language routines to be called from DG/L. 9.1 String Specifiers Because pointers are now two words instead of one, the string specifier packet is now four words instead of three. The specifier fields are: Symbolic Numeric Description Offset Offset +-----------------------------------+ SSPTR 0 | Byte pointer (string) to data (or)| | Word pointer (bit) to data (or) | 1 | Word pointer to parent (substring)| +-----------------------------------+ SSMAX 2 | * | Maximum size | +-----------------------------------+ 9.1 String Specifiers 29 SSLEN 3 | Current size | +-----------------------------------+ SSSIZ 4 size of specifier in words * If bit 0 of the maximum size field is 0, then the specifier is a normal character or bit string, and SSPTR contains either a byte pointer to the character string or a word pointer to the bit string. If bit 0 is a 1, then the specifier is a substring, and the max size field is the complement of the byte (or bit) number in the parent string that the substring starts at, and the pointer in SSPTR is a word pointer to the parent string specifier. 9.2 Array specifiers As before, arrays accessed as EXTERNAL or GLOBAL variables from DG/L have a pointer to the actual start of the array. This pointer is now a double word quantity, as are the specifier fields. When an array is pushed as an argument, the address of the start of the array is pushed onto the wide stack. An array looks like: Offset Description +---------------------------+ 0 | Pointer to the start of |----------\ 1 | the array | | +---------------------------+ | | ...... | | +---------------------------+ | -4*n-2 | low bound for the nth | | -4*n-1 | dimension | | +---------------------------+ | -4*n | high bound for the nth | | -4*n+1 | dimension | | +---------------------------+ | ...... | +---------------------------+ | -6 | low bound for the first | | -5 | dimension | | +---------------------------+ | -4 | high bound for the first | | -3 | dimension | | +---------------------------+ | -2 | number of dimensions | | -1 | | | +---------------------------+ | 0 | Start of the array |<---------/ | || | 9.2 Array specifiers 30 | \/ | | ...... | +---------------------------+ 9.3 Allocation of n words If you allocate a block of storage with ALLOCATE, WALLOCATE, GALLOCATE, or WGALLOCATE, the format is: Offset Description +---------------------------+ -2 | negative size of the | -1 | allocated block | +---------------------------+ 0 | block allocated |<-----Pointer | || | returned | \/ | points here n-1 | ......... | +---------------------------+ n | negative size of the | n+1 | allocated block | +---------------------------+ 9.4 Calling Sequence DG/L 32 bit procedures use the LCALL, WSAV(R,S), WRTN calling sequence. As with 16 bit programs, pointers to the arguments are pushed in reverse order before doing the call. AC2 no longer has the old stack pointer in it, since the LCALL cleans up the stack automatically, and also tells us the argument count. For example, in the following DG/L program: BEGIN EXTERNAL PROCEDURE FOO; STRING (32) S; INTEGER ARRAY A[1:5]; FOO( 5, S, A ); END; To do the above DG/L program in assembly language, you would have to do the following (ignoring initialization and putting the string and array into fixed locations instead of on the stack): .... LPEF A ; Push addresses of A, S, LPEF S ; and 5 onto stack LPEF FIVE ; in reverse order 9.4 Calling Sequence 31 LCALL FOO,0,3 ; Call FOO .... ; Set up the array specifier: .DWORD 5 ; high bound .DWORD 1 ; low bound .DWORD 1 ; number of words needed A: .BLK (5-1+1)*1 .... ; Set up string specifier: S: .DWORD 2*STR ; byte ptr to string .WORD 32. ; max size .WORD 0 ; current size STR: .BLK (32.+1)/2 ; actual string .... FIVE: .WORD 5 .... FOO would then look something like: .ENT FOO FOO: WSAVR .... WRTN .... .END 9.5 ?USP Because 32 bit AOS/VS does not support the ?IESS system call, the DG/L environment uses ?USP (unique storage position -- loca- tions 16 & 17), to hold the address of the per task global table. Users are forbidden 9.6 ?ZBOT In order to provide the Jump 0 handler for the AOS/VS 32 bit environment, the bottom of ZREL is set up to 54R8 instead of 50R8 by setting the symbol ?ZBOT. If you also need to bump the bottom of ZREL, start at 54R8. 9.7 Building a 32 bit MASM.PS 9.7 Building a 32 bit MASM.PS 32 To build a MASM.PS for the AOS/VS 32 bit environment, use the CLI macro DGL32MACPS.CLI. First you must have MASM.PR (and any files it may need), PARU.32.SR, SYSID.32.SR, and SKIPS.SR in your searchlist, as well as the DG/L directory. Note, AOS/VS MASM revision 1.10 gave various errors in assembling files using MASM.PS created with DGL32MACPS.CLI; MASM revision 1.20 fixes these problems. Useful symbols that are defined: FARG -- Offset from the wide frame pointer (WFP) of the argument count (narrow quantity). FOV -- Offset from WFP of the OVK, OVR flags (narrow quantity). FAC0 -- Offset from WFP where AC0 is saved on stack. FAC1 -- Offset from WFP where AC1 is saved on stack. FAC2 -- Offset from WFP where AC2 is saved on stack. FOFP -- Offset from WFP where the old frame pointer is stored. FRTN -- Offset from WFP where the return address and carry are stored. ARG0 -- Offset from WFP to the first argument address. ARG1 -- Offset from WFP to the second argument address. ... ..... ARG15 -- Offset from WFP to the 16th argument address. Useful macros that are defined: RUNSAVE -- Do a WSAVR of (+1)/2 words, ie is the number of single words to save instead of double. 9.7 Building a 32 bit MASM.PS 33 INTSAVE -- Do a WSSVR of (+1)/2 words, ie is the number of single words to save instead of double. RUNCALL , -- Call procedure with arguments. The macro does an .EXTL and then LCALL ,0,. INTCALL -- Call with an internal calling sequence. The macro does an .EXTL and then LJSR . VALPTR , -- Checks argument addresses for validity thus protecting you from trojan horse pointers. is the minimum number of arguments the procedure is to have, and is the maximum. Note: all Ac's are trashed after the call (AC3 <- WFP). VALWRD -- Validate an argument which is a word pointer (i.e. what was pushed was a pointer to the word pointer). Used in routines like BYTEREAD, etc. is the argument offset like ARG. If the word pointer is valid the next instruction is skipped and AC0 contains the word address the argument points to. If the word pointer is invalid, the instruction following the macro is executed and AC0 contains the error code. VALSTR -- Validate a character string argument. Used in routines like READSTRING, etc. is an argument offset like ARG0. If the string (or substring) specifier is valid, the macro skips the next word and AC2 points to the specifier. If the string is not valid, the next instruction is executed and AC0 contains the error code. VALBIT -- Similar to VALSTR, except that a bit string is validated. NOERRLAB -- Load AC1 with the value to tell RT.ERR and SEV.ERR that you have no error label. RT.ERR -- Call the default error handler. All errors, except for 9.7 Building a 32 bit MASM.PS 34 EREOF (End of File) are Fatal to Process. The error EREOF is nonfatal and may return. AC0 <- Error Code AC1 <- Error label indicator SEV.ERR -- Call the error handler setting the severity and type of the error. AC0 <- Error Code/Error Text address AC1 <- Error label indicator AC2 <- Severity & Type of the error 10 Multitasking 10.1 Stack Sizes 1) The default size for the MAIN TASK stack space (initial startup of your multitasking program) is the size of available core divided by the number of tasks specified at link time (the /K option on RLDR, /TASKS= switch on LINK). To select a different main task stack size, edit file DGLPARAM.SR by changing the contents of location `.MSTK' from zero to the desired stack size. Then assemble DGLPARAM and include in your link line. Note .MSTK must be a double word quantity under AOS/VS-32. 2) The stack size argument (if not specified, 0 is specified): size interpretation ---- -------------- >0 Allocate that much stack space, taking the error return if it isn't available. <-1 Try to allocate - words for stack; if it's not available, wait until it is and then proceed. Note, the task calling TASK, QTASK, or RUNTASK will wait before doing the ?TASK call -- so if there are no other tasks executing, this might wait forever. =-1 Try to allocate the default amount of stack, waiting as described above it it's not available. 10.1 Stack Sizes 35 =0 16 bit programs: If the task either begins with a SAVE, or starts in an overlay, allocate the default amount of stack, taking the error return if it isn't available. If the task does not begin with a SAVE and starts in the ROOT, then no stack is given. Note -- most DG/L routines cannot be called from this task because the task area is not initialized. Also RUNTASK will always allocate the de- fault amount even if the task does not begin with a SAVE and is in the ROOT. =0 32 bit programs: Try to allocate the default amount of stack, taking the error return if that is not available. 3) The default stack size for a task initiated by TASK, RUNTASK, or QTASK is 400 octal (256 decimal words) for 16 bit programs and 1000 octal (512 decimal words) for 32 bit programs. This can be changed by editing DGLPARAM.SR; the entry .DSTACK defines the default stack size. 4) Note that the stack allocated includes a number of words which will not be available for your actual stack space use. These are documented in the Multitasking chapter of each of the runtime manuals. A task which doesn't need any IOCBs would still have a Global area, TCB extender, Endzone and a 5-word frame header all allocated before the user code gets to use any of it. Since the TCB extender is currently 12 words for AOS/VS-32, 8 words for AOS/VS-16, 24 words for AOS or 29 for RDOS/RTOS, you need to allocate 47 words (for AOS/VS-16, 60 for AOS, 65 for RDOS) more for each stack than the actual stack frames of your programs will take up. Also note the table below. The table is slightly misleading in IOCBs; they are only allocated upon a call to READ, WRITE, OUTPUT, or FORMAT, and are freed when the formatted I/O is finished. 5) As noted in middle of the last paragraph, TCB EXTENDER SIZE in the manual is incorrect, as it is now 12 words for AOS/VS-32, 8 words for AOS/VS-16, 24 words for AOS, and 29 words for RDOS DG/L. 6) Due to the way TASK, QTASK, and RUNTASK allocate the user's stack, it uses two extra words for heap management overhead. See the table below. Be aware of this. 10.2 Warnings 36 10.2 Warnings If you want to start up a 16 bit task and give it a stack, it must either begin with a SAVE instruction or it must be given a non zero stack size. The only way you can start up a 16 bit task using QTASK or TASK and have it not be given a stack is to give it a zero stack size AND have it not begin with a SAVE instruction. All DG/L procedures begin with a SAVE instruction (WSAVR or WSAVS for 32 bit programs, STA 3,.ND1 on the Nova, followed by a call to the correct .SAV routine) 1) Except for OVQTASK, you cannot start up a task that begins in an overlay in RDOS. In AOS or AOS/VS-16, if a task begins in an overlay it is assumed to need a stack. 2) In addition, if you are using the debugger on a 16 bit multitasking program, don't set a breakpoint at a SAVE. DG/L's multitasking checks to see if the procedure has a SAVE, and a breakpoint is not a SAVE, so set your break- point at the next instruction after the save. If you want to see where the procedure came from, FP points to the return address/carry. 3) You cannot task internal procedures as the initial pro- cedure of a task, as this violates scoping rules. It may work, particularly if the internal procedure only uses OWN or GLOBAL variables in common with the caller, or no variables in common at all, but there are a number of things the compiler assumes about scoping, particularly the scoping of temporaries and constants, that may get you into trouble if you try this. 4) You can task separately compiled procedures, or GLOBAL procedures that are defined in a CLUSTER. This sort of scoping is not assumed within a CLUSTER. 5) Do not use a Task I.D. of 255 as it is reserved as the Task I.D of the main program when the multitask initializer is used (i.e. TASK, QTASK, or RUNTASK were referenced). If the singletask initializer is used, the main program gets the ID of the first task (=1) {see ATASK below}. 6) If you initiate queued tasks on AOS or AOS/VS via ATASK or assembly language calls that are scheduled to begin after the last normal task has killed itself, these queued tasks will not execute, as the last task will do a ?RETURN instead of ?KILL to avoid the spurious error message: 252 `LAST TASK WAS KILLED'. The workaround is to either initiate the queued tasks with QTASK, or to have a task 10.2 Warnings 37 wait until the last queued task has terminated. 7) If you do the following (PRIORITY > 0): PRIORITY( 0 ); /* give myself highest priority */ TASK( TASKA, DATUM, ID, PRIORITY, STACK, ERR ); AKILL( PRIORITY ); /* kill the task we just tasked up */ The stack space allocated for TASKA will not be returned to the global heap due to the fact that the initial wart has not yet executed (and has not set ?USP to indicate this is a DGL-style task and to return it's stack to the heap when it terminates). 10.3 TIDSTATUS TIDSTATUS is not available to the user running under AOS/VS due to the fact that the TCB's are no longer in the user address space. If you need to find the status of a task, use IDSTATUS instead. If there was no task with the specified ID, TIDSTATUS would take the error return, whereas IDSTATUS now returns a -1 if the specified task does not exist. See the later section of this chapter for details about IDSTATUS. 10.4 IDPRIORITY IDPRIORITY is not available to the user running under AOS/VS, because the way it is implemented is to search the TCB chain for a task with the specified ID, and return the priority field from that TCB. Since the TCB's are now in the AGENT address space instead of the user's, this routine cannot be implemented. 10.5 TIDABORT TIDABORT was documented incorrectly on page 22-4 of the AOS runtime manual (revision 0). It should be: TIDABORT( [,] ); Arguments: 10.5 TIDABORT 38 is an integer expression that gives the ident- ification number of the task you want to kill. is a statement label to which control transfers if an error occurs. Error Conditions: TASK ERROR CODES Reference: ?IDGOTO The task with the ID specified is aborted with an ?IDGOTO to the kill processing routine. Note that since the task's priority is not changed, the task will be killed when it next gets to execute. The difference between TIDKILL and TIDABORT in AOS and AOS/VS is that the priority is not changed for TIDABORT. In RDOS, TIDKILL waits until any outstanding system calls are finished before killing the task, whereas TIDABORT aborts most system calls. Under either system, the task can kill itself. 10.6 SIGNAL In the documentation on page 26-4 of the runtime manual (revision 0) about SIGNAL, it should be mentioned that if the mask is not specified, a default mask of -1 (all bits set) is used. You must use SIGNAL to wake up a task waiting in WAITFOR or WAITALL. Results are unpredictable if you use RECEIVE/TRANSMIT on the same condition word you use for SIGNAL/CLEAR/WAITALL/WAITFOR. 1) The manual doesn't clearly state that SIGNAL sets an inclusive OR of existing bits with bits passed in the SIGNAL call. That is, it doesn't clear any bits. 2) If the OR doesn't change the value, SIGNAL does not wake up any tasks, and is a No-op. 10.7 TASK and QTASK Revision 0 of the runtime manual is not clear as to how is accessed for the TASK and QTASK routines. It is a one word variable that is always passed by value to the procedure. That is, changing it in the task will not affect any other task, 10.7 TASK and QTASK 39 including the caller. TASK is documented on page 20-3, and QTASK is documented on 23-2. 10.8 Task Count and the Task Manager In DG/L revisions prior to 2.10, multitasking programs re- quired that you allocate (at link time) one more TCB than the maximum number of concurrent tasks, for use by the queued task manager, regardless if it was being used or not. With Rev 2.10, you no longer need to allocate this extra task unless you actually need it. In revision 2.10, the user must fire up the taskmanager explicity for queued tasking with TASKMANAGER. The ID must be non-zero and you must use our routine and not do the ?IQTS yourself. 10.9 ATASK DG/L multitasking routines (TASK, RUNTASK, and QTASK) cause special versions of several runtimes to be used including GALLOCATE and the initializer. ATASK does not force load these special versions, but it can coexist with either the singletask runtimes or multitask runtimes, which causes some differences in execution. For example, using the singletask initializer, when the main program returns, a normal ?RETURN is done. However, if the multi- task initializer was used, a ?KILL is done which does not stop the process if other tasks are executing. If you desire the multitask versions, declare somewhere in your program: EXTERNAL PROCEDURE TASK; even if you never call it. Note, you cannot task up a DG/L pro- cedure with ATASK because it does not set up the tables that DG/L runtimes need. 10.10 QTASK The runtime manual on page 23-2 (revision 0) says that the procedure argument to QTASK is a string expression when it must actually be an EXTERNAL PROCEDURE. 10.11 IDSTATUS 40 10.11 IDSTATUS For AOS & AOS/VS only, IDSTATUS (documented on page 21-2 of the revision 0 runtime manual) will now return -1 if there is no task with the given ID. Previously it returned 8, but now AOS & AOS/VS are using that particular bit for another purpose. 10.12 RUNTASK In RUNTASK, (documented on page 20-2 of the revision 0 runtime manual), passing a -1 as the means intercept and report all errors; this means ALL errors cause task termination including non-fatal ones. The runtime manual's description of key's code meaning can be clarified by the following: Code meaning input key = -1 Intercept and report all errors 0 Wait for a nonzero key(set by WAITFOR) output key = 0 Task is executing 1 Task has successfully completed >=3 Error in task (error code + 3) 10.13 RECIEVE The format of the call to RECEIVE on page 26-3 of the revision 0 runtime manual is incorrect. It should read: i := RECEIVE (key name); where is an integer variable that will receive the message and is a variable that contains the message. Also note that RECEIVE is an EXTERNAL INTEGER PROCEDURE. The calling sequence was documented backwards in the first rev of the manual. 10.14 NWRECEIVE There is a new routine to implement the Rev 1.00 AOS/VS (Rev 3.03 AOS) system call ?RECNW. The routine is: 10.14 NWRECEIVE 41 EXTERNAL INTEGER PROCEDURE NWRECEIVE; ...... := NWRECEIVE( ); This routine does not suspend the task like RECEIVE does if is zero (i.e. no task has done a TRANSMIT or WTRANSMIT to it). It can be used to clear before doing a TRANSMIT or WTRANSMIT. Note, if a task with higher priority has done a WTRANSMIT to , it will gain control first. Otherwise the caller regains immediate control. 10.15 Layout of a DG/L task's stack area On AOS and AOS/VS, TASK, RUNTASK, and QTASK allocate the following area for each task from the global heap: +---------------------------------------+ |1 (2) word(s) used in global allocation| .GP -----> +---------------------------------------+==========+ | Global table | | +---------------------------------------+ | | save area for ?IESS *** |----+ | +---------------------------------------+ | | | save area for ?IFPU ** | extender | +---------------------------------------+ | | | other stuff in extender |----+ | +---------------------------------------+ | initial | arguments to initial procedure | | .SP,.FP -> +---------------------------------------+ | (.WSP,.WFP) | Initial `SAVE' (runtask only) * | | (.WSB) +---------------------------------------+ size of | initial ?RCALL save * | stack +---------------------------------------+ user | stack used by program | asked .SP ------>| || | for (.WSP) | || | | | \/ | | .SSE ----->+---------------------------------------+ | (.WSL) | Endzone | | +---------------------------------------+ | | Allocated blocks from the local heap | | +---------------------------------------+==========+ | 1 (2) word(s) used in global allocation| +---------------------------------------+ * The stack area for an RDOS task is very similar to the above; the only exception is that the two SAVE areas are not done automatically (though the task would probably begin with a save). 10.15 Layout of a DG/L task's stack area 42 Also, the terminology for RDOS is different -- the ?IESS/?IFPU areas are set up with ESV.S/ESV.Z and field TELN in the TCB. ** There is no save area for ?IFPU for AOS/VS since the TCB's in the AGENT now contain the floating point save area. This is the main reason the extender shrank from 24 words to 7. *** There is no ?IESS area for 32 bit AOS/VS programs, since AOS/VS does not support ?IESS for 32 bit programs. Relevant fields have been added to the global table. Note that the save area for ?IFPU is allocated for RDOS, and AOS, even though the user put the /F switch (which disables float- ing point) on the compile. The names and numbers in parentheses are for 32 bit programs instead of their 16 bit counterparts. 10.16 ?USP word (location 16) Under AOS/VS-16, the multitask routines store 1B0 into ?USP to indicate that the task is a DG/L style task. This means that it has a stack and was initiated via either TASK, QTASK, or RUNTASK. Thus DG/L style tasks are forbidden to use ?USP. There is, however, a ZREL word that is swapped like ?USP that is available, .CMUSP. Non DG/L-style tasks can use ?USP, with the provision that they do not store 1B0 there. Under AOS/VS-32, all DG/L programs use ?USP (locations 16 & 17) to store the address of the global table, and all tasks are forbidden to modify it. 10.17 ?IESS area Under AOS/VS-16, each DG/L task sets up a four word ZREL save area that is swapped in/out each time the task is swapped in/out. RDOS/Eclipse and AOS the save area is 3 words. RDOS/nova sets up a five word ZREL save area including .ND1 and .ND2. AOS/VS-32 does not use the ?IESS area because the operating system doesn't support it. The ZREL locations are: .CMUSP - Meant to replace ?USP for DGL tasks (AOS/VS-16 only). .GP - Points to the global table that is unique to each task. .RP - A temporary that is used for various dirty purposes such as storing the return pointer. 10.17 ?IESS area 43 .RSP - This is called the Return Stack Pointer, and it is used in the interception of errors (ERRINTERCEPT and ERRTRAP). .ND1 - (RDOS/Nova only) \ --- used in emulation of Eclipse .ND2 - (RDOS/Nova only) / instructions. Note: If the task is not a DG/L task, the ?IESS call is not made. Under RDOS/Eclipse or AOS, if the user wants to set up an ?IESS area, it must be 3 words long, and start at .GP. The same holds true for RDOS/Nova, except that the area must be 5 words long, and for AOS/VS-16 which uses 4 words instead of 3. 11 Error Formats and Routines 11.1 Old DG/L Error Code 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Sev.| Type| Error code (12 bits) | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ || || || \\ || 00000R8 -- The error is a System Error || 10000R8 -- The error is an User Defined Error || 20000R8 -- The error is a text string || 30000R8 -- The error is a DG/L runtime Error \\ 000000R8P1 -- The error is Fatal to the Process 040000R8P1 -- The error is Fatal to the Task 100000R8P1 -- The error is Nonfatal 140000R8P1 -- The error is Absolutely Fatal 11.2 RDOS Error Codes 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 0 | Error Code (0-134) | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 11.3 AOS and AOS/VS-16 bit Error Code 44 11.3 AOS and AOS/VS-16 bit Error Code 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |Us| Error Group no.| Error Subcode | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ || || || \\ || Each product is assigned 1 or more groups || Sample DGC group numbers include: || 00000R8 - AOS error codes || 24000R8 - DG/L error codes || 77000R8 - AOS/VS only error codes \\ 000000R8P1 -- Error code reserved for Data General Corp. 100000R8P1 -- Error code available to users 11.4 AOS/VS-32 Error Codes 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Group Codes | Error Subcode | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Note that if the upper 16 bits are zero, it is the same as used for 16 bit mode and AOS. Data General reserves group codes 0 through 77R8 (error codes 0 - 77777R8) and 200R8 through 7777R8 (error codes 200000R8 - 7777777R8) for itself, allowing users to define group codes 100R8 through 177R8 (error codes 100000R8 - 177777R8) and 10000R8 through 17777R8 (error codes 10000000R8 - 17777777R8) for their own purposes. 11.5 Severity/type Format This is used in the new formats where we can't pass the severity and type fields in the upper 4 bits of the error code. 0 1 ... 11 12 13 14 15 +--+--+-----+--+--+--+--+--+ | 0 |Type | Sev.| +--+--+-----+--+--+--+--+--+ || || 11.5 Severity/type Format 45 || \\ || 0R8 - Error is fatal to process || 1R8 - Error is fatal to task || 2R8 - Error is nonfatal || 3R8 - Error is absolutely fatal || (cannot jump to error || label, ERRINTERCEPT, or || ERRTRAP code) \\ 00R8 - Error is system error 04R8 - Error is a user defined error 10R8 - Error is a string, not a code 14R8 - Error is a DG/L runtime error 11.6 Dg/L Error Mode Format 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |Pr| Type | Severity | Code | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ || || || || || || || \\ || || || {unused if using new format} || || || || || || If using the old format: || || || If 377R8 then intercept or || || || trap all errors that || || || match the severity & || || || type specified. || || || || || || If not 377R8 then intercept || || || or trap only errors || || || with that error code. || || \\ || || Handles error if fatality of bit set below: || || 4000R8 - Handle system errors || || 2000R8 - Handle user defined error codes || || 1000R8 - Handle user error texts (ERROR) || || 0400R8 - Handle DG/L runtime error || \\ || Handles error if severity of bit set below || 40000R8 - Handle fatal to process errors || 20000R8 - Handle fatal to task errors || 10000R8 - Handle nonfatal errors \\ If bit set (100000R8P1), print the error message before intercepting or trapping the error, otherwise don't. 11.6 Dg/L Error Mode Format 46 11.7 Dg/L Callable ERROR routines The following routines, all of which are described in Chapter 8 of the AOS and RDOS runtime manuals (revision 0), have been modified. First the old format will be described, then the new format will be given, followed by any differences between the various operating systems and/or hardware configurations we support. Note that error codes are 16 bits on the Eclipse, Nova, and 16 bit version of the MV/FAMILY, and 32 bits on the 32 bit code of the MV/FAMILY. 11.7.1 ERRFATAL Old format: ERRFATAL( ) New format: ERRFATAL( [,] ) For 16 bit processes, if the old format is used, then the routine expects the upper 4 bits of the to contain type and severity information. For 32 bit processes, it expects the error code to always be 32 bits long, and assumes the error code is a system error, unless the new format is used. In any case, the severity field is ignored, and is set to Fatal to Process. 11.7.2 ERRINTERCEPT Old format: ERRINTERCEPT[ (, , [,