diff --git a/Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst b/Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst new file mode 100644 index 00000000000000..ce0eb59a16f8d8 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2020-07-21-02-29-17.bpo-41100.kFtqID.rst @@ -0,0 +1 @@ +Add runtime checks for MACOSX_DEPLOYMENT_TARGET=10.10 so backwards compatible python can be built with latest Xcode \ No newline at end of file diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index efd99544f5a997..277d8b93325c62 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -79,6 +79,26 @@ corresponding Unix manual entries for more information on calls."); # include #endif /* HAVE_SYS_STAT_H */ +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_UTIMENSAT_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_FUTIMENS_RUNTIME __builtin_available(macos 10.13, ios 11, tvos 11, watchos 4, *) +#define HAVE_PREADV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) +#define HAVE_PWRITEV_RUNTIME __builtin_available(macos 10.16, ios 14, tvos 14, watchos 7, *) +#else +#define HAVE_UTIMENSAT_RUNTIME 1 +#define HAVE_FUTIMENS_RUNTIME 1 +#define HAVE_PREADV_RUNTIME 1 +#define HAVE_PWRITEV_RUNTIME 1 +#endif + +#if defined(__APPLE__) && TARGET_OS_OSX && __arm64__ && __clang__ +#pragma clang diagnostic ignored "-Wunguarded-availability-new" +#endif + #ifdef HAVE_SYS_WAIT_H # include // WNOHANG #endif @@ -4826,9 +4846,13 @@ static int utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) { #ifdef HAVE_UTIMENSAT - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); + if (HAVE_UTIMENSAT_RUNTIME) { + int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; + UTIME_TO_TIMESPEC; + return utimensat(dir_fd, path, time, flags); + } else { + return -1; + } #elif defined(HAVE_FUTIMESAT) UTIME_TO_TIMEVAL; /* @@ -4852,12 +4876,15 @@ static int utime_fd(utime_t *ut, int fd) { #ifdef HAVE_FUTIMENS - UTIME_TO_TIMESPEC; - return futimens(fd, time); -#else - UTIME_TO_TIMEVAL; - return futimes(fd, time); + if (HAVE_FUTIMENS_RUNTIME) { + UTIME_TO_TIMESPEC; + return futimens(fd, time); + } else #endif + { + UTIME_TO_TIMEVAL; + return futimes(fd, time); + } } #define PATH_UTIME_HAVE_FD 1 @@ -4875,12 +4902,15 @@ static int utime_nofollow_symlinks(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); -#else - UTIME_TO_TIMEVAL; - return lutimes(path, time); + if (HAVE_FUTIMENS_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); + } else #endif + { + UTIME_TO_TIMEVAL; + return lutimes(path, time); + } } #endif @@ -4891,9 +4921,12 @@ static int utime_default(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) + if (HAVE_UTIMENSAT_RUNTIME) { + UTIME_TO_TIMESPEC; + return utimensat(DEFAULT_DIR_FD, path, time, 0); + } +#endif +#if defined(HAVE_UTIMES) UTIME_TO_TIMEVAL; return utimes(path, time); #elif defined(HAVE_UTIME_H) @@ -5092,6 +5125,10 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS + int have_utimensat_runtime = 0; + if (HAVE_UTIMENSAT_RUNTIME) + have_utimensat_runtime = 1; + #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = utime_nofollow_symlinks(&utime, path->narrow); @@ -5099,7 +5136,7 @@ os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, #endif #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) + if (have_utimensat_runtime && ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))) result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); else #endif @@ -9255,59 +9292,64 @@ os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ { - Py_ssize_t cnt, n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + if (HAVE_PREADV_RUNTIME) { + Py_ssize_t cnt, n; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "preadv2() arg 2 must be a sequence"); - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "preadv2() arg 2 must be a sequence"); + return -1; + } - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } -#ifndef HAVE_PREADV2 - if(flags != 0) { - argument_unavailable_error("preadv2", "flags"); - return -1; - } -#endif + #ifndef HAVE_PREADV2 + if(flags != 0) { + argument_unavailable_error("preadv2", "flags"); + return -1; + } + #endif - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { - return -1; - } -#ifdef HAVE_PREADV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - n = preadv(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#endif + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { + return -1; + } + #ifdef HAVE_PREADV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + n = preadv(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #endif - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) { - posix_error(); + iov_cleanup(iov, buf, cnt); + if (n < 0) { + if (!async_err) { + posix_error(); + } + return -1; } + + return n; + } else { + PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); return -1; } - - return n; } #endif /* HAVE_PREADV */ @@ -9850,60 +9892,65 @@ os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { - Py_ssize_t cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; + if (HAVE_PWRITEV_RUNTIME) { + Py_ssize_t cnt; + Py_ssize_t result; + int async_err = 0; + struct iovec *iov; + Py_buffer *buf; - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "pwritev() arg 2 must be a sequence"); - return -1; - } + if (!PySequence_Check(buffers)) { + PyErr_SetString(PyExc_TypeError, + "pwritev() arg 2 must be a sequence"); + return -1; + } - cnt = PySequence_Size(buffers); - if (cnt < 0) { - return -1; - } + cnt = PySequence_Size(buffers); + if (cnt < 0) { + return -1; + } -#ifndef HAVE_PWRITEV2 - if(flags != 0) { - argument_unavailable_error("pwritev2", "flags"); - return -1; - } -#endif + #ifndef HAVE_PWRITEV2 + if(flags != 0) { + argument_unavailable_error("pwritev2", "flags"); + return -1; + } + #endif - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } -#ifdef HAVE_PWRITEV2 - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev2(fd, iov, cnt, offset, flags); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#else - do { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - result = pwritev(fd, iov, cnt, offset); - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); -#endif + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + #ifdef HAVE_PWRITEV2 + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev2(fd, iov, cnt, offset, flags); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #else + do { + Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH + result = pwritev(fd, iov, cnt, offset); + _Py_END_SUPPRESS_IPH + Py_END_ALLOW_THREADS + } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + #endif - iov_cleanup(iov, buf, cnt); - if (result < 0) { - if (!async_err) { - posix_error(); + iov_cleanup(iov, buf, cnt); + if (result < 0) { + if (!async_err) { + posix_error(); + } + return -1; } + + return result; + } else { + PyErr_SetString(PyExc_NotImplementedError, "preadv is not available"); return -1; } - - return result; } #endif /* HAVE_PWRITEV */ diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 8a4d149befb52a..96e2486f27da27 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -51,6 +51,20 @@ #define _Py_tzname tzname #endif +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_SETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#define HAVE_CLOCK_GETRES_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#define HAVE_CLOCK_SETTIME_RUNTIME 1 +#define HAVE_CLOCK_GETRES_RUNTIME 1 +#endif + #define SEC_TO_NS (1000 * 1000 * 1000) /* Forward declarations */ @@ -152,25 +166,30 @@ perf_counter(_Py_clock_info_t *info) static PyObject * time_clock_gettime(PyObject *self, PyObject *args) { - int ret; - struct timespec tp; - -#if defined(_AIX) && (SIZEOF_LONG == 8) - long clk_id; - if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { -#else - int clk_id; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { -#endif - return NULL; - } + if (HAVE_CLOCK_GETTIME_RUNTIME) { + int ret; + struct timespec tp; + + #if defined(_AIX) && (SIZEOF_LONG == 8) + long clk_id; + if (!PyArg_ParseTuple(args, "l:clock_gettime", &clk_id)) { + #else + int clk_id; + if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + #endif + return NULL; + } - ret = clock_gettime((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_gettime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return NULL; } - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } PyDoc_STRVAR(clock_gettime_doc, @@ -181,24 +200,29 @@ Return the time of the specified clock clk_id."); static PyObject * time_clock_gettime_ns(PyObject *self, PyObject *args) { - int ret; - int clk_id; - struct timespec ts; - _PyTime_t t; + if (HAVE_CLOCK_GETTIME_RUNTIME) { + int ret; + int clk_id; + struct timespec ts; + _PyTime_t t; - if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) { + return NULL; + } - ret = clock_gettime((clockid_t)clk_id, &ts); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (_PyTime_FromTimespec(&t, &ts) < 0) { + ret = clock_gettime((clockid_t)clk_id, &ts); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + if (_PyTime_FromTimespec(&t, &ts) < 0) { + return NULL; + } + return _PyTime_AsNanosecondsObject(t); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return NULL; } - return _PyTime_AsNanosecondsObject(t); } PyDoc_STRVAR(clock_gettime_ns_doc, @@ -211,27 +235,32 @@ Return the time of the specified clock clk_id as nanoseconds."); static PyObject * time_clock_settime(PyObject *self, PyObject *args) { - int clk_id; - PyObject *obj; - _PyTime_t t; - struct timespec tp; - int ret; - - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) - return NULL; + if (HAVE_CLOCK_SETTIME_RUNTIME) { + int clk_id; + PyObject *obj; + _PyTime_t t; + struct timespec tp; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) + return NULL; - if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0) - return NULL; + if (_PyTime_FromSecondsObject(&t, obj, _PyTime_ROUND_FLOOR) < 0) + return NULL; - if (_PyTime_AsTimespec(t, &tp) == -1) - return NULL; + if (_PyTime_AsTimespec(t, &tp) == -1) + return NULL; - ret = clock_settime((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_settime((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_settime is not available"); return NULL; } - Py_RETURN_NONE; } PyDoc_STRVAR(clock_settime_doc, @@ -242,29 +271,34 @@ Set the time of the specified clock clk_id."); static PyObject * time_clock_settime_ns(PyObject *self, PyObject *args) { - int clk_id; - PyObject *obj; - _PyTime_t t; - struct timespec ts; - int ret; - - if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) { - return NULL; - } + if (HAVE_CLOCK_SETTIME_RUNTIME) { + int clk_id; + PyObject *obj; + _PyTime_t t; + struct timespec ts; + int ret; + + if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) { + return NULL; + } - if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { - return NULL; - } - if (_PyTime_AsTimespec(t, &ts) == -1) { - return NULL; - } + if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { + return NULL; + } + if (_PyTime_AsTimespec(t, &ts) == -1) { + return NULL; + } - ret = clock_settime((clockid_t)clk_id, &ts); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_settime((clockid_t)clk_id, &ts); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_settime is not available"); return NULL; } - Py_RETURN_NONE; } PyDoc_STRVAR(clock_settime_ns_doc, @@ -277,20 +311,25 @@ Set the time of the specified clock clk_id with nanoseconds."); static PyObject * time_clock_getres(PyObject *self, PyObject *args) { - int ret; - int clk_id; - struct timespec tp; + if (HAVE_CLOCK_GETRES_RUNTIME) { + int ret; + int clk_id; + struct timespec tp; - if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) - return NULL; + if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id)) + return NULL; - ret = clock_getres((clockid_t)clk_id, &tp); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); + ret = clock_getres((clockid_t)clk_id, &tp); + if (ret != 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_getres is not available"); return NULL; } - - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } PyDoc_STRVAR(clock_getres_doc, @@ -1170,23 +1209,25 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"; #endif - if (clock_gettime(clk_id, &ts) == 0) { - if (info) { - struct timespec res; - info->implementation = function; - info->monotonic = 1; - info->adjustable = 0; - if (clock_getres(clk_id, &res)) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; + if (HAVE_CLOCK_GETTIME_RUNTIME) { + if (clock_gettime(clk_id, &ts) == 0) { + if (info) { + struct timespec res; + info->implementation = function; + info->monotonic = 1; + info->adjustable = 0; + if (clock_getres(clk_id, &res)) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; } - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; - } - if (_PyTime_FromTimespec(tp, &ts) < 0) { - return -1; + if (_PyTime_FromTimespec(tp, &ts) < 0) { + return -1; + } + return 0; } - return 0; } #endif @@ -1309,6 +1350,7 @@ sum of the kernel and user-space CPU time."); #if defined(MS_WINDOWS) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME 1 static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1349,6 +1391,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(_AIX) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME 1 static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1373,6 +1416,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) #define HAVE_THREAD_TIME +#define HAVE_THREAD_TIME_RUNTIME HAVE_CLOCK_GETTIME_RUNTIME static int _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -1380,10 +1424,16 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) const clockid_t clk_id = CLOCK_THREAD_CPUTIME_ID; const char *function = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)"; - if (clock_gettime(clk_id, &ts)) { - PyErr_SetFromErrno(PyExc_OSError); + if (HAVE_CLOCK_GETTIME_RUNTIME) { + if (clock_gettime(clk_id, &ts)) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + } else { + PyErr_SetString(PyExc_NotImplementedError, "clock_gettime is not available"); return -1; } + if (info) { struct timespec res; info->implementation = function; @@ -1694,17 +1744,6 @@ init_timezone(PyObject *m) static PyMethodDef time_methods[] = { {"time", time_time, METH_NOARGS, time_doc}, {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc}, -#ifdef HAVE_CLOCK_GETTIME - {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, - {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, -#endif -#ifdef HAVE_CLOCK_SETTIME - {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, - {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc}, -#endif -#ifdef HAVE_CLOCK_GETRES - {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, -#endif #ifdef HAVE_PTHREAD_GETCPUCLOCKID {"pthread_getcpuclockid", time_pthread_getcpuclockid, METH_VARARGS, pthread_getcpuclockid_doc}, #endif @@ -1727,13 +1766,24 @@ static PyMethodDef time_methods[] = { {"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc}, {"process_time", time_process_time, METH_NOARGS, process_time_doc}, {"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc}, + {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, + {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc}, + {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, +#ifdef HAVE_CLOCK_GETTIME + {"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc}, + {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc}, +#endif +#ifdef HAVE_CLOCK_SETTIME + {"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc}, + {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc}, +#endif #ifdef HAVE_THREAD_TIME {"thread_time", time_thread_time, METH_NOARGS, thread_time_doc}, {"thread_time_ns", time_thread_time_ns, METH_NOARGS, thread_time_ns_doc}, #endif - {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, - {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc}, - {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, +#ifdef HAVE_CLOCK_GETRES + {"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc}, +#endif {NULL, NULL} /* sentinel */ }; @@ -1874,9 +1924,49 @@ static struct PyModuleDef timemodule = { NULL }; +static void +delete_method(const char *name) +{ + for (int i = 0; time_methods[i].ml_name != NULL; i++) { + if ( 0==strcmp(time_methods[i].ml_name, name)) { + for (int j = i; time_methods[j].ml_name != NULL; j++) { + time_methods[j] = time_methods[j+1]; + } + break; + } + } +} + PyMODINIT_FUNC PyInit_time(void) { + #ifdef HAVE_CLOCK_GETTIME + if (HAVE_CLOCK_GETTIME_RUNTIME) {} else { + delete_method("clock_gettime"); + delete_method("clock_gettime_ns"); + } + #endif + + #ifdef HAVE_CLOCK_SETTIME + if (HAVE_CLOCK_SETTIME_RUNTIME) {} else { + delete_method("clock_settime"); + delete_method("clock_settime_ns"); + } + #endif + + #ifdef HAVE_CLOCK_GETRES + if (HAVE_CLOCK_GETRES_RUNTIME) {} else { + delete_method("clock_getres"); + } + #endif + + #ifdef HAVE_THREAD_TIME + if (HAVE_THREAD_TIME_RUNTIME) {} else { + delete_method("thread_time"); + delete_method("thread_time_ns"); + } + #endif + return PyModuleDef_Init(&timemodule); } diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 47369305ee88e9..0dc86e2cf9f5f4 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -31,6 +31,16 @@ int _Py_HashSecret_Initialized = 0; static int _Py_HashSecret_Initialized = 0; #endif +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !(TARGET_OS_OSX && __arm64__) +#define HAVE_GETENTROPY_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_GETENTROPY_RUNTIME 1 +#endif + #ifdef MS_WINDOWS static HCRYPTPROV hCryptProv = 0; @@ -225,13 +235,19 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise) Py_ssize_t len = Py_MIN(size, 256); int res; - if (raise) { - Py_BEGIN_ALLOW_THREADS - res = getentropy(buffer, len); - Py_END_ALLOW_THREADS - } - else { - res = getentropy(buffer, len); + + if (HAVE_GETENTROPY_RUNTIME) { + if (raise) { + Py_BEGIN_ALLOW_THREADS + res = getentropy(buffer, len); + Py_END_ALLOW_THREADS + } + else { + res = getentropy(buffer, len); + } + } else { + getentropy_works = 0; + return 0; } if (res < 0) { diff --git a/Python/pytime.c b/Python/pytime.c index b121b432f428d7..9757e5abc8e8a1 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -7,6 +7,12 @@ #include /* mach_absolute_time(), mach_timebase_info() */ #endif +#if defined(__APPLE__) && HAVE_BUILTIN_AVAILABLE && !defined(__arm64__) +#define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macos 10.12, ios 10, tvos 10, watchos 3, *) +#else +#define HAVE_CLOCK_GETTIME_RUNTIME 1 +#endif + #define _PyTime_check_mul_overflow(a, b) \ (assert(b > 0), \ (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \ @@ -683,59 +689,58 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) #else /* MS_WINDOWS */ int err; -#ifdef HAVE_CLOCK_GETTIME - struct timespec ts; -#else - struct timeval tv; -#endif assert(info == NULL || raise); #ifdef HAVE_CLOCK_GETTIME - err = clock_gettime(CLOCK_REALTIME, &ts); - if (err) { - if (raise) { - PyErr_SetFromErrno(PyExc_OSError); + if (HAVE_CLOCK_GETTIME_RUNTIME) { + struct timespec ts; + err = clock_gettime(CLOCK_REALTIME, &ts); + if (err) { + if (raise) { + PyErr_SetFromErrno(PyExc_OSError); + } + return -1; + } + if (pytime_fromtimespec(tp, &ts, raise) < 0) { + return -1; } - return -1; - } - if (pytime_fromtimespec(tp, &ts, raise) < 0) { - return -1; - } - if (info) { - struct timespec res; - info->implementation = "clock_gettime(CLOCK_REALTIME)"; - info->monotonic = 0; - info->adjustable = 1; - if (clock_getres(CLOCK_REALTIME, &res) == 0) { - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + if (info) { + struct timespec res; + info->implementation = "clock_gettime(CLOCK_REALTIME)"; + info->monotonic = 0; + info->adjustable = 1; + if (clock_getres(CLOCK_REALTIME, &res) == 0) { + info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + } + else { + info->resolution = 1e-9; + } } - else { - info->resolution = 1e-9; + } else +#endif /* HAVE_CLOCK_GETTIME */ + { + struct timeval tv; + /* test gettimeofday() */ + err = gettimeofday(&tv, (struct timezone *)NULL); + if (err) { + if (raise) { + PyErr_SetFromErrno(PyExc_OSError); + } + return -1; } - } -#else /* HAVE_CLOCK_GETTIME */ - - /* test gettimeofday() */ - err = gettimeofday(&tv, (struct timezone *)NULL); - if (err) { - if (raise) { - PyErr_SetFromErrno(PyExc_OSError); + if (pytime_fromtimeval(tp, &tv, raise) < 0) { + return -1; } - return -1; - } - if (pytime_fromtimeval(tp, &tv, raise) < 0) { - return -1; - } - if (info) { - info->implementation = "gettimeofday()"; - info->resolution = 1e-6; - info->monotonic = 0; - info->adjustable = 1; + if (info) { + info->implementation = "gettimeofday()"; + info->resolution = 1e-6; + info->monotonic = 0; + info->adjustable = 1; + } } -#endif /* !HAVE_CLOCK_GETTIME */ #endif /* !MS_WINDOWS */ return 0; } diff --git a/configure b/configure index 5024860ca4395a..ebdd1cfeed261d 100755 --- a/configure +++ b/configure @@ -12190,6 +12190,41 @@ $as_echo "yes" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if the compiler supports __builtin_available" >&5 +$as_echo_n "checking to see if the compiler supports __builtin_available... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<_ACEOF +#define HAVE_BUILTIN_AVAILABLE 1 +_ACEOF + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + for ac_prog in true do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.ac b/configure.ac index 5a3e340aa3e72b..6df35971dec8d3 100644 --- a/configure.ac +++ b/configure.ac @@ -3825,6 +3825,19 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ AC_MSG_RESULT(yes) ]) +AC_MSG_CHECKING([to see if the compiler supports __builtin_available]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[]],[[ + if (__builtin_available(macOS 10.8, iOS 5.0, *)) {} + ]]) + ],[ + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED(HAVE_BUILTIN_AVAILABLE, 1, + [Define to 1 if the compiler supports __builtin_available]) + ],[ + AC_MSG_RESULT([no]) +]) + dnl check for true AC_CHECK_PROGS(TRUE, true, /bin/true) diff --git a/pyconfig.h.in b/pyconfig.h.in index bc906a869b623e..e602a4a9f4bdc1 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -115,6 +115,9 @@ /* Define if `unsetenv` does not return an int. */ #undef HAVE_BROKEN_UNSETENV +#undef HAVE_BUILTIN_AVAILABLE +/* Define to 1 if the compiler supports __builtin_available */ + /* Has builtin atomics */ #undef HAVE_BUILTIN_ATOMIC