System abend

S322: CPU time limit exceeded

An S322 abend means a job or step used all the processor (CPU) time it was allowed, set by the TIME parameter or the job class default, so z/OS ended it. A program loop is the most common cause.

Also written as 322, abend 322, S322 abend, system abend 322, ABEND=S322, CPU time exceeded.

What it means

z/OS counts the processor time each job step uses. The limit comes from the TIME parameter on the EXEC statement, the TIME parameter on the JOB statement, or a default your installation sets for the job class. When a step reaches its limit, the system ends it with system completion code 322.

Only CPU time counts, meaning time the program spends running on a processor. Time spent waiting for I/O, for a tape or for another job to free a data set doesn't count, so a step can run for an hour and use a few seconds of CPU. An S322 tells you the program was busy the whole time. It was doing far more work than usual, or it was going round in a loop.

If TIME is coded on both the JOB and the EXEC statement, both limits apply. A step can't use more than its own limit, and it can't use more than the time the job has left.

Common causes

  • A loop in the program. A PERFORM UNTIL whose condition never comes true, or a read loop that keeps processing the same record, runs until the time limit stops it.
  • The input is much bigger than usual, such as a month-end or year-end file, and the step needs more CPU than its limit allows.
  • The TIME value is too small. It was copied from another job or set years ago, or the job moved to a class with a lower default.
  • A code change made the program slower, for example a table search that now runs once per record instead of once per run, or a database query that now reads far more rows.

How to find the problem

  1. Check the CPU time in the step end message, IEF032I (or IEF374I on some systems). If it matches the TIME value on the EXEC or JOB statement, or the class default, the step ran out of time.
  2. Read the IEA995I symptom dump. The PSW and the offset into the active load module show where the program was running when the time ran out. Find that offset in the compile listing. In a loop, the statement there is usually inside the loop.
  3. Compare record counts with a normal run. Normal counts with ten times the CPU point to a loop. Ten times the records points to the data volume.
  4. For a loop, check the condition that should end it. Look for a counter that is reset inside the loop, an end-of-file flag that is never set, or a file status that is ignored after a failed read.

How to fix it

  • Fix the loop first. Giving a looping program more time only makes it fail later and cost more.
  • If the work really needs more time, raise TIME on the EXEC statement. TIME=10 allows 10 minutes and TIME=(2,30) allows two and a half. If the JOB statement also has TIME, raise that too.
  • Avoid TIME=NOLIMIT or TIME=1440 as a quick fix. They switch the limit off, so a loop runs until an operator cancels it.
  • If the job class limit is the problem, ask your scheduling or operations team which class suits long-running work.

What it looks like

IEA995I SYMPTOM DUMP OUTPUT
  SYSTEM COMPLETION CODE=322  REASON CODE=00000000
   PSW AT TIME OF ERROR  078D1000   9F0035C6  ILC 0  INTC 00
   ACTIVE LOAD MODULE           ADDRESS=1F002E10  OFFSET=000007B6
   NAME=PAYCALC
IEF450I PAYRUN01 STEP030 - ABEND=S322 U0000 REASON=00000000
IEF032I STEP/STEP030 /STOP 2026285.0214
        CPU:     0 HR  05 MIN  00.02 SEC    SRB:     0 HR  00 MIN  00.11 SEC

Questions

What is the difference between S322 and S522?

S322 means the step used too much CPU time. S522 means it sat waiting too long without doing anything. A busy program gets S322 and a stuck one gets S522.

Does TIME=1440 remove the limit?

Yes, for that step. TIME=1440 or TIME=NOLIMIT on the EXEC statement tells the system not to time the step, and it also switches off the wait limit behind S522. Keep it for work that is meant to run a long time.

Why did the job pass yesterday and fail today with S322?

Usually the input was bigger, or a change introduced a loop or slower logic. The CPU time and record counts of the last good run tell you which.