Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/817382/?format=api
{ "id": 817382, "url": "http://patchwork.ozlabs.org/api/patches/817382/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20170922081728.32508-3-mac@mcrowe.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170922081728.32508-3-mac@mcrowe.com>", "list_archive_url": null, "date": "2017-09-22T08:17:26", "name": "[RFC,2/4] libstdc++ futex: Support waiting on std::chrono::steady_clock directly", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "4e63c555c931d26c8394471832097074188f2355", "submitter": { "id": 66786, "url": "http://patchwork.ozlabs.org/api/people/66786/?format=api", "name": "Mike Crowe", "email": "mac@mcrowe.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20170922081728.32508-3-mac@mcrowe.com/mbox/", "series": [ { "id": 4567, "url": "http://patchwork.ozlabs.org/api/series/4567/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=4567", "date": "2017-09-22T08:17:24", "name": "Make std::future::wait_* use std::chrono::steady_clock when required", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/4567/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/817382/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/817382/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-return-462758-incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "mailing list gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org\n\t(client-ip=209.132.180.131; helo=sourceware.org;\n\tenvelope-from=gcc-patches-return-462758-incoming=patchwork.ozlabs.org@gcc.gnu.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dkim=pass (1024-bit key;\n\tunprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org\n\theader.b=\"lf/FHcLR\"; dkim-atps=neutral", "sourceware.org; auth=none" ], "Received": [ "from sourceware.org (server1.sourceware.org [209.132.180.131])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xz5y41cWGz9s9Y\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 22 Sep 2017 18:20:11 +1000 (AEST)", "(qmail 28689 invoked by alias); 22 Sep 2017 08:18:29 -0000", "(qmail 27018 invoked by uid 89); 22 Sep 2017 08:18:25 -0000", "from relay101a.appriver.com (HELO relay.appriver.com)\n\t(207.97.230.14) by sourceware.org\n\t(qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP;\n\tFri, 22 Sep 2017 08:18:22 +0000", "from [213.210.30.29] (HELO elite.brightsign) by relay.appriver.com\n\t(CommuniGate Pro SMTP 6.1.7) with ESMTPS id 201294880;\n\tFri, 22 Sep 2017 04:18:20 -0400", "from chuckie.brightsign ([fd44:d8b8:cab5:cb01::19]\n\thelo=chuckie)\tby elite.brightsign with esmtp (Exim\n\t4.89)\t(envelope-from <mcrowe@brightsign.biz>)\tid\n\t1dvJAB-000B0J-TC; Fri, 22 Sep 2017 09:18:19 +0100", "from mac by chuckie with local (Exim 4.89)\t(envelope-from\n\t<mcrowe@brightsign.biz>)\tid 1dvJAB-0008Ts-Sd;\n\tFri, 22 Sep 2017 09:18:19 +0100" ], "DomainKey-Signature": "a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:from\n\t:to:cc:subject:date:message-id:in-reply-to:references; q=dns; s=\n\tdefault; b=gEZMk6DUiwblGwlNPyMS2+HGE7gY55tjGcUX/xyJd/GBnIpOlupUW\n\th06U/fIcIO9KH7Dsoy5SERTdQYXASgAZkfw8iWqLuB20A1q+srnSykYVc3/YgRZK\n\t7rOo4nBDPEb2b7N8mquNEs6IULOSGdHc4ILq3ZjkLULLnzR2CWxXnM=", "DKIM-Signature": "v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id\n\t:list-unsubscribe:list-archive:list-post:list-help:sender:from\n\t:to:cc:subject:date:message-id:in-reply-to:references; s=\n\tdefault; bh=yzwr5c7qXgP0+rQhgqRbBGcg7nY=; b=lf/FHcLRCQwA48qhe4SM\n\tk5ygq+9t3v7OocItxmj13h/9djm4DpfEA1P0nn4B6XOoab+Fsd+0+YnL/C8xwk6/\n\tGfQauzGLECGTKWyTtU20iY20gHoLuWqO4WPJ3GDgKpLK6zsl2XVc2WUfoyHMkQYa\n\ts5ajsaQGvH3ZTPFGiDyX1Lg=", "Mailing-List": "contact gcc-patches-help@gcc.gnu.org; run by ezmlm", "Precedence": "bulk", "List-Id": "<gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<mailto:gcc-patches-unsubscribe-incoming=patchwork.ozlabs.org@gcc.gnu.org>", "List-Archive": "<http://gcc.gnu.org/ml/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-help@gcc.gnu.org>", "Sender": "gcc-patches-owner@gcc.gnu.org", "X-Virus-Found": "No", "X-Spam-SWARE-Status": "No, score=-26.6 required=5.0 tests=BAYES_00, GIT_PATCH_0,\n\tGIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3,\n\tKAM_LAZY_DOMAIN_SECURITY,\n\tRCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=", "X-Spam-User": "qpsmtpd, 2 recipients", "X-HELO": "relay.appriver.com", "X-Note": [ "This Email was scanned by AppRiver SecureTide", "SecureTide Build: 7/20/2017 1:24:22 PM UTC (2.6.20.0)", "Filtered by 10.238.11.161", "ICH-CT/SI:0-1052/SG:1 9/22/2017 4:17:36 AM", "TCH-CT/SI:0-23/SG:1 9/22/2017 4:17:36 AM", "Spam Tests Failed:", "User Rule Hits:", "Global Rule Hits: G281 G282 G283 G284 G288 G289 G418", "Encrypt Rule Hits:", "Mail Class: VALID", "Headers Injected" ], "X-Note-AR-ScanTimeLocal": "09/22/2017 4:18:20 AM", "X-Policy": [ "brightsign.biz - brightsign.biz", "brightsign.biz - brightsign.biz", "brightsign.biz - brightsign.biz" ], "X-Primary": "mcrowe@brightsign.biz", "X-Virus-Scan": "V-", "X-Note-SnifferID": "0", "X-GBUdb-Analysis": "0, 213.210.30.29, Ugly c=0.530451 p=-0.883721 Source Normal", "X-Signature-Violations": "0-0-0-16321-c", "X-Country-Path": "->->United Kingdom->United States", "X-Note-Sending-IP": "213.210.30.29", "X-Note-Reverse-DNS": "elite.brightsigndigital.co.uk", "X-Note-Return-Path": "mcrowe@brightsign.biz", "From": "Mike Crowe <mac@mcrowe.com>", "To": "libstdc++@gcc.gnu.org,\tgcc-patches@gcc.gnu.org", "Cc": "Mike Crowe <mac@mcrowe.com>", "Subject": "[RFC PATCH 2/4] libstdc++ futex: Support waiting on\n\tstd::chrono::steady_clock directly", "Date": "Fri, 22 Sep 2017 09:17:26 +0100", "Message-Id": "<20170922081728.32508-3-mac@mcrowe.com>", "In-Reply-To": "<20170922081728.32508-1-mac@mcrowe.com>", "References": "<20170922081728.32508-1-mac@mcrowe.com>" }, "content": "The user-visible effect of this change is for std::future::wait_until\nto use CLOCK_MONOTONIC when passed a timeout of\nstd::chrono::steady_clock::time_point type. This makes it immune to\nany changes made to the system clock CLOCK_REALTIME.\n\nAdd an overload of __atomic_futex_unsigned::_M_load_and_text_until_impl\nthat accepts a std::chrono::steady_clock, and correctly passes this through\nto __atomic_futex_unsigned_base::_M_futex_wait_until_steady which uses\nCLOCK_MONOTONIC for the timeout within the futex system call. These\nfunctions are mostly just copies of the std::chrono::system_clock versions\nwith small tweaks.\n\nPrior to this commit, a std::chrono::steady timeout would be converted via\nstd::chrono::system_clock which risks reducing or increasing the timeout if\nsomeone changes CLOCK_REALTIME whilst the wait is happening. (The commit\nimmediately prior to this one increases the window of opportunity for that\nfrom a short period during the calculation of a relative timeout, to the\nentire duration of the wait.)\n\nI believe that I've added this functionality in a way that it doesn't break\nABI compatibility, but that has made it more verbose and less type safe. I\nbelieve that it would be better to maintain the timeout as an instance of\nthe correct clock type all the way down to a single _M_futex_wait_until\nfunction with an overload for each clock. The current scheme of separating\nout the seconds and nanoseconds early risks accidentally calling the wait\nfunction for the wrong clock. Unfortunately, doing this would break code\nthat compiled against the old header.\n---\n libstdc++-v3/include/bits/atomic_futex.h | 67 +++++++++++++++++++++++++++++++-\n libstdc++-v3/src/c++11/futex.cc | 33 ++++++++++++++++\n 2 files changed, 99 insertions(+), 1 deletion(-)", "diff": "diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h\nindex afcfeb7720d..c2b3df03592 100644\n--- a/libstdc++-v3/include/bits/atomic_futex.h\n+++ b/libstdc++-v3/include/bits/atomic_futex.h\n@@ -52,11 +52,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n #if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1\n struct __atomic_futex_unsigned_base\n {\n- // Returns false iff a timeout occurred.\n+ // __s and __ns are measured against CLOCK_REALTIME. Returns false\n+ // iff a timeout occurred.\n bool\n _M_futex_wait_until(unsigned *__addr, unsigned __val, bool __has_timeout,\n \tchrono::seconds __s, chrono::nanoseconds __ns);\n \n+ // __s and __ns are measured against CLOCK_MONOTONIC. Returns\n+ // false iff a timeout occurred.\n+ bool\n+ _M_futex_wait_until_steady(unsigned *__addr, unsigned __val, bool __has_timeout,\n+\tchrono::seconds __s, chrono::nanoseconds __ns);\n+\n // This can be executed after the object has been destroyed.\n static void _M_futex_notify_all(unsigned* __addr);\n };\n@@ -86,6 +93,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n // value if equal is false.\n // The assumed value is the caller's assumption about the current value\n // when making the call.\n+ // __s and __ns are measured against CLOCK_REALTIME.\n unsigned\n _M_load_and_test_until(unsigned __assumed, unsigned __operand,\n \tbool __equal, memory_order __mo, bool __has_timeout,\n@@ -110,6 +118,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \t}\n }\n \n+ // If a timeout occurs, returns a current value after the timeout;\n+ // otherwise, returns the operand's value if equal is true or a different\n+ // value if equal is false.\n+ // The assumed value is the caller's assumption about the current value\n+ // when making the call.\n+ // __s and __ns are measured against CLOCK_MONOTONIC.\n+ unsigned\n+ _M_load_and_test_until_steady(unsigned __assumed, unsigned __operand,\n+\tbool __equal, memory_order __mo, bool __has_timeout,\n+\tchrono::seconds __s, chrono::nanoseconds __ns)\n+ {\n+ for (;;)\n+\t{\n+\t // Don't bother checking the value again because we expect the caller\n+\t // to have done it recently.\n+\t // memory_order_relaxed is sufficient because we can rely on just the\n+\t // modification order (store_notify uses an atomic RMW operation too),\n+\t // and the futex syscalls synchronize between themselves.\n+\t _M_data.fetch_or(_Waiter_bit, memory_order_relaxed);\n+\t bool __ret = _M_futex_wait_until_steady((unsigned*)(void*)&_M_data,\n+\t\t\t\t\t __assumed | _Waiter_bit,\n+\t\t\t\t\t __has_timeout, __s, __ns);\n+\t // Fetch the current value after waiting (clears _Waiter_bit).\n+\t __assumed = _M_load(__mo);\n+\t if (!__ret || ((__operand == __assumed) == __equal))\n+\t return __assumed;\n+\t // TODO adapt wait time\n+\t}\n+ }\n+\n // Returns the operand's value if equal is true or a different value if\n // equal is false.\n // The assumed value is the caller's assumption about the current value\n@@ -140,6 +178,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \t true, __s.time_since_epoch(), __ns);\n }\n \n+ template<typename _Dur>\n+ unsigned\n+ _M_load_and_test_until_impl(unsigned __assumed, unsigned __operand,\n+\tbool __equal, memory_order __mo,\n+\tconst chrono::time_point<std::chrono::steady_clock, _Dur>& __atime)\n+ {\n+ auto __s = chrono::time_point_cast<chrono::seconds>(__atime);\n+ auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);\n+ // XXX correct?\n+ return _M_load_and_test_until_steady(__assumed, __operand, __equal, __mo,\n+\t true, __s.time_since_epoch(), __ns);\n+ }\n+\n public:\n \n _GLIBCXX_ALWAYS_INLINE unsigned\n@@ -200,6 +251,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n return (__i & ~_Waiter_bit) == __val;\n }\n \n+ // Returns false iff a timeout occurred.\n+ template<typename _Duration>\n+ _GLIBCXX_ALWAYS_INLINE bool\n+ _M_load_when_equal_until(unsigned __val, memory_order __mo,\n+\tconst chrono::time_point<std::chrono::steady_clock, _Duration>& __atime)\n+ {\n+ unsigned __i = _M_load(__mo);\n+ if ((__i & ~_Waiter_bit) == __val)\n+\treturn true;\n+ // TODO Spin-wait first. Ignore effect on timeout.\n+ __i = _M_load_and_test_until_impl(__i, __val, true, __mo, __atime);\n+ return (__i & ~_Waiter_bit) == __val;\n+ }\n+\n _GLIBCXX_ALWAYS_INLINE void\n _M_store_notify_all(unsigned __val, memory_order __mo)\n {\ndiff --git a/libstdc++-v3/src/c++11/futex.cc b/libstdc++-v3/src/c++11/futex.cc\nindex 217aeefe005..fc2dcd7ff99 100644\n--- a/libstdc++-v3/src/c++11/futex.cc\n+++ b/libstdc++-v3/src/c++11/futex.cc\n@@ -36,6 +36,7 @@\n // Constants for the wait/wake futex syscall operations\n const unsigned futex_wait_op = 0;\n const unsigned futex_wait_bitset_op = 9;\n+const unsigned futex_clock_monotonic_flag = 0;\n const unsigned futex_clock_realtime_flag = 256;\n const unsigned futex_bitset_match_any = ~0;\n const unsigned futex_wake_op = 1;\n@@ -75,6 +76,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n }\n }\n \n+ bool\n+ __atomic_futex_unsigned_base::_M_futex_wait_until_steady(unsigned *__addr,\n+ unsigned __val,\n+ bool __has_timeout, chrono::seconds __s, chrono::nanoseconds __ns)\n+ {\n+ if (!__has_timeout)\n+ {\n+\t// Ignore whether we actually succeeded to block because at worst,\n+\t// we will fall back to spin-waiting. The only thing we could do\n+\t// here on errors is abort.\n+\tint ret __attribute__((unused));\n+\tret = syscall (SYS_futex, __addr, futex_wait_op, __val, nullptr);\n+\t_GLIBCXX_DEBUG_ASSERT(ret == 0 || errno == EINTR || errno == EAGAIN);\n+\treturn true;\n+ }\n+ else\n+ {\n+\tstruct timespec rt;\n+\trt.tv_sec = __s.count();\n+\trt.tv_nsec = __ns.count();\n+\n+\tif (syscall (SYS_futex, __addr, futex_wait_bitset_op | futex_clock_monotonic_flag, __val, &rt, nullptr, futex_bitset_match_any) == -1)\n+\t {\n+\t _GLIBCXX_DEBUG_ASSERT(errno == EINTR || errno == EAGAIN\n+\t\t\t\t || errno == ETIMEDOUT);\n+\t if (errno == ETIMEDOUT)\n+\t return false;\n+\t }\n+\treturn true;\n+ }\n+ }\n+\n void\n __atomic_futex_unsigned_base::_M_futex_notify_all(unsigned* __addr)\n {\n", "prefixes": [ "RFC", "2/4" ] }