z/os 版本的 nanosleep()

huangapple go评论51阅读模式
英文:

z/os Version of nanosleep()

问题

我有一个类似的问题,参考链接:https://stackoverflow.com/questions/7827062/is-there-a-windows-equivalent-of-nanosleep 但是适用于 z/OS。

在 z/OS 上似乎没有 nanosleep() 函数。在查找了一些信息后,我看到了一些方法,例如:https://github.com/google/benchmark/pull/1067/files 但我想知道如何自己编写这个功能。我知道 Z ISA 架构支持非常精确的定时,即使在 sysplex 中也可以实现,所以我不想仅使用微秒来实现这个功能。

英文:

I have a similar question to: https://stackoverflow.com/questions/7827062/is-there-a-windows-equivalent-of-nanosleep but for z/OS.

There doesn't appear to be a nanosleep() function for z/OS. After poking around a bit I see some approaches like: https://github.com/google/benchmark/pull/1067/files but I'm wondering how I would go about coding this up myself. I know the Z ISA architecture supports really precise timing even across a sysplex, so I didn't want to just do this with microseconds.

答案1

得分: 2

虽然 z/OS 语言环境不支持 nanosleep,但它提供了对 cond_timed_wait 的支持,可以用来实现 nanosleep。

首先,要了解如何实现 nanosleep,我们需要了解它的功能:
> 它挂起一个线程,直到超时或发生信号。

cond_timed_wait 可调用服务执行以下操作:
> 它挂起调用线程,直到一组事件中的任何一个发生,或者直到经过了指定的时间量。

可以在这里查看文档:https://www.ibm.com/docs/en/zos/2.5.0?topic=csd-cond-timed-wait-bpx1ctw-bpx4ctw-suspend-thread-limited-time-event,并且可以通过 BPX1CTW 符号访问。

有了这些信息,我们可以编写一个调用 BPX1CTW(cont_timed_wait)的 nanosleep 函数,如下所示:

请注意,您还需要考虑错误代码和返回代码的差异。

#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;
  }

  /* 不要在 __cond_timed_wait() 未出错时破坏 errno。
   * 不要泄漏 EAGAIN,这只是超时过期的意思。
   */
  if (rv == -1 && err == EAGAIN) {
    errno = 0;
    rv = 0;
  }

  return rv;
}

如果您想利用现有的 z/OS 库来定义 nanosleep,以及可能缺少在 z/OS 中的其他 C 运行时函数,那么可以考虑使用 zoslib

英文:

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.

huangapple
  • 本文由 发表于 2023年6月22日 03:43:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526637.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定