summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_fileutils.h4
-rw-r--r--Include/internal/pycore_pylifecycle.h1
-rw-r--r--Include/internal/pycore_runtime.h2
-rw-r--r--Include/internal/pycore_time.h10
-rw-r--r--Modules/clinic/posixmodule.c.h10
-rw-r--r--Modules/posixmodule.c53
-rw-r--r--Modules/timemodule.c158
-rw-r--r--Python/fileutils.c24
-rw-r--r--Python/pylifecycle.c5
9 files changed, 142 insertions, 125 deletions
diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h
index 2f89da2..5c55282 100644
--- a/Include/internal/pycore_fileutils.h
+++ b/Include/internal/pycore_fileutils.h
@@ -320,6 +320,10 @@ PyAPI_FUNC(char*) _Py_UniversalNewlineFgetsWithSize(char *, int, FILE*, PyObject
extern int _PyFile_Flush(PyObject *);
+#ifndef MS_WINDOWS
+extern int _Py_GetTicksPerSecond(long *ticks_per_second);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index 61e0150..daf7cb7 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -40,7 +40,6 @@ extern void _PySys_FiniTypes(PyInterpreterState *interp);
extern int _PyBuiltins_AddExceptions(PyObject * bltinmod);
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
-extern PyStatus _PyTime_Init(void);
extern PyStatus _PyGC_Init(PyInterpreterState *interp);
extern PyStatus _PyAtExit_Init(PyInterpreterState *interp);
extern int _Py_Deepfreeze_Init(void);
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index e6efe8b..3674372 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -21,7 +21,6 @@ extern "C" {
#include "pycore_pymem.h" // struct _pymem_allocators
#include "pycore_pythread.h" // struct _pythread_runtime_state
#include "pycore_signal.h" // struct _signals_runtime_state
-#include "pycore_time.h" // struct _time_runtime_state
#include "pycore_tracemalloc.h" // struct _tracemalloc_runtime_state
#include "pycore_typeobject.h" // struct _types_runtime_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_state
@@ -205,7 +204,6 @@ typedef struct pyruntimestate {
struct _pymem_allocators allocators;
struct _obmalloc_global_state obmalloc;
struct pyhash_runtime_state pyhash_state;
- struct _time_runtime_state time;
struct _pythread_runtime_state threads;
struct _signals_runtime_state signals;
diff --git a/Include/internal/pycore_time.h b/Include/internal/pycore_time.h
index 46713f9..7ea3485 100644
--- a/Include/internal/pycore_time.h
+++ b/Include/internal/pycore_time.h
@@ -52,16 +52,6 @@ extern "C" {
#endif
-struct _time_runtime_state {
-#ifdef HAVE_TIMES
- int ticks_per_second_initialized;
- long ticks_per_second;
-#else
- int _not_used;
-#endif
-};
-
-
#ifdef __clang__
struct timeval;
#endif
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index 9c54935..a6c7637 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -5997,8 +5997,6 @@ exit:
#endif /* defined(HAVE_SYMLINK) */
-#if defined(HAVE_TIMES)
-
PyDoc_STRVAR(os_times__doc__,
"times($module, /)\n"
"--\n"
@@ -6021,8 +6019,6 @@ os_times(PyObject *module, PyObject *Py_UNUSED(ignored))
return os_times_impl(module);
}
-#endif /* defined(HAVE_TIMES) */
-
#if defined(HAVE_TIMERFD_CREATE)
PyDoc_STRVAR(os_timerfd_create__doc__,
@@ -12116,10 +12112,6 @@ exit:
#define OS_SYMLINK_METHODDEF
#endif /* !defined(OS_SYMLINK_METHODDEF) */
-#ifndef OS_TIMES_METHODDEF
- #define OS_TIMES_METHODDEF
-#endif /* !defined(OS_TIMES_METHODDEF) */
-
#ifndef OS_TIMERFD_CREATE_METHODDEF
#define OS_TIMERFD_CREATE_METHODDEF
#endif /* !defined(OS_TIMERFD_CREATE_METHODDEF) */
@@ -12403,4 +12395,4 @@ exit:
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
-/*[clinic end generated code: output=0f216bf44ea358f9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2900675ac5219924 input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index d99b533..70d107a 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -1030,6 +1030,10 @@ typedef struct {
PyObject *struct_rusage;
#endif
PyObject *st_mode;
+#ifndef MS_WINDOWS
+ // times() clock frequency in hertz; used by os.times()
+ long ticks_per_second;
+#endif
} _posixstate;
@@ -9986,8 +9990,6 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
#endif /* HAVE_SYMLINK */
-
-
static PyStructSequence_Field times_result_fields[] = {
{"user", "user time"},
{"system", "system time"},
@@ -10013,12 +10015,6 @@ static PyStructSequence_Desc times_result_desc = {
5
};
-#ifdef MS_WINDOWS
-#define HAVE_TIMES /* mandatory, for the method table */
-#endif
-
-#ifdef HAVE_TIMES
-
static PyObject *
build_times_result(PyObject *module, double user, double system,
double children_user, double children_system,
@@ -10064,8 +10060,8 @@ All fields are floating point numbers.
static PyObject *
os_times_impl(PyObject *module)
/*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
-#ifdef MS_WINDOWS
{
+#ifdef MS_WINDOWS
FILETIME create, exit, kernel, user;
HANDLE hProc;
hProc = GetCurrentProcess();
@@ -10083,28 +10079,26 @@ os_times_impl(PyObject *module)
(double)0,
(double)0,
(double)0);
-}
#else /* MS_WINDOWS */
-{
- struct tms t;
- clock_t c;
+ _posixstate *state = get_posix_state(module);
+ long ticks_per_second = state->ticks_per_second;
+
+ struct tms process;
+ clock_t elapsed;
errno = 0;
- c = times(&t);
- if (c == (clock_t) -1) {
+ elapsed = times(&process);
+ if (elapsed == (clock_t) -1) {
return posix_error();
}
- assert(_PyRuntime.time.ticks_per_second_initialized);
-#define ticks_per_second _PyRuntime.time.ticks_per_second
+
return build_times_result(module,
- (double)t.tms_utime / ticks_per_second,
- (double)t.tms_stime / ticks_per_second,
- (double)t.tms_cutime / ticks_per_second,
- (double)t.tms_cstime / ticks_per_second,
- (double)c / ticks_per_second);
-#undef ticks_per_second
-}
+ (double)process.tms_utime / ticks_per_second,
+ (double)process.tms_stime / ticks_per_second,
+ (double)process.tms_cutime / ticks_per_second,
+ (double)process.tms_cstime / ticks_per_second,
+ (double)elapsed / ticks_per_second);
#endif /* MS_WINDOWS */
-#endif /* HAVE_TIMES */
+}
#if defined(HAVE_TIMERFD_CREATE)
@@ -17279,6 +17273,15 @@ posixmodule_exec(PyObject *m)
Py_DECREF(unicode);
}
+#ifndef MS_WINDOWS
+ if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "cannot read ticks_per_second");
+ return -1;
+ }
+ assert(state->ticks_per_second >= 1);
+#endif
+
return PyModule_Add(m, "_have_functions", list);
}
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index bc3901e..aa0cdc5 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -73,51 +73,20 @@ module time
static int
check_ticks_per_second(long tps, const char *context)
{
- /* Effectively, check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second)
+ /* Effectively, check that _PyTime_MulDiv(t, SEC_TO_NS, tps)
cannot overflow. */
if (tps >= 0 && (_PyTime_t)tps > _PyTime_MAX / SEC_TO_NS) {
PyErr_Format(PyExc_OverflowError, "%s is too large", context);
return -1;
}
+ if (tps < 1) {
+ PyErr_Format(PyExc_RuntimeError, "invalid %s", context);
+ return -1;
+ }
return 0;
}
#endif /* HAVE_TIMES || HAVE_CLOCK */
-#ifdef HAVE_TIMES
-
-# define ticks_per_second _PyRuntime.time.ticks_per_second
-
-static void
-ensure_ticks_per_second(void)
-{
- if (_PyRuntime.time.ticks_per_second_initialized) {
- return;
- }
- _PyRuntime.time.ticks_per_second_initialized = 1;
-# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
- ticks_per_second = sysconf(_SC_CLK_TCK);
- if (ticks_per_second < 1) {
- ticks_per_second = -1;
- }
-# elif defined(HZ)
- ticks_per_second = HZ;
-# else
- ticks_per_second = 60; /* magic fallback value; may be bogus */
-# endif
-}
-
-#endif /* HAVE_TIMES */
-
-
-PyStatus
-_PyTime_Init(void)
-{
-#ifdef HAVE_TIMES
- ensure_ticks_per_second();
-#endif
- return PyStatus_Ok();
-}
-
/* Forward declarations */
static int pysleep(_PyTime_t timeout);
@@ -125,6 +94,14 @@ static int pysleep(_PyTime_t timeout);
typedef struct {
PyTypeObject *struct_time_type;
+#ifdef HAVE_TIMES
+ // times() clock frequency in hertz
+ long ticks_per_second;
+#endif
+#ifdef HAVE_CLOCK
+ // clock() frequency in hertz
+ long clocks_per_second;
+#endif
} time_module_state;
static inline time_module_state*
@@ -184,7 +161,7 @@ PyDoc_STRVAR(time_ns_doc,
\n\
Return the current time in nanoseconds since the Epoch.");
-#if defined(HAVE_CLOCK)
+#ifdef HAVE_CLOCK
#ifndef CLOCKS_PER_SEC
# ifdef CLK_TCK
@@ -195,15 +172,12 @@ Return the current time in nanoseconds since the Epoch.");
#endif
static int
-_PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
+py_clock(time_module_state *state, _PyTime_t *tp, _Py_clock_info_t *info)
{
- if (check_ticks_per_second(CLOCKS_PER_SEC, "CLOCKS_PER_SEC") < 0) {
- return -1;
- }
-
+ long clocks_per_second = state->clocks_per_second;
if (info) {
info->implementation = "clock()";
- info->resolution = 1.0 / (double)CLOCKS_PER_SEC;
+ info->resolution = 1.0 / (double)clocks_per_second;
info->monotonic = 1;
info->adjustable = 0;
}
@@ -215,7 +189,7 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
"or its value cannot be represented");
return -1;
}
- _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC);
+ _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, clocks_per_second);
*tp = _PyTime_FromNanoseconds(ns);
return 0;
}
@@ -1277,8 +1251,38 @@ PyDoc_STRVAR(perf_counter_ns_doc,
\n\
Performance counter for benchmarking as nanoseconds.");
+
+#ifdef HAVE_TIMES
static int
-_PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
+process_time_times(time_module_state *state, _PyTime_t *tp,
+ _Py_clock_info_t *info)
+{
+ long ticks_per_second = state->ticks_per_second;
+
+ struct tms process;
+ if (times(&process) == (clock_t)-1) {
+ return 0;
+ }
+
+ if (info) {
+ info->implementation = "times()";
+ info->monotonic = 1;
+ info->adjustable = 0;
+ info->resolution = 1.0 / (double)ticks_per_second;
+ }
+
+ _PyTime_t ns;
+ ns = _PyTime_MulDiv(process.tms_utime, SEC_TO_NS, ticks_per_second);
+ ns += _PyTime_MulDiv(process.tms_stime, SEC_TO_NS, ticks_per_second);
+ *tp = _PyTime_FromNanoseconds(ns);
+ return 1;
+}
+#endif
+
+
+static int
+py_process_time(time_module_state *state, _PyTime_t *tp,
+ _Py_clock_info_t *info)
{
#if defined(MS_WINDOWS)
HANDLE process;
@@ -1381,41 +1385,28 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
/* times() */
#ifdef HAVE_TIMES
- struct tms t;
-
- if (times(&t) != (clock_t)-1) {
- assert(_PyRuntime.time.ticks_per_second_initialized);
- if (check_ticks_per_second(ticks_per_second, "_SC_CLK_TCK") < 0) {
- return -1;
- }
- if (ticks_per_second != -1) {
- if (info) {
- info->implementation = "times()";
- info->monotonic = 1;
- info->adjustable = 0;
- info->resolution = 1.0 / (double)ticks_per_second;
- }
-
- _PyTime_t ns;
- ns = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second);
- ns += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second);
- *tp = _PyTime_FromNanoseconds(ns);
- return 0;
- }
+ int res = process_time_times(state, tp, info);
+ if (res < 0) {
+ return -1;
}
+ if (res == 1) {
+ return 0;
+ }
+ // times() failed, ignore failure
#endif
/* clock */
/* Currently, Python 3 requires clock() to build: see issue #22624 */
- return _PyTime_GetClockWithInfo(tp, info);
+ return py_clock(state, tp, info);
#endif
}
static PyObject *
-time_process_time(PyObject *self, PyObject *unused)
+time_process_time(PyObject *module, PyObject *unused)
{
+ time_module_state *state = get_time_state(module);
_PyTime_t t;
- if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
+ if (py_process_time(state, &t, NULL) < 0) {
return NULL;
}
return _PyFloat_FromPyTime(t);
@@ -1427,10 +1418,11 @@ PyDoc_STRVAR(process_time_doc,
Process time for profiling: sum of the kernel and user-space CPU time.");
static PyObject *
-time_process_time_ns(PyObject *self, PyObject *unused)
+time_process_time_ns(PyObject *module, PyObject *unused)
{
+ time_module_state *state = get_time_state(module);
_PyTime_t t;
- if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
+ if (py_process_time(state, &t, NULL) < 0) {
return NULL;
}
return _PyTime_AsNanosecondsObject(t);
@@ -1617,7 +1609,7 @@ sum of the kernel and user-space CPU time.");
static PyObject *
-time_get_clock_info(PyObject *self, PyObject *args)
+time_get_clock_info(PyObject *module, PyObject *args)
{
char *name;
_Py_clock_info_t info;
@@ -1656,7 +1648,8 @@ time_get_clock_info(PyObject *self, PyObject *args)
}
}
else if (strcmp(name, "process_time") == 0) {
- if (_PyTime_GetProcessTimeWithInfo(&t, &info) < 0) {
+ time_module_state *state = get_time_state(module);
+ if (py_process_time(state, &t, &info) < 0) {
return NULL;
}
}
@@ -2116,6 +2109,25 @@ time_exec(PyObject *module)
}
#endif
+#ifdef HAVE_TIMES
+ if (_Py_GetTicksPerSecond(&state->ticks_per_second) < 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "cannot read ticks_per_second");
+ return -1;
+ }
+
+ if (check_ticks_per_second(state->ticks_per_second, "_SC_CLK_TCK") < 0) {
+ return -1;
+ }
+#endif
+
+#ifdef HAVE_CLOCK
+ state->clocks_per_second = CLOCKS_PER_SEC;
+ if (check_ticks_per_second(state->clocks_per_second, "CLOCKS_PER_SEC") < 0) {
+ return -1;
+ }
+#endif
+
return 0;
}
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 649b188..9d12bc8 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -2943,3 +2943,27 @@ _Py_closerange(int first, int last)
#endif /* USE_FDWALK */
_Py_END_SUPPRESS_IPH
}
+
+
+#ifndef MS_WINDOWS
+// Ticks per second used by clock() and times() functions.
+// See os.times() and time.process_time() implementations.
+int
+_Py_GetTicksPerSecond(long *ticks_per_second)
+{
+#if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
+ long value = sysconf(_SC_CLK_TCK);
+ if (value < 1) {
+ return -1;
+ }
+ *ticks_per_second = value;
+#elif defined(HZ)
+ assert(HZ >= 1);
+ *ticks_per_second = HZ;
+#else
+ // Magic fallback value; may be bogus
+ *ticks_per_second = 60;
+#endif
+ return 0;
+}
+#endif
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index aff67d7..95a72eb 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -528,11 +528,6 @@ pycore_init_runtime(_PyRuntimeState *runtime,
return status;
}
- status = _PyTime_Init();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
status = _PyImport_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;