From patchwork Fri Jul 20 16:49:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Crowe X-Patchwork-Id: 947126 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-482000-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mcrowe.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="FIxdc47R"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=brightsigninfo.onmicrosoft.com header.i=@brightsigninfo.onmicrosoft.com header.b="k2P3aI6p"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41XH250mgmz9s7Q for ; Sat, 21 Jul 2018 02:50:36 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=Q/Gmg+J0gFvYdXjb JijtoPTRf5IT8LHYHBxa1XvU4lsLJIr2tKmA0//MBtHOVrMl4WVTRuiQXgEeEPwz zDcTpCgu/J4DdGMKu/rDE6ZknZ1fvpzxazoOARQivWG7Jp9l6E8IwXhxvsyECrlO n9UuHcQ5icFKkwtVOMtWtBW1y50= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=vXHVvDnGHGsLHhv7f+W6FK hsBmU=; b=FIxdc47R8ytkUyDWCe1dPwuFzVvVOcRPD5c8wdf/1Rn5P6LuCPYrL0 tN6PEkCiFMYLUBIHdmFcxAS2I/L+DwubPVjYMchoJUr3f8ctivwbhlahfl9w9vwe vQy5Sxfs9RySN40O3iOLA5c1vj0VzkZPbpDWKTKey7985tnFhdxkQ= Received: (qmail 122840 invoked by alias); 20 Jul 2018 16:50:11 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 122768 invoked by uid 89); 20 Jul 2018 16:50:10 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_INFOUSMEBIZ, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=2cc, 2.cc, UD:2.cc X-HELO: NAM02-SN1-obe.outbound.protection.outlook.com Received: from mail-sn1nam02on0119.outbound.protection.outlook.com (HELO NAM02-SN1-obe.outbound.protection.outlook.com) (104.47.36.119) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 20 Jul 2018 16:50:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brightsigninfo.onmicrosoft.com; s=selector1-brightsign-biz; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+s6sn34TPs1vly/OXgimaOtNvQCxXfK1fwAQN+acl/g=; b=k2P3aI6pr3LghShEpihb79ktBJD27JaFK/vUMHcEGVWd8QbgoPEcYQrpU92APDJv88y4j8fMULJurIDCfqYOYIj0HZfu6SQYhEkUvgSLwy/yRrp7hYbNFHs/Ba8mfDTeymRS6KI1kMucIZaraC7KJjDSWofHlPKAzT87rk4n0nk= Received: from BN6PR08CA0055.namprd08.prod.outlook.com (2603:10b6:404:b9::17) by BLUPR08MB486.namprd08.prod.outlook.com (2a01:111:e400:887::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.973.16; Fri, 20 Jul 2018 16:50:03 +0000 Received: from SN1NAM04FT021.eop-NAM04.prod.protection.outlook.com (2a01:111:f400:7e4c::200) by BN6PR08CA0055.outlook.office365.com (2603:10b6:404:b9::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.973.16 via Frontend Transport; Fri, 20 Jul 2018 16:50:03 +0000 Authentication-Results: spf=pass (sender IP is 213.210.30.29) smtp.mailfrom=brightsign.biz; gcc.gnu.org; dkim=none (message not signed) header.d=none; gcc.gnu.org; dmarc=none action=none header.from=mcrowe.com; Received-SPF: Pass (protection.outlook.com: domain of brightsign.biz designates 213.210.30.29 as permitted sender) receiver=protection.outlook.com; client-ip=213.210.30.29; helo=elite.brightsign; Received: from elite.brightsign (213.210.30.29) by SN1NAM04FT021.mail.protection.outlook.com (10.152.88.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.20.973.14 via Frontend Transport; Fri, 20 Jul 2018 16:50:01 +0000 Received: from chuckie.brightsign ([fd44:d8b8:cab5:cb01::19] helo=chuckie) by elite.brightsign with esmtp (Exim 4.89) (envelope-from ) id 1fgYbQ-000Cgi-2p; Fri, 20 Jul 2018 17:50:00 +0100 Received: from mac by chuckie with local (Exim 4.89) (envelope-from ) id 1fgYbQ-0007pr-20; Fri, 20 Jul 2018 17:50:00 +0100 From: Mike Crowe To: , CC: Jonathan Wakely , Mike Crowe Subject: [PATCH 1/2] condition_variable: Report early wakeup of wait_until as no_timeout Date: Fri, 20 Jul 2018 17:49:47 +0100 Message-ID: MIME-Version: 1.0 As currently implemented, condition_variable always ultimately waits against std::chrono::system_clock. This clock can be changed in arbitrary ways by the user which may result in us waking up too early or too late when measured against the caller-supplied clock. We can't (yet) do much about waking up too late[1], but if we wake up too early we must return cv_status::no_timeout to indicate a spurious wakeup rather than incorrectly returning cv_status::timeout. [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861 --- libstdc++-v3/ChangeLog | 7 +++++++ libstdc++-v3/include/std/condition_variable | 8 +++++++- libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) base-commit: 3052e4ec519e4f5456ab63f4954ae098524316ce -- git-series 0.9.1 BrightSign considers your privacy to be very important. The emails you send to us will be protected and secured. Furthermore, we will only use your email and contact information for the reasons you sent them to us and for tracking how effectively we respond to your requests. diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c9cd62a..4657af7 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2018-07-20 Mike Crowe + * include/std/condition_variable (wait_until): Only report timeout + if we really have timed out when measured against the + caller-supplied clock. + * testsuite/30_threads/condition_variable/members/2.cc: Add test + case to confirm above behaviour. + 2018-07-20 Jonathan Wakely PR libstdc++/86595 diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable index 84863a1..a2d146a 100644 --- a/libstdc++-v3/include/std/condition_variable +++ b/libstdc++-v3/include/std/condition_variable @@ -116,7 +116,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const auto __delta = __atime - __c_entry; const auto __s_atime = __s_entry + __delta; - return __wait_until_impl(__lock, __s_atime); + // We might get a timeout when measured against __clock_t but + // we need to check against the caller-supplied clock to tell + // whether we should return a timeout. + if (__wait_until_impl(__lock, __s_atime) == cv_status::timeout) + return _Clock::now() < __atime ? cv_status::no_timeout : cv_status::timeout; + else + return cv_status::no_timeout; } template diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc index 6f9724b..16850a4 100644 --- a/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc +++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc @@ -52,8 +52,60 @@ void test01() } } +struct slow_clock +{ + using rep = std::chrono::system_clock::rep; + using period = std::chrono::system_clock::period; + using duration = std::chrono::system_clock::duration; + using time_point = std::chrono::time_point; + static constexpr bool is_steady = false; + + static time_point now() + { + auto real = std::chrono::system_clock::now(); + return time_point{real.time_since_epoch() / 3}; + } +}; + + +void test01_alternate_clock() +{ + try + { + std::condition_variable c1; + std::mutex m; + std::unique_lock l(m); + auto const expire = slow_clock::now() + std::chrono::seconds(1); + + while (slow_clock::now() < expire) + { + auto const result = c1.wait_until(l, expire); + + // If wait_until returns before the timeout has expired when + // measured against the supplied clock, then wait_until must + // return no_timeout. + if (slow_clock::now() < expire) + VERIFY(result == std::cv_status::no_timeout); + + // If wait_until returns timeout then the timeout must have + // expired. + if (result == std::cv_status::timeout) + VERIFY(slow_clock::now() >= expire); + } + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } +} + int main() { test01(); + test01_alternate_clock(); return 0; }