1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/****************************************************************
* *
* Copyright 2001, 2013 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#ifndef SLEEP_H
#define SLEEP_H
/* Note: GT.M code *MUST NOT* use the sleep function because it causes problems with GT.M's timers on some platforms. Specifically,
* the sleep function results in SIGARLM handler being silently deleted on Solaris systems (through Solaris 9 at least). This leads
* to lost timer pops and has the potential for system hangs. The proper long sleep mechanism is hiber_start which can be accessed
* through the LONG_SLEEP macro defined in mdef.h.
*/
int m_sleep(int seconds);
int m_usleep(int useconds);
int m_nsleep(int nseconds);
#ifdef UNIX
# if !defined(_AIX) && !defined(__osf__) && !defined(__hpux) && !defined(__sparc) && !defined(_UWIN) && !defined(__linux__)
# if !defined(__MVS__) && !defined(__CYGWIN__)
# error "Unsure of support for sleep functions on this platform"
# endif
# endif
#define E_6 1000000
#define E_9 1000000000
#define SET_EXPIR_TIME(NOW_TIMEVAL, EXPIR_TIMEVAL, SECS, USECS) \
{ \
gettimeofday(&(NOW_TIMEVAL), NULL); \
if (E_6 <= ((NOW_TIMEVAL).tv_usec + USECS)) \
{ \
(EXPIR_TIMEVAL).tv_sec = (NOW_TIMEVAL).tv_sec + (SECS) + 1; \
(EXPIR_TIMEVAL).tv_usec = (NOW_TIMEVAL).tv_usec + (USECS) - E_6; \
} else \
{ \
(EXPIR_TIMEVAL).tv_sec = (NOW_TIMEVAL).tv_sec + (SECS); \
(EXPIR_TIMEVAL).tv_usec = (NOW_TIMEVAL).tv_usec + (USECS); \
} \
}
#define EVAL_REM_TIME(NOW_TIMEVAL, EXPIR_TIMEVAL, SECS, USECS) \
{ \
gettimeofday(&(NOW_TIMEVAL), NULL); \
if (((NOW_TIMEVAL).tv_sec > (EXPIR_TIMEVAL).tv_sec) \
|| (((NOW_TIMEVAL).tv_sec == (EXPIR_TIMEVAL).tv_sec) \
&& ((NOW_TIMEVAL).tv_usec >= (EXPIR_TIMEVAL).tv_usec))) \
return; \
if ((EXPIR_TIMEVAL).tv_usec < (NOW_TIMEVAL).tv_usec) \
{ \
SECS = (time_t)((EXPIR_TIMEVAL).tv_sec - (NOW_TIMEVAL).tv_sec - 1); \
USECS = (int)(E_6 + (EXPIR_TIMEVAL).tv_usec - (NOW_TIMEVAL).tv_usec); \
} else \
{ \
SECS = (time_t)((EXPIR_TIMEVAL).tv_sec - (NOW_TIMEVAL).tv_sec); \
USECS = (int)((EXPIR_TIMEVAL).tv_usec - (NOW_TIMEVAL).tv_usec); \
} \
}
#if defined(__osf__) || defined(__hpux)
/* The above platforms do not support clock_nanosleep, so use nanosleep. To avoid sleeping for much
* longer than requested in case of pathologically many interrupts, recalculate the remaining duration
* with gettimeofday.
*/
# define NANOSLEEP(MS) \
{ \
int status, usecs; \
struct timespec req; \
struct timeval now, expir; \
\
assert(0 < MS); \
req.tv_sec = (time_t)(MS / 1000); \
usecs = (MS % 1000) * 1000; \
req.tv_nsec = (long)(usecs * 1000); \
assert(E_9 > req.tv_nsec); \
SET_EXPIR_TIME(now, expir, req.tv_sec, usecs) \
while ((-1 == (status = nanosleep(&req, NULL))) && (EINTR == errno)) \
{ \
EVAL_REM_TIME(now, expir, req.tv_sec, usecs); \
req.tv_nsec = (long)(usecs * 1000); \
} \
}
#elif defined(__MVS__)
/* On z/OS neither clock_nanosleep nor nanosleep is available, so use a combination of sleep, usleep,
* and gettimeofday instead. Since we do not have a z/OS box presently, this implementation has not
* been tested, and so it likely needs some casts at the very least. Another note is that sleep is
* unsafe to mix with timers on other platforms, but on z/OS the documentation does not mention any
* fallouts, so this should be verified. If it turns out that sleep is unsafe, we might have to use
* pthread_cond_timewait or call usleep (which, given that we have used it on z/OS before, should be
* safe) in a loop.
*/
# define NANOSLEEP(MS) \
{ \
int secs; \
useconds_t usecs; \
struct timeval now, expir; \
\
assert(0 < MS); \
secs = MS / 1000; \
usecs = MS % 1000; \
SET_EXPIR_TIME(now, expir, secs, usecs) \
while (0 < secs) \
{ \
sleep(secs); /* BYPASSOK: */ \
EVAL_REM_TIME(now, expir, secs, usecs); \
} \
while (0 < usecs) \
{ \
usleep(usecs); \
EVAL_REM_TIME(now, expir, secs, usecs); \
} \
}
#else
/* The major supported platforms should have clock_nanosleep implementation, so to avoid extending the
* actual sleep times, we use clock_gettime to first obtain the point of reference, and then specify
* the TIMER_ABSTIME flag when invoking clock_nanosleep for absolute offsets. In case CLOCK_REALTIME
* type of clock is not supported on some platform, we fall back on nanosleep.
*/
# define NANOSLEEP(MS) \
{ \
int status, usecs; \
struct timespec req, cur; \
struct timeval now, expir; \
\
req.tv_sec = (time_t)(MS / 1000); \
usecs = (MS % 1000) * 1000; \
req.tv_nsec = (long)(usecs * 1000); \
assert(E_9 > req.tv_nsec); \
if ((-1 == (status = clock_gettime(CLOCK_REALTIME, &cur))) && (EINVAL == errno)) \
{ \
SET_EXPIR_TIME(now, expir, req.tv_sec, usecs) \
while ((-1 == (status = nanosleep(&req, NULL))) && (EINTR == errno)) \
{ \
EVAL_REM_TIME(now, expir, req.tv_sec, usecs); \
req.tv_nsec = (long)(usecs * 1000); \
} \
} else \
{ \
if (E_9 <= cur.tv_nsec + req.tv_nsec) \
{ \
req.tv_sec += (cur.tv_sec + 1); \
req.tv_nsec = cur.tv_nsec + req.tv_nsec - E_9; \
} else \
{ \
req.tv_sec += cur.tv_sec; \
req.tv_nsec += cur.tv_nsec; \
} \
while ((-1 == (status = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &req, NULL))) \
&& (EINTR == errno)); \
} \
}
#endif
# ifdef _AIX
typedef struct timestruc_t m_time_t;
# define nanosleep_func nsleep
# endif
# if defined(__sparc) || defined(__hpux) || defined(__osf__) || defined (__linux__) || defined (__CYGWIN__)
typedef struct timespec m_time_t;
# define nanosleep_func nanosleep
# endif
# ifdef _UWIN
# include "gtm_select.h"
# define usleep_func gtm_usleep
# endif
# ifdef __MVS__
typedef struct timespec m_time_t;
# define nanosleep_func usleep /* m_nsleep will not work on OS390, but it is not used */
# endif
#else
# error "Unsure of support for sleep functions on this non-UNIX platform"
#endif
#endif /* SLEEP_H */
|