Virtual Aether Implementation for RSX-11M Joseph Sventek Computer Science & Mathematics Department Lawrence Berkeley Laboratory Berkeley, CA 94720 The code described in this document is an implementation of the "virtual aether" inter-process communication mechanism, the specifications of which are given in "Virtual Aethers - an Inter-process Communication Mechanism for Distributed Processing", submitted to the Eighth International Conference on Operating System Principles, December 1981. Copies of that paper may be obtained from the author. Introduction Virtual aethers are named objects supplied by the operating system into which messages may be deposited and from which messages may be retrieved by processes connect to the aether. The implementation for RSX-11M consists of a loadable I/O-driver. The major portion of the driver is written in the C language, to aid porting of the mechanism to a wide variety of operating system. A macro-11 portion is also provided which interprets the I/O request packets and places the required information into global variables for manipulation by the C routines, as well as terminating the I/O requests when completed. Messages sent to an aether have finite lifetimes, determined by the sender, after which they are purged from the system. To implement this self-cleansing action, the driver always has a timer request outstanding in the executive. Before the driver may be unloaded, this timer must be de-activated. For this reason, an utility (UNX - extended unload) is provided; UNX causes the driver to stop its timer, and then unloads the driver from memory. When a message is sent to an aether, each process for which the message is destined receives an AST at the address passes in p5 in the create or access qio. The address of the "normal" or "interrupt" AST address is passed as the single parameter to the AST routine. The routine vaast.mac is provided, which saves r0-r5, calls the "real" AST routine, restores the registers, pops the parameter from the stack and dismisses the AST. This scenario enables one to use high level routines for AST routines without clobbering the registers for the mainline code. The C compiler used is David Conroy's compiler as distributed on the Fall '79 RSX SIG Symposium Tape in UIC's [310,113], [310,114] and [310,116]. The 'as' source for the three library routines used by the driver are included, as are the . obj files for all modules. (The three routines are strcmp.s, strcpy.s and csav.s). Also, the macro modules call csav when it is necessary to save registers. ****** CAUTION ****** If you try to use the DECUS Structured Languages C compiler to compile aether.c, problems will result, since the saving and restoring of registers is done differently in the two compilers, and the mapping of the underscore character (_) to legal RSX global name characters differs. For those of you who use the Mark Williams compiler, you should be able to use that compiler at will. In any case, the file aether.s could benefit from an application of the 'as' optimizer provided with that compiler. The following will describe each function which may be performed on the aethers. Included will be the function code to use in the qio, the layout of p1-p6 in the I/O packet, and expected returns in the I/O status block. The status block is used as a two word -1- Introduction integer, not as a pair of bytes and an integer. Interpretation of the status returns from the driver by calling programs should be aware of this fact. IMPORTANT NOTICE When accessing more than one aether from a single task, separate luns must be used for each access. Failure to do this may result in severe problems in your user task. -2- Creating an aether This function causes an aether to be created with the supplied name and access key (password). If the aether already exists, it can also perform an access function, if so directed. Function code: IO.CRE "12000 p1: address of byte buffer holding the aether name in ASCII characters, terminated with a 0-byte. Only the first 15 characters are used. p2: address of the byte buffer holding the access key (password) in ASCII characters, terminated with a 0-byte. Only the first 15 characters are used. p3: address of the interrupt service routine to be called when a normal message destined for this process is received. p4: address of the interrupt service routine to be called when an interrupt message destined for this process is received. p5: address of the AST routine to call initially for all messages destined for this process. It will usually be the address of "VAAST" (see discussion in the introduction). p6: if non-zero, perform an access function if the aether already exists. iosb(1) = ERR(-3) / CREATED(1) / ACCESSED(2) iosb(2) = descriptor for use in send, receive and deaccess functions -3- Accessing an aether This function causes the current process to access an existing aether. Function code: IO.ACW "7000 p1: address of byte buffer holding the aether name in ASCII characters, terminated with a 0-byte. Only the first 15 characters are used. p2: address of the byte buffer holding the access key (password) in ASCII characters, terminated with a 0-byte. Only the first 15 characters are used. p3: address of the interrupt service routine to be called when a normal message destined for this process is received. p4: address of the interrupt service routine to be called when an interrupt message destined for this process is received. p5: address of the AST routine to call initially for all messages destined for this process. It will usually be the address of "VAAST" (see discussion in the introduction). iosb(1) = ERR(-3) / ACCESSED(2) iosb(2) = descriptor for use in send, receive and deaccess functions -4- Deaccessing an aether This function causes the current process to deaccess the aether. This function is also implicitly performed for the process when it exits from the system. Function code: IO.DAC "10000 p1: descriptor returned by the create or access function in iosb(2) iosb(1) = OK(0) -5- Receive message from aether This function causes the oldest message queued for the requesting process to be dequeued. If no message exists, an error is returned. If the buffer is too small for the message, only the first size bytes of the message is returned and the rest is lost. Function code: IO.RVB "10400 p1: descriptor returned by the create or access function in iosb(2) p2: address of buffer into which the message is copied p3: size of the buffer specified in p2, in bytes. iosb(1) = ERR(-3) / BUFFER_OVERFLOW(-1) / # of bytes copied into buffer -6- Sending a normal message This function permits the requesting process to send an normal message to an aether. All connected processes except the requestor will receive an normal interrupt indicating that a message has been queued. If there is no room to buffer the message, or AST control blocks could not be allocated from pool, an error is returned. Function code: IO.WVB "11000 p1: descriptor returned by the create or access function in iosb(2) p2: address of buffer into which the message is copied p3: size of the message to send, in bytes. p4: lifetime of the message, in seconds. After this period of time has elapsed, the message will be purged from the buffers. iosb(1) = OK(0) / ERR(-3) -7- Send an interrupt message This function causes all connected processes except the requestor to receive an AST at the interrupt AST entry point. If the AST control blocks could not be allocated from pool, an error is returned Function code: IO.WVB!2 "11002 p1: descriptor returned by the create or access function in iosb(2) iosb(1) = OK(0) / ERR(-3) -8- Send a message to the creator of an aether This function permits a process which is not connected to an aether to send ONE message to the creator of an aether. This permits processes to rendezvous, in order to establish a connection protocol, or for other various reasons. If the creator of the aether has already deaccessed the aether, or if the message could not be buffered, an error is returned. This message, if queued, will cause the creator to receive an normal interrupt, and the creator will receive the message via the receive function. Function code: IO.WVB!1 "11001 p1: address of byte buffer holding the aether name in ASCII characters, terminated with a 0-byte. Only the first 15 characters are used. p2: address of buffer into which the message is copied p3: size of the message to send, in bytes. iosb(1) = OK(0) / ERR(-3) -9-