Thursday, October 21, 2021

Delaying a CL program by a fraction of a second with USLEEP

call usleep in a cl program

I have already written about how to delay a RPG program by less than a second by using the USLEEP procedure. Now I need to do the same in a CL program.

As we are in 2021 I hope that all of your CL source members are all the type CLLE. The program I am going to show must be compiled using the Create Bound CL program command, CRTBNDCL, not using the Create CL program command, CRTCLPGM, which is the default for type CLP.

USLEEP is a UNIX type API. This means that it is case sensitive. When I use it in a program I must use usleep, and not USLEEP or Usleep. I am just going to refer to it in the text of this post as USLEEP as it is easier for you to see its name amongst the rest of the text.

Let me jump straight in and show the code for the simple program I wrote to show how to use USLEEP in a CL program.

01  PGM





Line 2: In RPG this was a 10 long unsigned integer type variable. In CL it is still an unsigned integer, but it is four long. Notice that when I define the unsigned integer with no decimal places because an integer cannot contain a fraction of any number.

Line 3: This will contain the value returned from USLEEP. It is optional, and I am only including this to illustrate an issue later on.

Line 3: I am changing the value in &MICROSECS to be one microsecond less than a second.

Line 5: This is where I call USLEEP. As USLEEP is an external procedure I call it using the Call Procedure command, CALLPRC. I am passing the micro seconds, and getting the return value from the procedure in the &RTNVAL variable. Just for now ignore the *BYVAL I will talk about that later.

I place a debug break point at line 6, and call the program. When I check the value that was returned by USLEEP I see:


This means that the procedure was called and it executed without error.

What about the *BYVAL?

There are two ways I can pass a parameter to a procedure:

  1. By value: *BYVAL
  2. By reference: *BYREF
  Parameter  . . . . . . > &MICROSECS                 
  Passed . . . . . . . .     *BYVAL        *BYREF, *BYVAL

By passing by value means that USLEEP receives a copy of the parameter. Any changes made within the procedure do not change the value in the CL variable.

Passing by reference means that the pointer address of the variable is passed to the procedure.

The default for the CALLPRC command is *BYREF. If I change line 5 to be:

05  CALLPRC PRC('usleep') PARM((&MICROSECS)) +

The CALLPRC uses the default, *BYREF. When I call the program the value in &RTNVAL is not blank, which indicates that there was an error in the procedure.

&RTNVAL = 4294967295

Which is why I pass the micro seconds by value, not reference.

As you have seen it is as easy to call USLEEP in a CL as it is in RPG. So next time you need to delay job by a fraction of a second your CL programs don't have to call a RPG program to do so.


This article was written for IBM i 7.4, and should work for some earlier releases too.


  1. This looks interesting. Thank you for posting.

    There is a typo in the text:
    By reference: *BAYREF

    1. Oops. Thank you for pointing that out. The correction has been made.

  2. Technically, &RTNVAL should be integer not unsigned integer and this is respectful of the prototype exposed by the API.
    In fact, you are getting a big number as an error, buy should be a negative number, that's the way of posix apis...

  3. see this (follows by previous email) by IBM that confirm this

  4. Reynaldo Dandreb MedillaOctober 25, 2021 at 9:38 AM

    simple and cool Simon, thanks

  5. Great, thank you Simon for sharing!


To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.