gtpc3m0j | Concepts and Structures |
A distinction between application and system programs is helpful. Also, two different program structures called reentrant and serially reusable identify some of the synchronization issues inherent in parallel processing, whether a program is classified as an application program or as a system program.
A functional distinction between application and system programs is:
Reentrant programs become an important ingredient within a system that incorporates a high level of parallel processing. Reentrant programs allow a single copy of a program or routine to be used concurrently by two or more processes.
In this context, there is a significant distinction to be made between the terms program and process because a single reentrant program is designed to handle multiple processes. Recall, from the introduction in this chapter, that a program is characterized as the passive representation of a process. Now it is useful to think of multiple processes as animations of a single program. The reentrant program accommodates multiple processes through switching execution on a single I-stream engine as well as simultaneous execution on multiple I-stream engines. A distinction between a program and a process is not always necessary; for example, the phrase "an application program is delayed" implies a running program in the service of some process.
Reentrant programs conserve main storage space, eliminate some file accesses for fetching additional copies of a program to service additional processes, and permit the same copy of a program to be executed simultaneously in multiple I-stream engines. Be assured, however, that multiprogramming and multiprocessing can be implemented without using reentrant programs by consuming more main storage space, making additional accesses to external storage, and synchronizing processor execution.
The TPF system requires that ISO-C programs be reentrant, which means that the RENT compile-time option must be specified when you compile segments that contain writable static. There is a performance overhead for writable static, however, particularly when calling library functions. Consider designing ISO-C libraries and applications that do not contain writable static data. An application that does not contain writable static data is considered to be naturally reentrant and does not need to be compiled with the RENT option. This avoids the overhead associated with writable static.
Process is an abstraction of several TPF constructs and, in particular, of one called an Entry. An Entry is created to do application processing. In particular, an Entry is used to accept an input message and to produce a response (output) message, where the response can be preceded by updates to the database. The input message comes from an end user (for example, a reservations agent) and anticipates a corresponding response (for example, printing a ticket or a message that displays a flight schedule). Normally, various reentrant programs, called program segments, are run sequentially on behalf of the Entry. The concrete description of an Entry associates the input message with control blocks and related pointers. A more comprehensive description of an Entry is delayed until additional TPF system structure is introduced in TPF System Structural Characteristics. Nevertheless, an overview of the control block structure in support of TPF processes, called Entries, is shown in Figure 12. This is an abstraction of the details and relies upon your assumed previous computing experience.
Figure 12. TPF Process Structure
The notion of reentrancy is combined with the notion of an Entry in the following example: The same copy of a TPF application program can be used to update an airline seat inventory on behalf of many reservations agents; each agent enters messages needed to request seat reservations for different customers. The unique messages from each of several agents and the implied system actions represent several processes (Entries, in this case). The same program can be servicing several Entries on the same I-stream engine through multiprogramming and simultaneously processing on multiple I-stream engines through multiprocessing. Therefore, Entry unique data must be held in private storage areas (which in the TPF system are called the ECB work areas). A reentrant program indirectly references unique input and output data with private I-stream engine registers that point to the data. The values in the registers must be reset for each invocation of the program. This ensures that information used and generated as a result of processing separate Entries remains independent of the shared code invoked to do the processing. This permits the program to be reentered on behalf of additional Entries before the program computes the result of previous Entries.
In the early versions of the TPF system, a primitive form of reentrant programming was practiced. Before multiple I-stream engines, it was not necessary to coordinate the updating of system tables because in a uniprocessor environment, there is only one I-stream engine.
This violation of the reentrant attribute in a multiple I-stream engine environment can be explained by considering that if the sequence of code that updates an entry in a system table is simultaneously executed in more than one I-stream engine without incorporating critical region protection, the entry can be inaccurately modified. Even though the hardware arbitrates simultaneous access to the same storage location by two different I-stream engines, this is not sufficient to ensure that any two I-stream engine executions are far enough separated in time to ensure that the second access to the table entry sees the result of the first I-stream engine's execution. This could result in losing one of the updates.
This problem is mentioned here to shed some insight on the subtleties of evolving the TPF system into a multiprocessing environment.
A sequence of code that is guaranteed to run to completion before being invoked to accept another input is called serially reusable code. In earlier versions of the TPF system, serially reusable code was used within reentrant programs to update shared data. This was reasonable because in a uniprocessing environment, a sequence of code that updates shared data is serially reusable within a single I-stream engine. However, if the code is to remain serially reusable in a multiple I-stream engine environment, then the code can be used by only one I-stream engine at a time. Serially reusable code is a critical region in disguise.
In early versions of the TPF system, the system programs were designed on the assumption that all application programs were serviced by a set of system programs that ran on a single I-stream engine (CPU), required very little processing per request, used no I/O, and ran to completion before servicing another application request. In other words, it was assumed that system programs were serially reusable.
Many application programs are reentrant, but not all. Some refer to a shared area of main storage called the global area. The interval of time in which an Entry modifies the global area is not critical in a uniprocessor environment; the attribute of being serially reusable during modifications to the global area is tacitly assumed. This critical region for applications causes problems in a multiprocessing environment. The use of the global area in a multiprocessing environment affects application program interfaces and is related to some rather complex structures for incorporating references to the global area into the application programs.
A serially reusable sequence of code may, in a uniprocessor environment, build data within a program area that is not private or indirectly referenced. However, this same code occasionally fails in a multiprocessing environment when the code is executed simultaneously on more than one I-stream engine. This is caused by updating values in a shared area that can be corrupted by the conflicting demands of separate processes in a multiple I-stream engine environment. In reality, within a multiple I-stream engine environment, a serially reusable program that is designed to run in a uniprocessor environment is no longer guaranteed to run to completion before being reused.
Several techniques apply to both system and application programs and are used within the TPF system to overcome the assumptions of serial reusability in the past:
This means that the critical regions of existing code must be identified and controlled by the mechanisms that restrict their execution to one I-stream engine at a time.
This means that within an ESA configuration of multiple I-stream engines, the program can only execute in one I-stream engine. The TPF system provides a load balancing mechanism to do this, or the user installation can design its own.
This leads to various forms of interprocessor communication.
The best technique would be a completely new system design and implementation. However, this is an option constrained by the past: preserving application interfaces for loyal customers.