While the z/OS Language Environment does not support nanosleep
, it does provide support for cond_timed_wait
which can be used to implement nanosleep.
First, to understand how to implement nanosleep, we need to understand what it does:
it suspends a thread until a timeout or signal occurs
The cond_timed_wait
callable service does the following:
It suspends the calling thread until any one of a set of events has occurred, or until a specified amount of time has passed.
It is documented here https://www.ibm.com/docs/en/zos/2.5.0?topic=csd-cond-timed-wait-bpx1ctw-bpx4ctw-suspend-thread-limited-time-event and available via the BPX1CTW symbol.
With that said, we can write a nanosleep function that calls BPX1CTW (cont_timed_wait) as follows:
Note that you'll also need to consider the differences in error codes and return codes.
#pragma linkage(BPX4CTW, OS)
#pragma linkage(BPX1CTW, OS)
int __cond_timed_wait(unsigned int secs, unsigned int nsecs,
unsigned int event_list, unsigned int *secs_rem,
unsigned int *nsecs_rem) {
int rv, rc, rn;
ifdef __LP64__
BPX4CTW(&secs, &nsecs, &event_list, secs_rem, nsecs_rem, &rv, &rc, &rn);
#else
BPX1CTW(&secs, &nsecs, &event_list, secs_rem, nsecs_rem, &rv, &rc, &rn);
#endif
if (rv != 0)
errno = rc;
return rv;
}
int nanosleep(const struct timespec *req, struct timespec *rem) {
unsigned secrem;
unsigned nanorem;
int rv;
int err;
rv = __cond_timed_wait((unsigned int)req->tv_sec, (unsigned int)req->tv_nsec,
(unsigned int)(CW_CONDVAR | CW_INTRPT), &secrem,
&nanorem);
err = errno;
if (rem != NULL && (rv == 0 || err == EINTR)) {
rem->tv_nsec = nanorem;
rem->tv_sec = secrem;
}
/* Don't clobber errno unless __cond_timed_wait() errored.
* Don't leak EAGAIN, that just means the timeout expired.
*/
if (rv == -1 && err == EAGAIN) {
errno = 0;
rv = 0;
}
return rv;
}
If you're looking to leverage an existing z/OS library that defines nanosleep, and potentially other C runtime functions that are missing in z/OS, then consider leveraging zoslib.