Skip to content

Commit 6fc4ade

Browse files
committed
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
exposed in Python.h. This function is similar to POSIX gettimeofday(struct timeval *tp), but available on platforms without gettimeofday().
1 parent 1c5471f commit 6fc4ade

File tree

8 files changed

+150
-85
lines changed

8 files changed

+150
-85
lines changed

Include/Python.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#error "PYMALLOC_DEBUG requires WITH_PYMALLOC"
6262
#endif
6363
#include "pymath.h"
64+
#include "pytime.h"
6465
#include "pymem.h"
6566

6667
#include "object.h"

Include/pytime.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef Py_PYTIME_H
2+
#define Py_PYTIME_H
3+
4+
#include "pyconfig.h" /* include for defines */
5+
6+
/**************************************************************************
7+
Symbols and macros to supply platform-independent interfaces to time related
8+
functions and constants
9+
**************************************************************************/
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
#ifdef HAVE_GETTIMEOFDAY
15+
typedef struct timeval _PyTime_timeval;
16+
#else
17+
typedef struct {
18+
time_t tv_sec; /* seconds since Jan. 1, 1970 */
19+
long tv_usec; /* and microseconds */
20+
} _PyTime_timeval;
21+
#endif
22+
23+
/* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday
24+
* fails or is not available, fall back to lower resolution clocks.
25+
*/
26+
PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp);
27+
28+
/* Dummy to force linking. */
29+
PyAPI_FUNC(void) _PyTime_Init(void);
30+
31+
#ifdef __cplusplus
32+
}
33+
#endif
34+
35+
#endif /* Py_PYTIME_H */
36+
#ifndef Py_PYTIME_H
37+
#define Py_PYTIME_H
38+
39+
#include "pyconfig.h" /* include for defines */
40+
41+
/**************************************************************************
42+
Symbols and macros to supply platform-independent interfaces to time related
43+
functions and constants
44+
**************************************************************************/
45+
#ifdef __cplusplus
46+
extern "C" {
47+
#endif
48+
49+
#ifdef HAVE_GETTIMEOFDAY
50+
typedef struct timeval _PyTime_timeval;
51+
#else
52+
typedef struct {
53+
time_t tv_sec; /* seconds since Jan. 1, 1970 */
54+
long tv_usec; /* and microseconds */
55+
} _PyTime_timeval;
56+
#endif
57+
58+
/* Similar to POSIX gettimeofday but cannot fail. If system gettimeofday
59+
* fails or is not available, fall back to lower resolution clocks.
60+
*/
61+
PyAPI_FUNC(void) _PyTime_gettimeofday(_PyTime_timeval *tp);
62+
63+
/* Dummy to force linking. */
64+
PyAPI_FUNC(void) _PyTime_Init(void);
65+
66+
#ifdef __cplusplus
67+
}
68+
#endif
69+
70+
#endif /* Py_PYTIME_H */

Makefile.pre.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ PYTHON_OBJS= \
314314
Python/pymath.o \
315315
Python/pystate.o \
316316
Python/pythonrun.o \
317+
Python/pytime.o \
317318
Python/structmember.o \
318319
Python/symtable.o \
319320
Python/sysmodule.o \
@@ -696,6 +697,7 @@ PYTHON_HEADERS= \
696697
Include/pystrtod.h \
697698
Include/pythonrun.h \
698699
Include/pythread.h \
700+
Include/pytime.h \
699701
Include/rangeobject.h \
700702
Include/setobject.h \
701703
Include/sliceobject.h \

Modules/_datetimemodule.c

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#include <time.h>
1010

11-
#include "timefuncs.h"
11+
#include "_time.h"
1212

1313
/* Differentiate between building the core module and building extension
1414
* modules.
@@ -4166,37 +4166,10 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp,
41664166
static PyObject *
41674167
datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
41684168
{
4169-
#ifdef HAVE_GETTIMEOFDAY
4170-
struct timeval t;
4171-
4172-
#ifdef GETTIMEOFDAY_NO_TZ
4173-
gettimeofday(&t);
4174-
#else
4175-
gettimeofday(&t, (struct timezone *)NULL);
4176-
#endif
4169+
_PyTime_timeval t;
4170+
_PyTime_gettimeofday(&t);
41774171
return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
41784172
tzinfo);
4179-
4180-
#else /* ! HAVE_GETTIMEOFDAY */
4181-
/* No flavor of gettimeofday exists on this platform. Python's
4182-
* time.time() does a lot of other platform tricks to get the
4183-
* best time it can on the platform, and we're not going to do
4184-
* better than that (if we could, the better code would belong
4185-
* in time.time()!) We're limited by the precision of a double,
4186-
* though.
4187-
*/
4188-
PyObject *time;
4189-
double dtime;
4190-
4191-
time = time_time();
4192-
if (time == NULL)
4193-
return NULL;
4194-
dtime = PyFloat_AsDouble(time);
4195-
Py_DECREF(time);
4196-
if (dtime == -1.0 && PyErr_Occurred())
4197-
return NULL;
4198-
return datetime_from_timestamp(cls, f, dtime, tzinfo);
4199-
#endif /* ! HAVE_GETTIMEOFDAY */
42004173
}
42014174

42024175
/* Return best possible local time -- this isn't constrained by the

Modules/timemodule.c

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,10 @@
33

44
#include "Python.h"
55
#include "structseq.h"
6-
#include "timefuncs.h"
6+
#include "_time.h"
77

88
#define TZNAME_ENCODING "utf-8"
99

10-
#ifdef __APPLE__
11-
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME)
12-
/*
13-
* floattime falls back to ftime when getttimeofday fails because the latter
14-
* might fail on some platforms. This fallback is unwanted on MacOSX because
15-
* that makes it impossible to use a binary build on OSX 10.4 on earlier
16-
* releases of the OS. Therefore claim we don't support ftime.
17-
*/
18-
# undef HAVE_FTIME
19-
#endif
20-
#endif
21-
2210
#include <ctype.h>
2311

2412
#ifdef HAVE_SYS_TYPES_H
@@ -29,13 +17,6 @@
2917
#include <io.h>
3018
#endif
3119

32-
#ifdef HAVE_FTIME
33-
#include <sys/timeb.h>
34-
#if !defined(MS_WINDOWS) && !defined(PYOS_OS2)
35-
extern int ftime(struct timeb *);
36-
#endif /* MS_WINDOWS */
37-
#endif /* HAVE_FTIME */
38-
3920
#if defined(__WATCOMC__) && !defined(__QNX__)
4021
#include <i86.h>
4122
#else
@@ -946,44 +927,12 @@ PyInit_time(void)
946927
return m;
947928
}
948929

949-
950-
/* Implement floattime() for various platforms */
951-
952930
static double
953931
floattime(void)
954932
{
955-
/* There are three ways to get the time:
956-
(1) gettimeofday() -- resolution in microseconds
957-
(2) ftime() -- resolution in milliseconds
958-
(3) time() -- resolution in seconds
959-
In all cases the return value is a float in seconds.
960-
Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
961-
fail, so we fall back on ftime() or time().
962-
Note: clock resolution does not imply clock accuracy! */
963-
#ifdef HAVE_GETTIMEOFDAY
964-
{
965-
struct timeval t;
966-
#ifdef GETTIMEOFDAY_NO_TZ
967-
if (gettimeofday(&t) == 0)
968-
return (double)t.tv_sec + t.tv_usec*0.000001;
969-
#else /* !GETTIMEOFDAY_NO_TZ */
970-
if (gettimeofday(&t, (struct timezone *)NULL) == 0)
971-
return (double)t.tv_sec + t.tv_usec*0.000001;
972-
#endif /* !GETTIMEOFDAY_NO_TZ */
973-
}
974-
975-
#endif /* !HAVE_GETTIMEOFDAY */
976-
{
977-
#if defined(HAVE_FTIME)
978-
struct timeb t;
979-
ftime(&t);
980-
return (double)t.time + (double)t.millitm * (double)0.001;
981-
#else /* !HAVE_FTIME */
982-
time_t secs;
983-
time(&secs);
984-
return (double)secs;
985-
#endif /* !HAVE_FTIME */
986-
}
933+
_PyTime_timeval t;
934+
_PyTime_gettimeofday(&t);
935+
return (double)t.tv_sec + t.tv_usec*0.000001;
987936
}
988937

989938

PCbuild/pythoncore.vcproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,10 @@
875875
RelativePath="..\Include\pymath.h"
876876
>
877877
</File>
878+
<File
879+
RelativePath="..\Include\pytime.h"
880+
>
881+
</File>
878882
<File
879883
RelativePath="..\Include\pymem.h"
880884
>
@@ -1767,6 +1771,10 @@
17671771
RelativePath="..\Python\pymath.c"
17681772
>
17691773
</File>
1774+
<File
1775+
RelativePath="..\Python\pytime.c"
1776+
>
1777+
</File>
17701778
<File
17711779
RelativePath="..\Python\pystate.c"
17721780
>

Python/pythonrun.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ Py_InitializeEx(int install_sigs)
268268
/* Initialize _warnings. */
269269
_PyWarnings_Init();
270270

271+
_PyTime_Init();
272+
271273
initfsencoding();
272274

273275
if (install_sigs)

Python/pytime.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include "Python.h"
2+
3+
#ifdef __APPLE__
4+
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME)
5+
/*
6+
* _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter
7+
* might fail on some platforms. This fallback is unwanted on MacOSX because
8+
* that makes it impossible to use a binary build on OSX 10.4 on earlier
9+
* releases of the OS. Therefore claim we don't support ftime.
10+
*/
11+
# undef HAVE_FTIME
12+
#endif
13+
#endif
14+
15+
#ifdef HAVE_FTIME
16+
#include <sys/timeb.h>
17+
#if !defined(MS_WINDOWS) && !defined(PYOS_OS2)
18+
extern int ftime(struct timeb *);
19+
#endif /* MS_WINDOWS */
20+
#endif /* HAVE_FTIME */
21+
22+
void
23+
_PyTime_gettimeofday(_PyTime_timeval *tp)
24+
{
25+
/* There are three ways to get the time:
26+
(1) gettimeofday() -- resolution in microseconds
27+
(2) ftime() -- resolution in milliseconds
28+
(3) time() -- resolution in seconds
29+
In all cases the return value in a timeval struct.
30+
Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
31+
fail, so we fall back on ftime() or time().
32+
Note: clock resolution does not imply clock accuracy! */
33+
#ifdef HAVE_GETTIMEOFDAY
34+
#ifdef GETTIMEOFDAY_NO_TZ
35+
if (gettimeofday(tp) == 0)
36+
return;
37+
#else /* !GETTIMEOFDAY_NO_TZ */
38+
if (gettimeofday(tp, (struct timezone *)NULL) == 0)
39+
return;
40+
#endif /* !GETTIMEOFDAY_NO_TZ */
41+
#endif /* !HAVE_GETTIMEOFDAY */
42+
#if defined(HAVE_FTIME)
43+
{
44+
struct timeb t;
45+
ftime(&t);
46+
tp->tv_sec = t.time;
47+
tp->tv_usec = t.millitm * 1000;
48+
}
49+
#else /* !HAVE_FTIME */
50+
tp->tv_sec = time(NULL);
51+
tp->tv_usec = 0;
52+
#endif /* !HAVE_FTIME */
53+
return;
54+
}
55+
56+
void
57+
_PyTime_Init()
58+
{
59+
/* Do nothing. Needed to force linking. */
60+
}

0 commit comments

Comments
 (0)