Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* Time module */ | 1 /* Time module */ |
2 | 2 |
3 #include "Python.h" | 3 #include "Python.h" |
4 | 4 |
5 #include <ctype.h> | 5 #include <ctype.h> |
6 | 6 |
7 #ifdef HAVE_SYS_TIMES_H | 7 #ifdef HAVE_SYS_TIMES_H |
8 #include <sys/times.h> | 8 #include <sys/times.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 19 matching lines...) Expand all Loading... | |
30 | 30 |
31 #if defined(__BORLANDC__) | 31 #if defined(__BORLANDC__) |
32 /* These overrides not needed for Win32 */ | 32 /* These overrides not needed for Win32 */ |
33 #define timezone _timezone | 33 #define timezone _timezone |
34 #define tzname _tzname | 34 #define tzname _tzname |
35 #define daylight _daylight | 35 #define daylight _daylight |
36 #endif /* __BORLANDC__ */ | 36 #endif /* __BORLANDC__ */ |
37 #endif /* MS_WINDOWS */ | 37 #endif /* MS_WINDOWS */ |
38 #endif /* !__WATCOMC__ || __QNX__ */ | 38 #endif /* !__WATCOMC__ || __QNX__ */ |
39 | 39 |
40 #if defined(__APPLE__) | |
41 #include <mach/mach_time.h> | |
42 #endif | |
43 | |
44 /* Forward declarations */ | 40 /* Forward declarations */ |
45 static int floatsleep(double); | 41 static int floatsleep(double); |
46 static PyObject* floattime(_Py_clock_info_t *info); | 42 static PyObject* floattime(_Py_clock_info_t *info); |
47 | 43 |
48 #ifdef MS_WINDOWS | 44 #ifdef MS_WINDOWS |
49 static OSVERSIONINFOEX winver; | 45 static OSVERSIONINFOEX winver; |
50 #endif | 46 #endif |
51 | 47 |
52 static PyObject * | 48 static PyObject * |
53 time_time(PyObject *self, PyObject *unused) | 49 time_time(PyObject *self, PyObject *unused) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 info->adjustable = 0; | 85 info->adjustable = 0; |
90 } | 86 } |
91 return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC); | 87 return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC); |
92 } | 88 } |
93 #endif /* HAVE_CLOCK */ | 89 #endif /* HAVE_CLOCK */ |
94 | 90 |
95 #if defined(MS_WINDOWS) && !defined(__BORLANDC__) | 91 #if defined(MS_WINDOWS) && !defined(__BORLANDC__) |
96 #define WIN32_PERF_COUNTER | 92 #define WIN32_PERF_COUNTER |
97 /* Win32 has better clock replacement; we have our own version, due to Mark | 93 /* Win32 has better clock replacement; we have our own version, due to Mark |
98 Hammond and Tim Peters */ | 94 Hammond and Tim Peters */ |
99 static int | 95 static PyObject* |
100 win_perf_counter(_Py_clock_info_t *info, PyObject **result) | 96 win_perf_counter(_Py_clock_info_t *info) |
101 { | 97 { |
102 static LONGLONG cpu_frequency = 0; | 98 static LONGLONG cpu_frequency = 0; |
103 static LONGLONG ctrStart; | 99 static LONGLONG ctrStart; |
104 LARGE_INTEGER now; | 100 LARGE_INTEGER now; |
105 double diff; | 101 double diff; |
106 | 102 |
107 if (cpu_frequency == 0) { | 103 if (cpu_frequency == 0) { |
108 LARGE_INTEGER freq; | 104 LARGE_INTEGER freq; |
109 QueryPerformanceCounter(&now); | 105 QueryPerformanceCounter(&now); |
110 ctrStart = now.QuadPart; | 106 ctrStart = now.QuadPart; |
111 if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { | 107 if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { |
112 /* Unlikely to happen - this works on all intel | 108 PyErr_SetFromWindowsErr(0); |
113 machines at least! Revert to clock() */ | 109 return NULL; |
114 *result = NULL; | |
115 return -1; | |
116 } | 110 } |
117 cpu_frequency = freq.QuadPart; | 111 cpu_frequency = freq.QuadPart; |
118 } | 112 } |
119 QueryPerformanceCounter(&now); | 113 QueryPerformanceCounter(&now); |
120 diff = (double)(now.QuadPart - ctrStart); | 114 diff = (double)(now.QuadPart - ctrStart); |
121 if (info) { | 115 if (info) { |
122 info->implementation = "QueryPerformanceCounter()"; | 116 info->implementation = "QueryPerformanceCounter()"; |
123 info->resolution = 1.0 / (double)cpu_frequency; | 117 info->resolution = 1.0 / (double)cpu_frequency; |
124 info->monotonic = 1; | 118 info->monotonic = 1; |
125 info->adjustable = 0; | 119 info->adjustable = 0; |
126 } | 120 } |
127 *result = PyFloat_FromDouble(diff / (double)cpu_frequency); | 121 return PyFloat_FromDouble(diff / (double)cpu_frequency); |
128 return 0; | |
129 } | 122 } |
130 #endif | 123 #endif |
131 | 124 |
132 #if defined(WIN32_PERF_COUNTER) || defined(HAVE_CLOCK) | 125 #if defined(WIN32_PERF_COUNTER) || defined(HAVE_CLOCK) |
133 #define PYCLOCK | 126 #define PYCLOCK |
134 static PyObject* | 127 static PyObject* |
135 pyclock(_Py_clock_info_t *info) | 128 pyclock(_Py_clock_info_t *info) |
136 { | 129 { |
137 #ifdef WIN32_PERF_COUNTER | 130 #ifdef WIN32_PERF_COUNTER |
138 PyObject *res; | 131 return win_perf_counter(info); |
139 if (win_perf_counter(info, &res) == 0) | 132 #else |
140 return res; | |
141 #endif | |
142 return floatclock(info); | 133 return floatclock(info); |
134 #endif | |
143 } | 135 } |
144 | 136 |
145 static PyObject * | 137 static PyObject * |
146 time_clock(PyObject *self, PyObject *unused) | 138 time_clock(PyObject *self, PyObject *unused) |
147 { | 139 { |
148 return pyclock(NULL); | 140 return pyclock(NULL); |
149 } | 141 } |
150 | 142 |
151 PyDoc_STRVAR(clock_doc, | 143 PyDoc_STRVAR(clock_doc, |
152 "clock() -> floating point number\n\ | 144 "clock() -> floating point number\n\ |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 os.environ['TZ']. The TZ environment variable should be specified in\n\ | 888 os.environ['TZ']. The TZ environment variable should be specified in\n\ |
897 standard Unix timezone format as documented in the tzset man page\n\ | 889 standard Unix timezone format as documented in the tzset man page\n\ |
898 (eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently\n\ | 890 (eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently\n\ |
899 fall back to UTC. If the TZ environment variable is not set, the local\n\ | 891 fall back to UTC. If the TZ environment variable is not set, the local\n\ |
900 timezone is set to the systems best guess of wallclock time.\n\ | 892 timezone is set to the systems best guess of wallclock time.\n\ |
901 Changing the TZ environment variable without calling tzset *may* change\n\ | 893 Changing the TZ environment variable without calling tzset *may* change\n\ |
902 the local timezone used by methods such as localtime, but this behaviour\n\ | 894 the local timezone used by methods such as localtime, but this behaviour\n\ |
903 should not be relied on."); | 895 should not be relied on."); |
904 #endif /* HAVE_WORKING_TZSET */ | 896 #endif /* HAVE_WORKING_TZSET */ |
905 | 897 |
906 #if defined(MS_WINDOWS) || defined(__APPLE__) \ | 898 static PyObject * |
907 || (defined(HAVE_CLOCK_GETTIME) \ | |
908 && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC))) | |
909 #define PYMONOTONIC | |
910 #endif | |
911 | |
912 #ifdef PYMONOTONIC | |
913 static PyObject* | |
914 pymonotonic(_Py_clock_info_t *info) | 899 pymonotonic(_Py_clock_info_t *info) |
915 { | 900 { |
916 #if defined(MS_WINDOWS) | 901 _PyTime_timeval tv; |
917 static ULONGLONG (*GetTickCount64) (void) = NULL; | 902 if (_PyTime_monotonic_info(&tv, info) < 0) { |
918 static ULONGLONG (CALLBACK *Py_GetTickCount64)(void); | 903 assert(info != NULL); |
919 static int has_getickcount64 = -1; | 904 return NULL; |
920 double result; | 905 } |
921 | 906 return PyFloat_FromDouble((double)tv.tv_sec + tv.tv_usec * 1e-6); |
922 if (has_getickcount64 == -1) { | |
923 /* GetTickCount64() was added to Windows Vista */ | |
924 if (winver.dwMajorVersion >= 6) { | |
925 HINSTANCE hKernel32; | |
926 hKernel32 = GetModuleHandleW(L"KERNEL32"); | |
927 *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32, | |
928 "GetTickCount64"); | |
929 has_getickcount64 = (Py_GetTickCount64 != NULL); | |
930 } | |
931 else | |
932 has_getickcount64 = 0; | |
933 } | |
934 | |
935 if (has_getickcount64) { | |
936 ULONGLONG ticks; | |
937 ticks = Py_GetTickCount64(); | |
938 result = (double)ticks * 1e-3; | |
939 } | |
940 else { | |
941 static DWORD last_ticks = 0; | |
942 static DWORD n_overflow = 0; | |
943 DWORD ticks; | |
944 | |
945 ticks = GetTickCount(); | |
946 if (ticks < last_ticks) | |
947 n_overflow++; | |
948 last_ticks = ticks; | |
949 | |
950 result = ldexp(n_overflow, 32); | |
951 result += ticks; | |
952 result *= 1e-3; | |
953 } | |
954 | |
955 if (info) { | |
956 DWORD timeAdjustment, timeIncrement; | |
957 BOOL isTimeAdjustmentDisabled, ok; | |
958 if (has_getickcount64) | |
959 info->implementation = "GetTickCount64()"; | |
960 else | |
961 info->implementation = "GetTickCount()"; | |
962 info->monotonic = 1; | |
963 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, | |
964 &isTimeAdjustmentDisabled); | |
965 if (!ok) { | |
966 PyErr_SetFromWindowsErr(0); | |
967 return NULL; | |
968 } | |
969 info->resolution = timeIncrement * 1e-7; | |
970 info->adjustable = 0; | |
971 } | |
972 return PyFloat_FromDouble(result); | |
973 | |
974 #elif defined(__APPLE__) | |
975 static mach_timebase_info_data_t timebase; | |
976 uint64_t time; | |
977 double secs; | |
978 | |
979 if (timebase.denom == 0) { | |
980 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot | |
981 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ | |
982 (void)mach_timebase_info(&timebase); | |
983 } | |
984 | |
985 time = mach_absolute_time(); | |
986 secs = (double)time * timebase.numer / timebase.denom * 1e-9; | |
987 if (info) { | |
988 info->implementation = "mach_absolute_time()"; | |
989 info->resolution = (double)timebase.numer / timebase.denom * 1e-9; | |
990 info->monotonic = 1; | |
991 info->adjustable = 0; | |
992 } | |
993 return PyFloat_FromDouble(secs); | |
994 | |
995 #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_HIGHRES) || defined(CLOCK_MO NOTONIC)) | |
996 struct timespec tp; | |
997 #ifdef CLOCK_HIGHRES | |
998 const clockid_t clk_id = CLOCK_HIGHRES; | |
999 const char *function = "clock_gettime(CLOCK_HIGHRES)"; | |
1000 #else | |
1001 const clockid_t clk_id = CLOCK_MONOTONIC; | |
1002 const char *function = "clock_gettime(CLOCK_MONOTONIC)"; | |
1003 #endif | |
1004 | |
1005 if (clock_gettime(clk_id, &tp) != 0) { | |
1006 PyErr_SetFromErrno(PyExc_OSError); | |
1007 return NULL; | |
1008 } | |
1009 | |
1010 if (info) { | |
1011 struct timespec res; | |
1012 info->monotonic = 1; | |
1013 info->implementation = function; | |
1014 info->adjustable = 0; | |
1015 if (clock_getres(clk_id, &res) == 0) | |
1016 info->resolution = res.tv_sec + res.tv_nsec * 1e-9; | |
1017 else | |
1018 info->resolution = 1e-9; | |
1019 } | |
1020 return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); | |
1021 #endif | |
1022 } | 907 } |
1023 | 908 |
1024 static PyObject * | 909 static PyObject * |
1025 time_monotonic(PyObject *self, PyObject *unused) | 910 time_monotonic(PyObject *self, PyObject *unused) |
1026 { | 911 { |
1027 return pymonotonic(NULL); | 912 return pymonotonic(NULL); |
1028 } | 913 } |
1029 | 914 |
1030 PyDoc_STRVAR(monotonic_doc, | 915 PyDoc_STRVAR(monotonic_doc, |
1031 "monotonic() -> float\n\ | 916 "monotonic() -> float\n\ |
1032 \n\ | 917 \n\ |
1033 Monotonic clock, cannot go backward."); | 918 Monotonic clock, cannot go backward."); |
1034 #endif /* PYMONOTONIC */ | |
1035 | 919 |
1036 static PyObject* | 920 static PyObject* |
1037 perf_counter(_Py_clock_info_t *info) | 921 perf_counter(_Py_clock_info_t *info) |
1038 { | 922 { |
1039 #if defined(WIN32_PERF_COUNTER) || defined(PYMONOTONIC) | |
1040 PyObject *res; | |
1041 #endif | |
1042 #if defined(WIN32_PERF_COUNTER) | |
1043 static int use_perf_counter = 1; | |
1044 #endif | |
1045 #ifdef PYMONOTONIC | |
1046 static int use_monotonic = 1; | |
1047 #endif | |
1048 | |
1049 #ifdef WIN32_PERF_COUNTER | 923 #ifdef WIN32_PERF_COUNTER |
1050 if (use_perf_counter) { | 924 return win_perf_counter(info); |
1051 if (win_perf_counter(info, &res) == 0) | 925 #else |
1052 return res; | 926 return pymonotonic(info); |
1053 use_perf_counter = 0; | 927 #endif |
1054 } | |
1055 #endif | |
1056 | |
1057 #ifdef PYMONOTONIC | |
1058 if (use_monotonic) { | |
1059 res = pymonotonic(info); | |
1060 if (res != NULL) | |
1061 return res; | |
1062 use_monotonic = 0; | |
1063 PyErr_Clear(); | |
1064 } | |
1065 #endif | |
1066 | |
1067 return floattime(info); | |
1068 } | 928 } |
1069 | 929 |
1070 static PyObject * | 930 static PyObject * |
1071 time_perf_counter(PyObject *self, PyObject *unused) | 931 time_perf_counter(PyObject *self, PyObject *unused) |
1072 { | 932 { |
1073 return perf_counter(NULL); | 933 return perf_counter(NULL); |
1074 } | 934 } |
1075 | 935 |
1076 PyDoc_STRVAR(perf_counter_doc, | 936 PyDoc_STRVAR(perf_counter_doc, |
1077 "perf_counter() -> float\n\ | 937 "perf_counter() -> float\n\ |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1224 info.adjustable = 0; | 1084 info.adjustable = 0; |
1225 info.resolution = 1.0; | 1085 info.resolution = 1.0; |
1226 #endif | 1086 #endif |
1227 | 1087 |
1228 if (strcmp(name, "time") == 0) | 1088 if (strcmp(name, "time") == 0) |
1229 obj = floattime(&info); | 1089 obj = floattime(&info); |
1230 #ifdef PYCLOCK | 1090 #ifdef PYCLOCK |
1231 else if (strcmp(name, "clock") == 0) | 1091 else if (strcmp(name, "clock") == 0) |
1232 obj = pyclock(&info); | 1092 obj = pyclock(&info); |
1233 #endif | 1093 #endif |
1234 #ifdef PYMONOTONIC | |
1235 else if (strcmp(name, "monotonic") == 0) | 1094 else if (strcmp(name, "monotonic") == 0) |
1236 obj = pymonotonic(&info); | 1095 obj = pymonotonic(&info); |
1237 #endif | |
1238 else if (strcmp(name, "perf_counter") == 0) | 1096 else if (strcmp(name, "perf_counter") == 0) |
1239 obj = perf_counter(&info); | 1097 obj = perf_counter(&info); |
1240 else if (strcmp(name, "process_time") == 0) | 1098 else if (strcmp(name, "process_time") == 0) |
1241 obj = py_process_time(&info); | 1099 obj = py_process_time(&info); |
1242 else { | 1100 else { |
1243 PyErr_SetString(PyExc_ValueError, "unknown clock"); | 1101 PyErr_SetString(PyExc_ValueError, "unknown clock"); |
1244 return NULL; | 1102 return NULL; |
1245 } | 1103 } |
1246 if (obj == NULL) | 1104 if (obj == NULL) |
1247 return NULL; | 1105 return NULL; |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1419 #ifdef HAVE_MKTIME | 1277 #ifdef HAVE_MKTIME |
1420 {"mktime", time_mktime, METH_O, mktime_doc}, | 1278 {"mktime", time_mktime, METH_O, mktime_doc}, |
1421 #endif | 1279 #endif |
1422 #ifdef HAVE_STRFTIME | 1280 #ifdef HAVE_STRFTIME |
1423 {"strftime", time_strftime, METH_VARARGS, strftime_doc}, | 1281 {"strftime", time_strftime, METH_VARARGS, strftime_doc}, |
1424 #endif | 1282 #endif |
1425 {"strptime", time_strptime, METH_VARARGS, strptime_doc}, | 1283 {"strptime", time_strptime, METH_VARARGS, strptime_doc}, |
1426 #ifdef HAVE_WORKING_TZSET | 1284 #ifdef HAVE_WORKING_TZSET |
1427 {"tzset", time_tzset, METH_NOARGS, tzset_doc}, | 1285 {"tzset", time_tzset, METH_NOARGS, tzset_doc}, |
1428 #endif | 1286 #endif |
1429 #ifdef PYMONOTONIC | |
1430 {"monotonic", time_monotonic, METH_NOARGS, monotonic_doc}, | 1287 {"monotonic", time_monotonic, METH_NOARGS, monotonic_doc}, |
1431 #endif | |
1432 {"process_time", time_process_time, METH_NOARGS, process_time_doc}, | 1288 {"process_time", time_process_time, METH_NOARGS, process_time_doc}, |
1433 {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, | 1289 {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, |
1434 {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, | 1290 {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, |
1435 {NULL, NULL} /* sentinel */ | 1291 {NULL, NULL} /* sentinel */ |
1436 }; | 1292 }; |
1437 | 1293 |
1438 | 1294 |
1439 PyDoc_STRVAR(module_doc, | 1295 PyDoc_STRVAR(module_doc, |
1440 "This module provides various functions to manipulate time values.\n\ | 1296 "This module provides various functions to manipulate time values.\n\ |
1441 \n\ | 1297 \n\ |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1527 PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 9); | 1383 PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 9); |
1528 #endif | 1384 #endif |
1529 PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType); | 1385 PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType); |
1530 initialized = 1; | 1386 initialized = 1; |
1531 return m; | 1387 return m; |
1532 } | 1388 } |
1533 | 1389 |
1534 static PyObject* | 1390 static PyObject* |
1535 floattime(_Py_clock_info_t *info) | 1391 floattime(_Py_clock_info_t *info) |
1536 { | 1392 { |
1537 _PyTimeSpec ts; | 1393 _PyTime_timeval t; |
1538 #ifdef HAVE_CLOCK_GETTIME | 1394 if (_PyTime_gettimeofday_info(&t, info) < 0) { |
1539 struct timespec tp; | 1395 assert(info != NULL); |
1540 int ret; | 1396 return NULL; |
1541 | 1397 } |
1542 /* _PyTime_gettimeofday() does not use clock_gettime() | 1398 return PyFloat_FromDouble((double)t.tv_sec + t.tv_usec * 1e-6); |
1543 because it would require to link Python to the rt (real-time) | |
1544 library, at least on Linux */ | |
1545 ret = clock_gettime(CLOCK_REALTIME, &tp); | |
1546 if (ret == 0) { | |
1547 if (info) { | |
1548 struct timespec res; | |
1549 info->implementation = "clock_gettime(CLOCK_REALTIME)"; | |
1550 info->monotonic = 0; | |
1551 info->adjustable = 1; | |
1552 if (clock_getres(CLOCK_REALTIME, &res) == 0) | |
1553 info->resolution = res.tv_sec + res.tv_nsec * 1e-9; | |
1554 else | |
1555 info->resolution = 1e-9; | |
1556 } | |
1557 return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); | |
1558 } | |
1559 #endif | |
1560 if (_PyTimeSpec_get_time_info(&ts, info) < 0) { | |
1561 assert(0 && "_PyTimeSpec_get_time_info should never fail"); | |
Charles-François Natali
2014/07/31 19:50:26
This is ugly.
haypo
2014/08/01 01:44:20
Done.
| |
1562 return NULL; | |
1563 } | |
1564 return PyFloat_FromDouble((double)ts.tv_sec + ts.tv_nsec * 1e-9); | |
1565 } | 1399 } |
1566 | 1400 |
1567 | 1401 |
1568 /* Implement floatsleep() for various platforms. | 1402 /* Implement floatsleep() for various platforms. |
1569 When interrupted (or when another error occurs), return -1 and | 1403 When interrupted (or when another error occurs), return -1 and |
1570 set an exception; else return 0. */ | 1404 set an exception; else return 0. */ |
1571 | 1405 |
1572 static int | 1406 static int |
1573 floatsleep(double secs) | 1407 floatsleep(double secs) |
1574 { | 1408 { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1636 } | 1470 } |
1637 #else | 1471 #else |
1638 /* XXX Can't interrupt this sleep */ | 1472 /* XXX Can't interrupt this sleep */ |
1639 Py_BEGIN_ALLOW_THREADS | 1473 Py_BEGIN_ALLOW_THREADS |
1640 sleep((int)secs); | 1474 sleep((int)secs); |
1641 Py_END_ALLOW_THREADS | 1475 Py_END_ALLOW_THREADS |
1642 #endif | 1476 #endif |
1643 | 1477 |
1644 return 0; | 1478 return 0; |
1645 } | 1479 } |
LEFT | RIGHT |