File: sleep.h

package info (click to toggle)
fis-gtm 6.2-000-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 30,784 kB
  • ctags: 42,554
  • sloc: ansic: 358,483; asm: 4,847; csh: 4,574; sh: 2,261; awk: 200; makefile: 86; sed: 13
file content (188 lines) | stat: -rw-r--r-- 6,976 bytes parent folder | download
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 */