Table of Contents
- Overview
- The mainframe model: quasi-reentrant execution
- How Heirloom reproduces it on the JVM
- What overlaps — and the performance benefit
- Why your shared storage stays safe
- What you can and cannot assume
- Summary
- Related articles
Audience: developers and operations engineers running PL/I applications migrated with Heirloom, especially online/CICS workloads serving many concurrent transactions.
Overview
On the mainframe, a quasi-reentrant PL/I program runs single-threaded under CICS: only one task executes program logic at a time, and each task steps aside whenever it waits on I/O. Your migrated application runs on a modern Java application server with a pool of threads — but it preserves that same single-threaded behavior, so your code keeps working exactly as it did, without race conditions and without you adding any locks.
This article explains how that works, why your shared storage is safe, and how the runtime still gets a real performance benefit by letting database, CICS, and MQ I/O overlap across transactions.
Note: You do not configure any of this and you do not change your code for it. The behavior is automatic and always on. This article is background so you can reason about performance and about what is (and isn't) safe to assume.
The mainframe model: quasi-reentrant execution
A quasi-reentrant program (the PL/I default) relies on a guarantee from CICS: only one task runs program logic at any instant, on a single dispatcher thread (the "QR TCB"). That guarantee is what makes shared storage — the CWA, a global work area, STATIC variables — safe to use without locks: nothing else is running while you touch it.
The other half of the model is just as important: whenever a task issues I/O (a CICS command, an SQL statement, an MQ operation), it yields so that other tasks can run while it waits. The waiting task is not hogging the single execution slot:
one execution slot (program logic) I/O subsystem (DB2 / CICS / MQ)
logic ──────┐ yield on I/O ┌──────────────────────────┐
└───────────────────▶ │ I/O runs here; the logic │
logic ◀─────┐ resume after I/O │ slot is FREE for others │
└────────────────────-└──────────────────────────┘
How Heirloom reproduces it on the JVM
The runtime enforces the same rule with a single, application-wide lock that represents that one execution slot:
- A thread holds the lock while it runs your PL/I logic. Because there is only one lock, only one thread runs program logic at a time — exactly like the single QR TCB.
- A thread releases the lock whenever it performs I/O (CICS, SQL, or MQ), and reacquires it before continuing with program logic afterward.
So your program runs on a pooled Java thread, but it never runs its logic concurrently with another transaction's logic. The mainframe contract is preserved on standard hardware.
What overlaps — and the performance benefit
Releasing the lock during I/O is what makes the model fast. While one transaction waits on a slow database query, another transaction can use the execution slot to run its logic — and start its own I/O, which then overlaps too. The I/O work itself genuinely runs in parallel; only the program logic is serialized.
If the slot were held through I/O: Heirloom (slot released during I/O): T1 [logic][===SQL===][logic] T1 [logic][===SQL===][logic] T2 [logic][===SQL===][logic] T2 [logic][===SQL===][logic] T3 ...transactions queue up, slow T3 [logic][===SQL===][logic] ← finishes far sooner
On I/O-heavy workloads with many concurrent transactions, this typically delivers 2–4× the throughput of a design that serialized I/O as well, plus better use of multi-core servers.
Why your shared storage stays safe
Because only one thread runs program logic at a time, the storage your programs share — a global work area, GETMAIN-with-SHARED storage, STATIC data — is touched by one transaction at a time. That means:
- No torn reads or lost updates from two transactions writing the same shared area simultaneously.
- No need to add synchronization to your migrated PL/I code. The runtime provides the serialization the mainframe gave you.
See How the PL/I Runtime Manages Memory for how these storage areas are represented.
What you can and cannot assume
You can assume:
- Your program logic never runs concurrently with another transaction's logic.
- Shared storage is safe to read and write without locks.
- I/O from different transactions can and will overlap, improving throughput.
You should not assume:
- That your program runs faster by being multithreaded internally — a single program's logic is still single-threaded, just as on the mainframe.
- That long, CPU-bound stretches of logic are free. Because logic runs in one slot, a tight loop or heavy computation that never pauses for I/O will hold up other transactions until it finishes. If a compute-heavy section starves other work, break it up — this is the same consideration you would give a long-running quasi-reentrant program on the mainframe.
- That you should hold external resources (such as your own OS-level locks) across an I/O operation — doing so works against the overlap the runtime is providing.
Summary
- Migrated programs preserve the mainframe's quasi-reentrant model: only one transaction runs program logic at a time, even on a multithreaded application server.
- The runtime does this with a single execution slot that a thread holds during logic and releases during I/O, then reacquires.
- Releasing the slot during I/O lets database/CICS/MQ work overlap across transactions — typically 2–4× throughput on I/O-heavy workloads.
- Shared storage (GWA,
GETMAIN SHARED,STATIC) is safe without locks because only one transaction touches it at a time. - Long CPU-bound logic still serializes everyone — keep heavy compute sections from starving other transactions.
Related articles
- How Transactions Are Managed (ETP + PL/I Runtime) — the transaction lifecycle and resource scopes.
- How the PL/I Runtime Manages Memory — why shared storage is safe under this model.
- How SQL Executes in a Migrated PL/I Application — SQL statements and their I/O points.
- How to Use IBM MQ Messaging — MQ operations and their I/O points.
- Understanding Your Migrated PL/I Application — the big-picture overview.
0 Comments