You are on page 1of 13

http://publib.boulder.ibm.

com/infocenter/ratde
vz/v7r5/index.jsp?
topic=/com.ibm.ent.cbl.zos.doc/topics/PGan
dLR/tasks/tpchk04.htm
Examples: static and dynamic CALL statements

This example shows how you can code static and dynamic calls.

The example has three parts:

• Code that uses a static call to call a subprogram


• Code that uses a dynamic call to call the same subprogram
• The subprogram that is called by the two types of calls

The following example shows how you would code static calls:

PROCESS NODYNAM NODLL


IDENTIFICATION DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 RECORD-2 PIC X. (6)
01 RECORD-1. (2)
05 PAY PICTURE S9(5)V99.
05 HOURLY-RATE PICTURE S9V99.
05 HOURS PICTURE S99V9.
. . .
PROCEDURE DIVISION.
CALL "SUBPROG" USING RECORD-1. (1)
CALL "PAYMASTR" USING RECORD-1 RECORD-2. (5)
STOP RUN.

The following example shows how you would code dynamic calls:
DATA DIVISION.
WORKING-STORAGE SECTION.
77 PGM-NAME PICTURE X(8).
01 RECORD-2 PIC x. (6)
01 RECORD-1. (2)
05 PAY PICTURE S9(5)V99.
05 HOURLY-RATE PICTURE S9V99.
05 HOURS PICTURE S99V9.
. . .
PROCEDURE DIVISION.
. . .
MOVE "SUBPROG" TO PGM-NAME.
CALL PGM-NAME USING RECORD-1. (1)
CANCEL PGM-NAME.
MOVE "PAYMASTR" TO PGM-NAME. (4)
CALL PGM-NAME USING RECORD-1 RECORD-2. (5)
STOP RUN.

The following example shows a called subprogram that is called by each of the two
preceding calling programs:

IDENTIFICATION DIVISION.
PROGRAM-ID. SUBPROG.
DATA DIVISION.
LINKAGE SECTION.
01 PAYREC. (2)
10 PAY PICTURE S9(5)V99.
10 HOURLY-RATE PICTURE S9V99.
10 HOURS PICTURE S99V9.
77 PAY-CODE PICTURE 9. (6)
PROCEDURE DIVISION USING PAYREC. (1)
. . .
EXIT PROGRAM. (3)
ENTRY "PAYMASTR" USING PAYREC PAY-CODE. (5)
. . .
GOBACK. (7)

(1)
Processing begins in the calling program. When the first CALL statement is
executed, control is transferred to the first statement of the PROCEDURE
DIVISION in SUBPROG, which is the called program.

In each of the CALL statements, the operand of the first USING option is
identified as RECORD-1.

(2)
When SUBPROG receives control, the values within RECORD-1 are made
available to SUBPROG; however, in SUBPROG they are referred to as PAYREC.

The PICTURE character-strings within PAYREC and PAY-CODE contain the same
number of characters as RECORD-1 and RECORD-2, although the descriptions
are not identical.

(3)
When processing within SUBPROG reaches the EXIT PROGRAM statement,
control is returned to the calling program. Processing continues in that
program until the second CALL statement is issued.
(4)
In the example of a dynamically called program, because the second CALL
statement refers to another entry point within SUBPROG, a CANCEL statement
is issued before the second CALL statement.
(5)
With the second CALL statement in the calling program, control is again
transferred to SUBPROG, but this time processing begins at the statement
following the ENTRY statement in SUBPROG.
(6)
The values within RECORD-1 are again made available to PAYREC. In addition,
the value in RECORD-2 is now made available to SUBPROG through the
corresponding USING operand, PAY-CODE.

When control is transferred the second time from the statically linked
program, SUBPROG is made available in its last-used state (that is, if any
values in SUBPROG storage were changed during the first execution, those
changed values are still in effect). When control is transferred from the
dynamically linked program, however, SUBPROG is made available in its initial
state, because of the CANCEL statement that has been executed.

(7)
When processing reaches the GOBACK statement, control is returned to the
calling program at the statement immediately after the second CALL
statement.

In any given execution of the called program and either of the two calling programs,
if the values within RECORD-1 are changed between the time of the first CALL and the
second, the values passed at the time of the second CALL statement will be the
changed, not the original, values. If you want to use the original values, you must
save them.

Making both static and dynamic calls


You can use both static and dynamic CALL statements in the same program if you
compile the program with the NODYNAM compiler option.

In this case, with the CALL literal statement, the called subprogram will be link-
edited with the main program into one load module. The CALL identifier statement
results in the dynamic invocation of a separate load module.

When a dynamic CALL statement and a static CALL statement to the same
subprogram are issued within one program, a second copy of the subprogram is
loaded into storage. Because this arrangement does not guarantee that the
subprogram will be left in its last-used state, results can be unpredictable.

DYNAM
Use DYNAM to cause nonnested, separately compiled programs invoked through the
CALL literal statement to be loaded (for CALL) and deleted (for CANCEL) dynamically
at run time. (CALL identifier statements always result in a runtime load of the target
program and are not affected by this option.)

DYNAM option syntax

.-NODYNAM-.
>>-+---------+-------------------------------------------------><

'-DYNAM---'

Default is: NODYNAM

Abbreviations are: DYN|NODYN

Restriction: The DYNAM compiler option must not be used in the following cases:

• COBOL programs that are processed by the CICS translator or the CICS
compiler option
• COBOL programs that have EXEC SQL statements and are run under CICS or
DB2 call attach facility (CAF)

If your COBOL program calls programs that have been linked as dynamic link
libraries (DLLs), you must not use the DYNAM option. You must instead compile the
program with the NODYNAM and DLL options.

When to use a dynamic call with subprograms


Your decision to use dynamic calls with subprograms depends on factors such as
location of the load module, frequency of calls to the subprograms, size of the
subprograms, ease of maintenance, the need to call subprograms in their unused
state, the need for AMODE switching, and when the program-names are known.

The load module that you want to dynamically call must be in an MVS load library
rather than in the hierarchical file system.

If subprograms are called in only a few conditions, you can use dynamic calls to
bring in the subprograms only when needed.

If the subprograms are very large or there are many of them, using static calls might
require too much main storage. Less total storage might be required to call and
cancel one, then call and cancel another, than to statically call both.
If you are concerned about ease of maintenance, dynamic calls can help.
Applications do not have to be link-edited again when dynamically called
subprograms are changed.

When you cannot use the INITIAL attribute to ensure that a subprogram is placed in
its unused state each time that it is called, you can set the unused state by using a
combination of dynamic CALL and CANCEL statements. When you cancel a
subprogram that was first called by a COBOL program, the next call causes the
subprogram to be reinitialized to its unused state.

Using the CANCEL statement to explicitly cancel a subprogram that was dynamically
loaded and branched to by a non-COBOL program does not result in any action being
taken to release the subprogram's storage or to delete the subprogram.

Suppose you have an OS/VS COBOL or other AMODE 24 program in the same run unit
with Enterprise COBOL programs that you want to run in 31-bit addressing mode.
COBOL dynamic call processing includes AMODE switching for AMODE 24 programs that
call AMODE 31 programs, and vice versa. To have this implicit AMODE switching done,
you must use the Language Environment runtime option ALL31(OFF). AMODE
switching is not performed when ALL31(ON) is set.

When AMODE switching is performed, control is passed from the caller to a Language
Environment library routine. After the switching is performed, control passes to the
called program; the save area for the library routine will be positioned between the
save area for the caller program and the save area for the called program.

If you do not know the program-name to be called until run time, use the format
CALL identifier, where identifier is a data item that will contain the name of the called
program at run time. For example, you could use CALL identifier when the program
to be called varies depending on conditional processing in your program. CALL
identifier is always dynamic, even if you use the NODYNAM compiler option.

Performance considerations of static and


dynamic calls
Because a statically called program is link-edited into the same load module as the
calling program, a static call is faster than a dynamic call. A static call is the
preferred method if your application does not require the services of the dynamic
call.
Statically called programs cannot be deleted using CANCEL, so static calls might take
more main storage. If storage is a concern, think about using dynamic calls. Storage
usage of calls depends on whether:

• The subprogram is called only a few times. Regardless of whether it is called,


a statically called program is loaded into storage; a dynamically called
program is loaded only when it is called.
• You subsequently delete the dynamically called subprogram with a CANCEL
statement.

You cannot delete a statically called program, but you can delete a
dynamically called program. Using a dynamic call and then a CANCEL
statement to delete the dynamically called program after it is no longer
needed in the application (and not after each call to it) might require less
storage than using a static call.

Related concepts

CALL identifier and CALL literal

CALL identifier, where identifier is a data item that contains the name of a nonnested
subprogram at run time, always results in the target subprogram being loaded when
it is called. CALL literal, where literal is the explicit name of a nonnested target
subprogram, can be resolved either statically or dynamically.

With CALL identifier, the name of the DLL must match the name of the target entry
point.

With CALL literal, if the NODYNAM compiler option is in effect, either static or dynamic
linking can be done. If DYNAM is in effect, CALL literal is resolved in the same way as
CALL identifier: the target subprogram is loaded when it is called, and the name of
the DLL must match the name of the target entry point.

These call definitions apply only in the case of a COBOL program calling a nonnested
program. When a COBOL program calls a nested program, the call is resolved by the
compiler without any system intervention.

Limitation: Two or more separately linked executables (.EXE or .DLL files) in an


application must not statically call the same nonnested subprogram.
Static linking and dynamic linking
By using linking, you can have a program call another program that is not contained
in the source code of the calling program. Before or during execution, the object
module of the calling program is linked with the object module of the called program.

Static linking occurs when a calling program is linked to a called program in a single
executable module. When the program is loaded, the operating system places into
memory a single file that contains the executable code and data.

The result of statically linking programs is an .EXE file or dynamic link library (DLL)
subprogram that contains the executable code for multiple programs. This file
includes both the calling program and the called program.

The primary advantage of static linking is that you can create self-contained,
independent programs. In other words, the executable program consists of one part
(the .EXE file) that you need to keep track of. Static linking has these disadvantages:

• Linked external programs are built into the executable files, making these
files larger.
• You cannot change the behavior of executable files without relinking them.
• External called programs cannot be shared, requiring that duplicate copies of
programs be loaded in memory if more than one calling program needs to
access them.

To overcome these disadvantages, use dynamic linking.

Dynamic linking lets several programs use a single copy of an executable module.
The executable module is separate from the programs that use it. You can build
several subprograms into a DLL. Calling programs can use these subprograms as if
they were part of the executable code of the calling program. You can change the
dynamically linked subprograms without recompiling or relinking the calling program.

DLLs are typically used to provide common functions for a number of programs. For
example, you can use DLLs to implement subprogram packages, subsystems, and
interfaces to other programs, or to create object-oriented class libraries.

You can dynamically link files with the supplied runtime DLLs and with your own
COBOL DLLs.

Transferring control to another program


You can use several different methods to transfer control to another program: static
calls, dynamic calls, calls to nested programs, and calls to dynamic link libraries
(DLLs).

In addition to making calls between Enterprise COBOL programs, you can also make
static and dynamic calls between Enterprise COBOL and programs compiled with
older compilers in all environments including CICS.

When you use OS/VS COBOL with Enterprise COBOL, there are differences in support
between non-CICS and CICS:

In a non-CICS environment
You can make static and dynamic calls between Enterprise COBOL and other
COBOL programs.

Exception: You cannot call VS COBOL II or OS/VS COBOL programs in the


UNIX environment.

In a CICS environment
You cannot call OS/VS COBOL programs in the CICS environment. You must
use EXEC CICS LINK to transfer control between OS/VS COBOL programs and
other COBOL programs.

Calls to nested programs allow you to create applications using structured


programming techniques. You can use nested programs in place of PERFORM
procedures to prevent unintentional modification of data items. Call nested programs
using either the CALL literal or CALL identifier statement.

Calls to dynamic link libraries (DLLs) are an alternative to COBOL dynamic CALL, and
are well suited to object-oriented COBOL applications, UNIX programs, and
applications that interoperate with C/C++.

Under z/OS, linking two load modules together results logically in a single program
with a primary entry point and an alternate entry point, each with its own name.
Each name by which a subprogram is to be dynamically called must be known to the
system. You must specify each such name in linkage-editor or binder control
statements as either a NAME or an ALIAS of the load module that contains the
subprogram.

Making static calls


When you use the CALL literal statement in a program that is compiled using the
NODYNAM and NODLL compiler options, a static call occurs. With these options, all CALL
literal calls are handled as static calls.

With static calls statement, the COBOL program and all called programs are part of
the same load module. When control is transferred, the called program already
resides in storage, and a branch to it takes place. Subsequent executions of the CALL
statement make the called program available in its last-used state unless the called
program has the INITIAL attribute. In that case, the called program and each
program directly or indirectly contained within it are placed into their initial state
each time the called program is called within a run unit.

If you specify alternate entry points, a static CALL statement can use any alternate
entry point to enter the called subprogram.

Making dynamic calls


When you use a CALL literal statement in a program that is compiled using the DYNAM
and the NODLL compiler options, or when you use the CALL identifier statement in a
program that is compiled using the NODLL compiler option, a dynamic call occurs.

In these forms of the CALL statement, the called COBOL subprogram is not link-
edited with the main program. Instead, it is link-edited into a separate load module,
and is loaded at run time only when it is required (that is, when called). The
program-name in the PROGRAM-ID paragraph or ENTRY statement must be identical to
the corresponding load module name or load module alias of the load module that
contains the program.

Each subprogram that you call with a dynamic CALL statement can be part of a
different load module that is a member of either the system link library or a private
library that you supply. In either case it must be in an MVS load library; it cannot
reside in the hierarchical file system. When a dynamic CALL statement calls a
subprogram that is not resident in storage, the subprogram is loaded from secondary
storage into the region or partition that contains the main program, and a branch to
the subprogram is performed.

The first dynamic call to a subprogram within a run unit obtains a fresh copy of the
subprogram. Subsequent calls to the same subprogram (by either the original caller
or any other subprogram within the same run unit) result in a branch to the same
copy of the subprogram in its last-used state, provided the subprogram does not
possess the INITIAL attribute. Therefore, the reinitialization of either of the following
items is your responsibility:

• GO TO statements that have been altered


• Data items

If you call the same COBOL program in different run units, a separate copy of
WORKING-STORAGE is allocated for each run unit.

Restrictions: You cannot make dynamic calls to:

• COBOL DLL programs


• COBOL programs compiled with the PGMNAME(LONGMIXED) option, unless the
program-name is less than or equal to eight characters in length and is all
uppercase
• COBOL programs compiled with the PGMNAME(LONGUPPER) option, unless the
program-name is less than or equal to eight characters in length
• More than one entry point in the same COBOL program (unless an intervening
CANCEL statement was executed)

When to use dynamic linking and static linking

The operating system provides facilities for creating and using dynamically linked
shared libraries. With dynamic linking, external symbols referenced in user code and
defined in a shared library are resolved by the loader at load time. When you compile
a program that uses shared libraries, they are dynamically linked to your program by
default.

The idea behind shared libraries is to have only one copy of commonly used routines
and to maintain this common copy in a unique shared-library segment. These
common routines can significantly reduce the size of executable programs, thereby
saving disk space.

You can reduce the size of your programs by using dynamic linking, but there is
usually a trade-off in performance. The shared library code is not present in the
executable image on disk, but is kept in a separate library file. Shared code is loaded
into memory once in the shared library segment and shared by all processes that
reference it. Dynamically linked libraries therefore reduce the amount of virtual
storage used by your program, provided that several concurrently running
applications (or copies of the same application) use the procedures provided in the
shared library. They also reduce the amount of disk space required for your program
provided that several different applications stored on a given system share a library.
Other advantages of shared libraries are as follows:

• Load time might be reduced because the shared library code might already be
in memory.

• Run-time performance can be enhanced because the operating system is less


likely to page out shared library code that is being used by several applications,
or copies of an application, rather than code that is only being used by a single
application. As a result, fewer page faults occur.

• The routines are not statically bound to the application but are dynamically
bound when the application is loaded. This permits applications to automatically
inherit changes to the shared libraries, without recompiling or rebinding.

Disadvantages of dynamic linking include the following:

• From a performance viewpoint, there is "glue code" that is required in the


executable program to access the shared segment. There is a performance cost
in references to shared library routines of about eight machine cycles per
reference. Programs that use shared libraries are usually slower than those that
use statically-linked libraries.

• A more subtle effect is a reduction in "locality of reference." You may be


interested in only a few of the routines in a library, and these routines may be
scattered widely in the virtual address space of the library. Thus, the total
number of pages you need to touch to access all of your routines is significantly
higher than if these routines were all bound directly into your executable
program. One impact of this situation is that, if you are the only user of these
routines, you experience more page faults to get them all into real memory. In
addition, because more pages are touched, there is a greater likelihood of
causing an instruction translation lookaside buffer (TLB) miss.

• When a program references a limited number of procedures in a library, each


page of the library that contains a referenced procedure must be individually
paged into real memory. If the procedures are small enough that using static
linking might have linked several procedures that are in different library pages
into a single page, then dynamic linking may increase paging thus decreasing
performance.

• Dynamically linked programs are dependent on having a compatible library. If


a library is changed (for example, a new compiler release may change a
library), applications might have to be reworked to be made compatible with the
new version of the library. If a library is removed from the system, programs
using that library will no longer work.
In statically-linked programs, all code is contained in a single executable module.
Library references are more efficient because the library procedures are statically
linked into the program. Static linking increases the file size of your program, and it
may increase the code size in memory if other applications, or other copies of your
application, are running on the system.

The cc command defaults to the shared-library option. To override the default, when
you compile your programs to create statically-linked object files, use the -bnso
option as follows:

cc xxx.c -o xxx.noshr -O -bnso -bI:/lib/syscalls.exp

This option forces the linker to place the library procedures your program references
into the program's object file. The /lib/syscalIs.exp file contains the names of
system routines that must be imported to your program from the system. This file
must be specified for static linking. The routines that it names are imported
automatically by libc.a for dynamic linking, so you do not need to specify this file
during dynamic linking. For further details on these options, see Efficient use of the
ld command and the Id command.

• Determining if nonshared libraries help performance


One method of determining whether your application is sensitive to the shared-
library approach is to recompile your executable program using the nonshared
option.

You might also like