Line data Source code
1 : #include "Python.h"
2 : #ifdef MS_WINDOWS
3 : #include <windows.h>
4 : #endif
5 :
6 : #if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME)
7 : /*
8 : * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter
9 : * might fail on some platforms. This fallback is unwanted on MacOSX because
10 : * that makes it impossible to use a binary build on OSX 10.4 on earlier
11 : * releases of the OS. Therefore claim we don't support ftime.
12 : */
13 : # undef HAVE_FTIME
14 : #endif
15 :
16 : #if defined(HAVE_FTIME) && !defined(MS_WINDOWS)
17 : #include <sys/timeb.h>
18 : extern int ftime(struct timeb *);
19 : #endif
20 :
21 : static void
22 0 : pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info)
23 : {
24 : #ifdef MS_WINDOWS
25 : FILETIME system_time;
26 : ULARGE_INTEGER large;
27 : ULONGLONG microseconds;
28 :
29 : GetSystemTimeAsFileTime(&system_time);
30 : large.u.LowPart = system_time.dwLowDateTime;
31 : large.u.HighPart = system_time.dwHighDateTime;
32 : /* 11,644,473,600,000,000: number of microseconds between
33 : the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
34 : days). */
35 : microseconds = large.QuadPart / 10 - 11644473600000000;
36 : tp->tv_sec = microseconds / 1000000;
37 : tp->tv_usec = microseconds % 1000000;
38 : if (info) {
39 : DWORD timeAdjustment, timeIncrement;
40 : BOOL isTimeAdjustmentDisabled;
41 :
42 : info->implementation = "GetSystemTimeAsFileTime()";
43 : info->monotonic = 0;
44 : (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
45 : &isTimeAdjustmentDisabled);
46 : info->resolution = timeIncrement * 1e-7;
47 : info->adjustable = 1;
48 : }
49 : #else
50 : /* There are three ways to get the time:
51 : (1) gettimeofday() -- resolution in microseconds
52 : (2) ftime() -- resolution in milliseconds
53 : (3) time() -- resolution in seconds
54 : In all cases the return value in a timeval struct.
55 : Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
56 : fail, so we fall back on ftime() or time().
57 : Note: clock resolution does not imply clock accuracy! */
58 :
59 : #ifdef HAVE_GETTIMEOFDAY
60 : int err;
61 : #ifdef GETTIMEOFDAY_NO_TZ
62 : err = gettimeofday(tp);
63 : #else
64 0 : err = gettimeofday(tp, (struct timezone *)NULL);
65 : #endif
66 0 : if (err == 0) {
67 0 : if (info) {
68 0 : info->implementation = "gettimeofday()";
69 0 : info->resolution = 1e-6;
70 0 : info->monotonic = 0;
71 0 : info->adjustable = 1;
72 : }
73 0 : return;
74 : }
75 : #endif /* HAVE_GETTIMEOFDAY */
76 :
77 : #if defined(HAVE_FTIME)
78 : {
79 : struct timeb t;
80 0 : ftime(&t);
81 0 : tp->tv_sec = t.time;
82 0 : tp->tv_usec = t.millitm * 1000;
83 0 : if (info) {
84 0 : info->implementation = "ftime()";
85 0 : info->resolution = 1e-3;
86 0 : info->monotonic = 0;
87 0 : info->adjustable = 1;
88 : }
89 : }
90 : #else /* !HAVE_FTIME */
91 : tp->tv_sec = time(NULL);
92 : tp->tv_usec = 0;
93 : if (info) {
94 : info->implementation = "time()";
95 : info->resolution = 1.0;
96 : info->monotonic = 0;
97 : info->adjustable = 1;
98 : }
99 : #endif /* !HAVE_FTIME */
100 :
101 : #endif /* MS_WINDOWS */
102 : }
103 :
104 : void
105 0 : _PyTime_gettimeofday(_PyTime_timeval *tp)
106 : {
107 0 : pygettimeofday(tp, NULL);
108 0 : }
109 :
110 : void
111 0 : _PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
112 : {
113 0 : pygettimeofday(tp, info);
114 0 : }
115 :
116 : static void
117 0 : error_time_t_overflow(void)
118 : {
119 0 : PyErr_SetString(PyExc_OverflowError,
120 : "timestamp out of range for platform time_t");
121 0 : }
122 :
123 : time_t
124 0 : _PyLong_AsTime_t(PyObject *obj)
125 : {
126 : #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
127 : PY_LONG_LONG val;
128 : val = PyLong_AsLongLong(obj);
129 : #else
130 : long val;
131 : assert(sizeof(time_t) <= sizeof(long));
132 0 : val = PyLong_AsLong(obj);
133 : #endif
134 0 : if (val == -1 && PyErr_Occurred()) {
135 0 : if (PyErr_ExceptionMatches(PyExc_OverflowError))
136 0 : error_time_t_overflow();
137 0 : return -1;
138 : }
139 0 : return (time_t)val;
140 : }
141 :
142 : PyObject *
143 972 : _PyLong_FromTime_t(time_t t)
144 : {
145 : #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
146 : return PyLong_FromLongLong((PY_LONG_LONG)t);
147 : #else
148 : assert(sizeof(time_t) <= sizeof(long));
149 972 : return PyLong_FromLong((long)t);
150 : #endif
151 : }
152 :
153 : static int
154 0 : _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
155 : double denominator)
156 : {
157 : assert(denominator <= LONG_MAX);
158 0 : if (PyFloat_Check(obj)) {
159 : double d, intpart, err;
160 : /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
161 : volatile double floatpart;
162 :
163 0 : d = PyFloat_AsDouble(obj);
164 0 : floatpart = modf(d, &intpart);
165 0 : if (floatpart < 0) {
166 0 : floatpart = 1.0 + floatpart;
167 0 : intpart -= 1.0;
168 : }
169 :
170 0 : *sec = (time_t)intpart;
171 0 : err = intpart - (double)*sec;
172 0 : if (err <= -1.0 || err >= 1.0) {
173 0 : error_time_t_overflow();
174 0 : return -1;
175 : }
176 :
177 0 : floatpart *= denominator;
178 0 : *numerator = (long)floatpart;
179 0 : return 0;
180 : }
181 : else {
182 0 : *sec = _PyLong_AsTime_t(obj);
183 0 : if (*sec == (time_t)-1 && PyErr_Occurred())
184 0 : return -1;
185 0 : *numerator = 0;
186 0 : return 0;
187 : }
188 : }
189 :
190 : int
191 0 : _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
192 : {
193 0 : if (PyFloat_Check(obj)) {
194 : double d, intpart, err;
195 :
196 0 : d = PyFloat_AsDouble(obj);
197 0 : (void)modf(d, &intpart);
198 :
199 0 : *sec = (time_t)intpart;
200 0 : err = intpart - (double)*sec;
201 0 : if (err <= -1.0 || err >= 1.0) {
202 0 : error_time_t_overflow();
203 0 : return -1;
204 : }
205 0 : return 0;
206 : }
207 : else {
208 0 : *sec = _PyLong_AsTime_t(obj);
209 0 : if (*sec == (time_t)-1 && PyErr_Occurred())
210 0 : return -1;
211 0 : return 0;
212 : }
213 : }
214 :
215 : int
216 0 : _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
217 : {
218 0 : return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9);
219 : }
220 :
221 : int
222 0 : _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec)
223 : {
224 0 : return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6);
225 : }
226 :
227 : void
228 1 : _PyTime_Init()
229 : {
230 : /* Do nothing. Needed to force linking. */
231 1 : }
|