The COBOL-IT Region Interface
Overview
For the purposes of this documentation, there are 4 sample programs, and a compile script which are designed to highlight key information about the COBOL Region Interface.
The upper limit on the number of regions that can be processed concurrently by CICS is 100 concurrent regions.
When implementing the COBOL-IT Region Interface, programs must be compiled with the -fthread-safe
compiler flag. Compiling with -fthread-safe
provides region isolation, which is implemented in the same way as thread isolation.
The sample programs are:
Sample Program | Description |
---|---|
comp.sh | The compile script |
testregion.c | The main program |
proga.cob | COBOL program CALL’ed by testregion.c |
progb.cob | COBOL program CALL’ed by proga. |
progfail.cob |
The compile script used, and the sample programs are all included at the end of this chapter.
The compile script
comp.sh
cobc -fthread-safe -m proga.cob
cobc -fthread-safe -m progb.cob
cobc -fthread-safe -m progfail.cob
cobc -x testregion.c
Please note that all of the programs used in the demo are compiled with the -fthread-safe
compiler flag. It is a requirement that all
programs that are involved with regions MUST be compiled the the -fthread-safe
compiler option. For more information on the -fthread-safe
compiler flag, please reference Guidelines for thread-safe programs.
To enable debugging of the "C" code, the compiler flags -G-save-temps
should be added to each of the compile commands in comp.sh.
After compiling the programs, run the testregion executable:
>testregion
Testregion calls a COBOL program called proga
, which calls a subprogram progb
.
The demo shows:
- How to initialize a region, and call a program in that region
- How to cancel a program
- How to use
cob_set_exit_rtd_proc
withsetjmp
/longjmp
The REGION API
All API functions get as a parameter the runtime data from region 0 (the main program region). The runtime data from region 0 is retrieved with a call to cob_get_rtd( )
at program startup.
Note
"rtd" is an abbreviation of "runtime data".
The API functions:
- unsigned int cob_enterprise_get_current_region (cit_runtime_t * r0rtd);
Returns the current region number.
Input: | |
---|---|
cit_runtime_t * r0rtd |
Region 0 (main region) rtd |
- cit_runtime_t * cob_enterprise_set_current_region (cit_runtime_t * r0rtd, unsigned int region);
Returns an rtd of the region number 'region'. The region is initialized if needed.
Input: | |
---|---|
cit_runtime_t * r0rtd |
Region 0 (main region) rtd |
unsigned int region |
Requested region, number between 0 and 15 |
- void cob_enterprise_cancel_region(COB_RTD, unsigned int region, int full_cancel) ;
Cancels all programs started in a region.
Input: | |
---|---|
cit_runtime_t * r0rtd |
Region 0 (main region ) rtd |
unsigned int region |
Region number to cancel between 0 and 15 |
int full_cancel |
If not 0, the programs are unloaded from memory and memory allocated is freed. |
Examples for performing Logical/Full Cancels in Region 1:
cob_enterprise_cancel_region(rtd, 1,0) | The last parameter must be set to 0 to perform a “Logical Cancel”. |
cob_enterprise_cancel_region(rtd, 1,1) | The last parameter must be set to 1 to perform a “Full Cancel”. |
How to call a program (and all sub programs) in a region
When a region is set to be the current active region, it returns an rtd that must be used as the first parameter for all calls to the runtime library.
To call a program in a region :
-
Set the current active region
-
Use the returned rtd to resolve and call the program
For example:
union {
int (*func)();
void *func_void;
} unifunc;
cit_runtime_t *
rtd_region; rtd_region = cob_enterprise_set_current_region(R0_rtd, region);
unifunc.func_void = cob_resolve (rtd_region, "proga");
if ( unifunc.func_void == NULL ) {
cob_call_error (rtd_region);
}
unifunc.func (NULL,NULL,NULL);
Warning
As a general rule, you should never call a runtime function giving as a first parameter an rtd that does not reference runtime data of the current active region.
The sole exception to this rule would be a call to cob_enterprise_cancel_region.
SetJump/LongJump
In the Region 0 the C program may call cob_set_exit_rtd_proc
to set up a C function that will be called if for any reason the runtime aborts. Note that this may also be called if the COBOL program executes a STOP RUN
.
Used with setjmp
/longjmp
this provides a way to recover from an error. Spelling query
The sample program below shows how to recover from an error which is caused by CALL
'ing a subprogram that does not exist:
- void cob_set_exit_rtd_proc (cit_runtime_t * r0rtd, cob_rtd_exit_proc cob_exit_proc)
Input: | |
---|---|
cit_runtime_t * r0rtd | Region 0 (main region) rtd |
cob_rtd_exit_proc | Followed by the pointer to the exit proc |
cob_exit_proc | A pointer to a C function getting as its first parameter the rtd of the current region and as its second parameter |
The Sample Programs
comp.sh
cobc -fthread-safe -m proga.cob
cobc -fthread-safe -m progb.cob
cobc -fthread-safe -m progfail.cob
cobc -fthread-safe -x testregion.c
testregion.c
#include <stdio.h>
#include <assert.h>
#include "libcob.h"
jmp_buf jump_buffer;
void cob_exit_proc (COB_RTD, int status)
{
/* terminate the current region */
cob_terminate_exec(rtd );
/* then go back to call*/
longjmp(jump_buffer, 1);
}
void call_prog (COB_RTD, int region, char *prog_name, char * mess) {
union {
int (*func)();
void *func_void;
} unifunc;
cit_runtime_t * rtd_region;
rtd_region = cob_enterprise_set_current_region(rtd, region);
unifunc.func_void = cob_resolve (rtd_region, prog_name);
if ( unifunc.func_void == NULL ) {
cob_call_error (rtd_region);
}
printf("\nregion %s\n", mess);
unifunc.func (NULL,NULL,NULL);
}
int main (int argc, char **argv)
{
COB_RTD = cob_get_rtd();
cit_runtime_t * rtd_region1;
cit_runtime_t * rtd_region2;
cob_init (rtd, 0, NULL);
/* set up termanate Proc in Region 0*/
cob_set_exit_rtd_proc(rtd,cob_exit_proc);
/* test Long jump*/
if (setjmp(jump_buffer) == 0) {
call_prog(rtd, 0, "proga", "main");
call_prog(rtd, 0, "proga", "main");
call_prog(rtd, 1, "proga", "r1");
call_prog(rtd, 1, "proga", "r1");
call_prog(rtd, 2, "proga", "r2");
printf("\n cancel region 1\n");
cob_enterprise_cancel_region(rtd, 1, 0);
call_prog(rtd, 0, "proga", "main");
call_prog(rtd, 1, "proga", "r1");
call_prog(rtd, 2, "proga", "r2");
cob_enterprise_cancel_region(rtd, 2, 0);
call_prog(rtd, 2, "proga", "r2");
call_prog(rtd, 2, "progfail", "r1");
printf("We should never display this message");
} else {
printf("After long jump");
call_prog(rtd, 1, "proga", "r1");
}
}
proga.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. proga.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
WORKING-STORAGE SECTION.
01 fa PIC X(30) VALUE "INITITAL VALUE".
PROCEDURE DIVISION.
DISPLAY "PROGRAM A " fa .
MOVE "New data" TO fa.
CALL "progb" .
CALL "progb" .
DISPLAY "PROGRAM A CANCEL ProgB" .
CANCEL "progb".
CALL "progb" .
progb.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. progb.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
WORKING-STORAGE SECTION.
01 fa PIC X(30) VALUE "INITITAL VALUE".
PROCEDURE DIVISION.
DISPLAY "PROGRAM B " fa .
MOVE "New data" TO fa.
progfail.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. progfail.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
WORKING-STORAGE SECTION.
01 fa PIC X(30) VALUE "INITITAL VALUE".
PROCEDURE DIVISION.
DISPLAY "PROGRAM Fail " fa .
MOVE "New data" TO fa.
CALL "FAIL" .