Calling Multitasking Functions from Assembler
Register | Usage |
---|---|
R1 | Address of a list of addresses of the parameters |
R14 | Return address |
R15 | Address of the entry point for the function |
The external symbols and parameter address list DSECTs are defined in the assembler binding files. The application can call CMS functions without using the parameter list DSECTs provided. They are provided only as a convenience, in case the programmer wishes to use symbolic names for the entries in the address list. The names of the DSECT fields are documented only in the binding files themselves. However, the important point is that the order of parameters is defined in the reference documentation for each function. That is all you need to know to build the parameter list.
L R1,address of data area
USING VMTHRYI_PLIST,R1
MVC VMTHRYI_PLIST_RC,=A(RC) Address of return code
MVC VMTHRYI_PLIST_RE,=A(RE) Address of reason code
MVC VMTHRYI_PLIST_TID,=A(TID) Address of Thread ID
L R15,=A(THREADYIELD)
BALR R14,R15 Invoke ThreadYield
RC
, RE
, and TID
all
reside in storage locations whose addresses are constants computed
by the loader at load time (note the use of =A
in
referring to those parameters). If
reentrant code is required, then all parameters and the parameter
list must reside in dynamically-obtained storage. This means that
the parameter list must be built at run time using LA and ST instructions.
For example, if we assume that R1 points to a fragment of dynamically-obtained
storage for the parameter list, and if we assume that a base register
for dynamically-obtained storage for the parameters themselves (for
example, R13) has already been set up, then the following code fragment
produces reentrant code: USING VMTHRYI_PLIST,R1
LA R2,RC
ST R2,VMTHRYI_PLIST_RC
LA R2,RE
ST R2,VMTHRYI_PLIST_RE
LA R2,TID
ST R2,VMTHRYI_PLIST_TID
L R15,=A(THREADYIELD)
BALR R14,R15
If a section of code is shared among threads in a single dispatch class, and if that code contains a point at which control could be lost, then that code must be reentrant. If a section of code is shared among threads in multiple dispatch classes, then that section of code must be multiprocessor-capable.
A simpler way to handle the construction of the parameter address list and the function invocation is to use the CALL macro provided by CMS. It builds the parameter list automatically and generates the BALR instruction. The CALL macro does not support long names, so instead of specifying the routine name, use the register form.
L R15,=A(THREADYIELD)
CALL (15),(RC,RE,TID)
VMTHRYI_PLIST DSECT
VMTHRYI_PLIST_RC DS F
VMTHRYI_PLIST_RE DS F
VMTHRYI_PLIST_THREAD_ID DS F
VMTHRYI_PLIST_LENGTH EQU *-VMTHRYI_PLIST
Determining the largest parameter list DSECT included in a program requires a few more assembler instructions. The length of the largest parameter list DSECT is found in a global macro variable called &DMAX. To use this length:
- Include the assembler binding files at the end of the program.
- Declare the global macro variable &DMAX before the assembler binding files.
- Define the variable with the largest parameter list DSECT length after the assembler binding files. The largest length is the address of &DMAX. A CSECT statement is required between the assembler binding files and the largest length variable.
TESTASM CSECT
.
.
.
GBLA &DMAX
VMASMMT
TESTASM CSECT
MAX_PLIST_LENGTH DC A(&DMAX)
END