Reliable high-resolution CPU TIME retrieval under MVS 3.8J

The s370_perf instruction time benchmark (see
project and
posting)
uses currently the elapsed time retrieved with STCK for all
timing measurements. Mark L. Gaubatz commented rightfully that CPU time
should be used as the basis of all performance measurements (see
message, see
topic).
To implement this one needs a low overhead method to access the task CPU time with high resolution, best with microsecond precision.

s370_perf is designed to run on MVS 3.8J, as freely
available with the
Tur(n)key 4- System
distribution. The methods used for CPU time retrieval on modern MVS systems
are not available, most notably

TIMEUSED macro not available (was introduced later)

TCBTTIME field in TCB not available
(was introduced later)

Tom Armstrong pointed me to a function CPUTIM which is included
in the Algol F IVP code IEXSAMP4 and used for algorithm timing.
It essentially returns the sum of the ACB fields
ASCBEJST and ASCBSRBT. The essential drawback is
that these fields are only updated after each dispatch, and a test quickly
showed that the CPU time retrieved this way has errors of up to 170 msec
(seen on a 2 CPU systems with only one user job active).

When searching for other 'cpu time from ASCBEJST' methods I stumbled
across the TIMED function included in the 1998 edition of the
KERNLIB section of the CERN PACKLIB (see
sourcecode).
This function calls the SVC CALLDISP to force an update of
ASCBEJST. Turns out that this works under MVS/SE,
but not under MVS 3.8J. A WAIT on a fall-through
ECB (see
posting)
also doesn't work under MVS 3.8J.

A comment in the TIMED function finally pointed me to the proper solution. The comment states effectively:

for on non-SE systems use ASCBEJST + (TOD - LCCADTOD).

LCCADTOD is a LCCA field which holds the TOD
of the last dispatch. So I searched the whole MVS 3.8J code base
for code using LCCADTOD. Easy to do after a full export with the
hercexport tool (see posting on
hercexport and tk4- takeout) and a simple

find -name "*.mac" -type f -print0 | xargs -0 grep -l ",LCCADTOD"

lists all PDS members with code accessing directly LCCADTOD.
The essential hits are

which contain two versions of a CPUTIM function from a CBT
volume, one for FORTRAN and one for PL/I. The essential core of both
implementations is

STCK TOD
LM R4,R5,TOD
$SLD R4,LCCADTOD
$ALD R4,ASCBEJST

where $ALD and $SLD are macros for double word
integer add/sub (available on the same CBT volume in PDS
cbtcov.file188). A quick test immediately shows that this works
fine and returns a high resolution CPU time.

However, the key trick of this method, that the time since last dispatch
is added, causes also a vulnerability. If a dispatch occurs between the
subtract of LCCADTOD and the add of ASCBEJST the
CPU time spend during the previous dispatch is double counted. Not very likely
to happen, but possible, especially on a single CPU system with some I/O load.
To protect against this vulnerability, I store the LCCADTOD value
at the beginning of the function, and check after all arithmetic whether the
LCCADTOD value changed. If yes, a dispatch happened, and the
whole procedure is simply re-tried. Taken all together the core of my
CPUTIM method looks like

This is a private hobbyist website
no impressum or privacy protection statement required
see
GitHub terms
Note to US readers: This content is provided by an EU citizen.
Trumps US-EU relation assessment varies between foe (15.07.2018)
and true love (25.07.2018).
Unclear what prevails, read content at our own risk.