HP OpenVMS Systems Documentation |
OpenVMS Programming Concepts Manual
2.8.4.6 Per-Kernel-Thread Data Cells
Several pages in P1 space contain process state in the form of data
cells. A number of these cells must have a per-kernel-thread
equivalent. These data cells do not all reside on pages with the same
protection. Because of this, the per-kernel-thread area reserves two
pages for these cells. Each page has a different page protection; one
page protection is user read, user write (URUW); the other is user
read, executive write (UREW).
Process creation results in a PCB/KTB, a PHD/FRED, and a set of stacks. All processes have a single kernel thread, the initial thread.
A multithreaded process always begins as a single threaded process. A
multithreaded process contains a PCB/KTB pair and a PHD/FRED pair for
the initial thread; for its other threads, it contains additional KTBs,
additional FREDs, and additional sets of stacks. When the multithreaded
application exits, the process returns to its single threaded state,
and all additional KTBs, FREDs, and stacks are deleted.
The SYS$SETPRI system service and the SET PROCESS/PRIORITY DCL command both take a process identification value (PID) as an input and therefore affect only a single kernel thread at a time. If you want to change the base priorities of all kernel threads in a process, you must either make a separate call to SYS$SETPRI or invoke the SET PROCESS/PRIORITY command for each thread. In OpenVMS Alpha Version 7.2, a new value for the 'policy' parameter to the SYS$SETPRI system service has been added. If JPI$K_ALL_THREADS is specified, the call to SYS$SETPRI changes the base priorities of all kernel threads in the target process. The same support is provided by the ALL_THREADS qualifier to the SET PROCESS/PRIORITY DCL command.
Chapter 3
|
Example 3-1 Performing an Iterative Calculation with a Spawned Subprocess |
---|
PROGRAM CALC ! Status variable and system routines INTEGER*4 STATUS, 2 SYS$CRELNM, 2 LIB$GET_EF, 2 LIB$SPAWN ! Define itmlst structure STRUCTURE /ITMLST/ UNION MAP INTEGER*2 BUFLEN INTEGER*2 CODE INTEGER*4 BUFADR INTEGER*4 RETLENADR END MAP MAP INTEGER*4 END_LIST END MAP END UNION END STRUCTURE ! Declare itmlst RECORD /ITMLST/ LNMLIST(2) ! Number to pass to REPEAT.FOR CHARACTER*3 REPETITIONS_STR INTEGER REPETITIONS ! Symbols for LIB$SPAWN and SYS$CRELNM ! Include FORSYSDEF symbol definitions: INCLUDE '($LNMDEF)' EXTERNAL CLI$M_NOLOGNAM, 2 CLI$M_NOCLISYM, 2 CLI$M_NOKEYPAD, 2 CLI$M_NOWAIT, 2 LNM$_STRING . . ! Set REPETITIONS_STR . ! Set up and create logical name REP_NUMBER in job table LNMLIST(1).BUFLEN = 3 LNMLIST(1).CODE = %LOC (LNM$_STRING) LNMLIST(1).BUFADR = %LOC(REPETITIONS_STR) LNMLIST(1).RETLENADR = 0 LNMLIST(2).END_LIST = 0 STATUS = SYS$CRELNM (, 2 'LNM$JOB', ! Logical name table 2 'REP_NUMBER',, ! Logical name 2 LNMLIST) ! List specifying ! equivalence string IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Execute REPEAT.FOR in a subprocess MASK = %LOC (CLI$M_NOLOGNAM) .OR. 2 %LOC (CLI$M_NOCLISYM) .OR. 2 %LOC (CLI$M_NOKEYPAD) .OR. 2 %LOC (CLI$M_NOWAIT) STATUS = LIB$GET_EF (FLAG) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = LIB$SPAWN ('RUN REPEAT',,,MASK,,,,FLAG) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) . . . |
REPEAT.FOR
PROGRAM REPEAT ! Repeats a calculation REP_NUMBER of times, ! where REP_NUMBER is a logical name ! Status variables and system routines INTEGER STATUS, 2 SYS$TRNLNM, 2 SYS$DELLNM ! Number of times to repeat INTEGER*4 REITERATE, 2 REPEAT_STR_LEN CHARACTER*3 REPEAT_STR ! Item list for SYS$TRNLNM ! Define itmlst structure STRUCTURE /ITMLST/ UNION MAP INTEGER*2 BUFLEN INTEGER*2 CODE INTEGER*4 BUFADR INTEGER*4 RETLENADR END MAP MAP INTEGER*4 END_LIST END MAP END UNION END STRUCTURE ! Declare itmlst RECORD /ITMLST/ LNMLIST (2) ! Define item code EXTERNAL LNM$_STRING ! Set up and translate the logical name REP_NUMBER LNMLIST(1).BUFLEN = 3 LNMLIST(1).CODE = LNM$_STRING LNMLIST(1).BUFADR = %LOC(REPEAT_STR) LNMLIST(1).RETLENADR = %LOC(REPEAT_STR_LEN) LNMLIST(2).END_LIST = 0 STATUS = SYS$TRNLNM (, 2 'LNM$JOB', ! Logical name table 2 'REP_NUMBER',, ! Logical name 2 LNMLIST) ! List requesting ! equivalence string IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Convert equivalence string to integer ! BN causes spaces to be ignored READ (UNIT = REPEAT_STR (1:REPEAT_STR_LEN), 2 FMT = '(BN,I3)') REITERATE ! Calculations DO I = 1, REITERATE . . . END DO ! Delete logical name STATUS = SYS$DELLNM ('LNM$JOB', ! Logical name table 2 'REP_NUMBER',) ! Logical name IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) END |
The symbols you create and access for process communication are command
language interpreter (CLI) symbols. These symbols are stored in symbol
tables maintained for use within the context of DCL, the default
command language interpreter. They can store up to 255 bytes of
information. The use of these symbols is limited to processes using
DCL. If the process is not using DCL, an error status is returned by
the symbol routines.
3.1.3.1 Local and Global Symbols
The two kinds of CLI symbols and their definitions are as follows:
If you need to pass information from one program to another within a process, you can assign data to a global symbol when you create the symbol. Then, other programs can access the contents of the global symbol. You should use global symbols so the value within the symbol can be accessed by other programs.
To use DCL global symbols, follow this procedure:
Use the common area to store data from one image to the next. Such data
is unlikely to be corrupted between the time one image deposits it in a
common area and another image reads it from the area. The common area
can store 252 bytes of data. The LIB$PUT_COMMON routine writes
information to this common area; the LIB$GET_COMMON routine reads
information from this common area.
3.1.4.1 Creating the Process Common Area
The common area for your process is automatically created for you; no
special declaration is necessary. To pass more than 255 bytes of data,
put the data into a file instead of in the common area and use the
common area to pass the specification.
3.1.4.2 Common I/O Routines
The LIB$PUT_COMMON routine allows a program to copy a string into the process's common storage area. This area remains defined during multiple image activations. LIB$GET_COMMON allows a program to copy a string from the common area into a destination string. The programs reading and writing the data in the common area must agree upon its amount and format. The maximum length of the destination string is defined as follows:
[min(256, the length of the data in the common storage area) - 4] |
This maximum length is normally 252.
In BASIC and Fortran, you can use these routines to allow a USEROPEN routine to pass information back to the routine that called it. A USEROPEN routine cannot write arguments. However, it can call LIB$PUT_COMMON to put information into the common area. The calling program can then use LIB$GET_COMMON to retrieve it.
You can also use these routines to pass information between images run
successively, such as chained images run by LIB$RUN_PROGRAM.
3.1.4.3 Modifying or Deleting Data in the Common Block
You cannot modify or delete data in the process common area unless you
invoke LIB$PUT_COMMON. Therefore, you can execute any number of images
between one image and another, provided that you have not invoked
LIB$PUT_COMMON. Each subsequent image reads the correct data. Invoking
LIB$GET_COMMON to read the common block does not modify the data.
3.1.4.4 Specifying Other Types of Data
Although the descriptions of the LIB$PUT_COMMON and LIB$GET_COMMON routines in the OpenVMS RTL Library (LIB$) Manual specify a character string for the argument containing the data written to or read from the common area, you can specify other types of data. However, you must pass both noncharacter and character data by descriptor.
The following program segment reads statistics from the terminal and enters them into a binary file. After all of the statistics are entered into the file, the program places the name of the file into the per-process common area and exits.
. . . ! Enter statistics . . . ! Put the name of the stats file into common STATUS = LIB$PUT_COMMON (FILE_NAME (1:LEN)) . . . |
The following program segment reads the file name from the per-process common block and compiles a report using the statistics from that file.
. . . ! Read the name of the stats file from common STATUS = LIB$GET_COMMON (FILE_NAME, 2 LEN) ! Compile the report . . . |
Communication between processes, or interprocess communication, can be performed in the following ways:
Each approach offers different possibilities in terms of the speed at which it communicates information and the amount of information it can communicate. For example, shared files offer the possibility of sharing an unlimited amount of information; however, this approach is the slowest because the disk must be accessed to share information.
Like shared files, global sections offer the possibility of sharing large amounts of information. Because sharing information through global sections requires only memory access, it is the fastest communication method.
Logical names and mailboxes can communicate moderate amounts of information. Because each method operates through a relatively complex system service, each is faster than files, but slower than the other communication methods.
The lock management services and common event flag cluster methods can communicate relatively small amounts of information. With the exception of global sections, they are the fastest of the interprocess communication methods.
Common event flags: Processes executing within the same group can use common event flags to signal the occurrence or completion of particular activities. For details about event flags, and an example of how cooperating processes in the same group use a common event flag, see Chapter 6.
Logical name tables: Processes executing in the same job can use the job logical name table to provide member processes with equivalence names for logical names. Processes executing in the same group can use the group logical name table. A process must have the GRPNAM or SYSPRV privilege to place names in the group logical name table. All processes in the system can use the system logical name table. A process must have the SYSNAM or SYSPRV privilege to place names in the system logical name table. Processes can also create and use user-defined logical name tables. For details about logical names and logical name tables, see Chapter 32.
Mailboxes: You can use mailboxes as virtual input/output devices to pass information, messages, or data among processes. For additional information on how to create and use mailboxes, see Section 3.2.1. Mailboxes may also be used to provide a creating process with a way to determine when and under what conditions a created subprocess was deleted. For an example of a termination mailbox, see Section 4.9.4.2.
Global sections: Global sections can be either disk files or page-file sections that contain shareable code or data. Through the use of memory management services, these files can be mapped to the virtual address space of more than one process. In the case of a data file on disk, cooperating processes can synchronize reading and writing the data in physical memory; as data is updated, system paging results in the updated data being written directly back into the disk file. Global page-file sections are useful for temporary storage of common data; they are not mapped to a disk file. Instead, they page only to the system default page file. Global sections are described in more detail in Chapter 13 and Chapter 12.
Lock management system services: Processes can use the lock management system services to control access to resources (any entity on the system that the process can read, write, or execute). In addition to controlling access, the lock management services provide a mechanism for passing information among processes that have access to a resource (lock value blocks). Blocking ASTs can be used to notify a process that other processes are waiting for a resource. Using lock value blocks is a practical technique for communicating in cluster environments. With lock value blocks, communication between two processes from node to node in a distributed environment is an effective way of implementing cluster communication. For more information about the lock management system services, see Chapter 7.
While common event flags and lock management services establish
communication, they are most useful for synchronizing events and are
discussed in Chapter 6. Global sections and shared files are best
used for sharing data and are discussed in Chapter 26.
3.2.1 Mailboxes
A mailbox is a virtual device used for communication among processes.
You must call OpenVMS RMS services, language I/O statements, or I/O
system services to perform actual data transfers.
3.2.1.1 Creating a Mailbox
To create a mailbox, use the SYS$CREMBX system service. SYS$CREMBX creates the mailbox and returns the number of the I/O channel assigned to the mailbox.
The format for the SYS$CREMBX system service is as follows:
SYS$CREMBX ([prmflg] ,chan ,[maxmsg] ,[bufquo] ,[promsk] ,[acmode]
,[lognam]
,[flags] ,[nullarg])
When you invoke SYS$CREMBX, you usually specify the following two arguments:
The SYS$CREMBX system service also allows you to specify the message size, buffer size, mailbox protection code, and access mode of the mailbox; however, the default values for these arguments are usually sufficient. For more information on SYS$CREMBX, refer to the OpenVMS System Services Reference Manual.
Previous | Next | Contents | Index |