From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mellona.thatsmathematics.com (mellona.thatsmathematics.com [23.253.160.201]) by sourceware.org (Postfix) with ESMTPS id 0C0813858D28; Mon, 11 Dec 2023 19:24:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0C0813858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=thatsmathematics.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=thatsmathematics.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0C0813858D28 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=23.253.160.201 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702322670; cv=none; b=nEhL1qERp07u519YVGV/VU7Ax9gpTuLfWyfLUSHODU/kOCZwxL1Qi31qlyz092Jps/I5HaHJJqyKF2ovEPO/bkpr1xAHvK3+3BTCY0QQ3sTAMvLTgJ9VBN5wd71FJUoDUKk3utj8KvKMSETDHS33gm8B+HNqxtYJ7dss9t7Fsnc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702322670; c=relaxed/simple; bh=G4s42cFNSkHWH1Q10RFIpwAsg/LK6Z9RAr9UphDKBs0=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=IXu2omgzRgKqwJJAwk1QCvFgVouscFW00dEHgJY6NkvmEW3UyDM+cRxq6KGpHmFJV50Wz5fP/7oYv1EMdulE8YRZkgPC9uwBHAI8IVRK00uv2dkuP1ZqobPFuvaOBW5EcUSxLHr6Ldb7/1dsQALOpx/691nYam4FHO+7L2yqv78= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=thatsmathematics.com; s=condor; t=1702322668; bh=G4s42cFNSkHWH1Q10RFIpwAsg/LK6Z9RAr9UphDKBs0=; h=Date:From:To:cc:Subject:In-Reply-To:References:From; b=UCBzeiWl3+Od2OrbRgC92CoMM/zZnzkPQMgsvJg5QB+pXEwVk61qJeUfVCz/GVWeT xtPRopMfz0XvqtELmn68M0JTsB0f6lEgTRocUXnUBYdTB9E/x6KD2Y6LWcNPXPxU3z f6Bohn4ZwEdKHBrw3/dCBa/h44ToNLKfEWkX/kAnrendotkOeyMBFFHLnjIXiMJ1qk bPPC01YDW5FFZP3E8BFdws7AdAN0c7yNN1OYwgl/wjWc5E+3sy+NDZvWzId2OiJgbj AO73H19l0TBPoEAHG9ROYvhLGNtC4I7QrD/usK7KDDtEMEAJMiDdIGkhRhlt+wb0iz 4zE4aUmgfg4ZQ== Received: from moneta.lan (c-67-177-244-133.hsd1.co.comcast.net [67.177.244.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mellona.thatsmathematics.com (Postfix) with ESMTPSA id C6E8C1E8A3D; Mon, 11 Dec 2023 19:24:27 +0000 (UTC) Date: Mon, 11 Dec 2023 12:24:25 -0700 (MST) From: Nate Eldredge To: jwakely@redhat.com cc: trodgers@redhat.com, gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Subject: Re: [PATCH 1/2] libstdc++: Atomic wait/notify ABI stabilization In-Reply-To: <88357210-2f36-4711-1b2b-0b4185810e7c@thatsmathematics.com> Message-ID: References: <88357210-2f36-4711-1b2b-0b4185810e7c@thatsmathematics.com> MIME-Version: 1.0 Content-Type: text/plain; format=flowed; charset=US-ASCII X-Spam-Status: No, score=0.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_BARRACUDACENTRAL,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Mon, 11 Dec 2023, Nate Eldredge wrote: > To fix, we need something like `__args._M_old = __val;` inside the loop in > __atomic_wait_address(), so that we always wait on the exact value that the > predicate __pred() rejected. Again, there are similar instances in > atomic_timed_wait.h. Thinking through this, there's another problem. The main loop in __atomic_wait_address() would then be: while (!__pred(__val)) { __args._M_old = __val; __detail::__wait_impl(__wait_addr, &__args); __val = __vfn(); } The idea being that we only call __wait_impl to wait on a value that the predicate said was unacceptable. But looking for instance at its caller __atomic_semaphore::_M_acquire() in bits/semaphore_base.h, the predicate passed in is _S_do_try_acquire(), whose code is: _S_do_try_acquire(__detail::__platform_wait_t* __counter, __detail::__platform_wait_t __old) noexcept { if (__old == 0) return false; return __atomic_impl::compare_exchange_strong(__counter, __old, __old - 1, memory_order::acquire, memory_order::relaxed); } It returns false if the value passed in was unacceptable (i.e. zero), *or* if it was nonzero (let's say 1) but the compare_exchange failed because another thread swooped in and modified the semaphore counter. In that latter case, __atomic_wait_address() would pass 1 to __wait_impl(), which is likewise bad. If the counter is externally changed back to 1 just before we call __platform_wait (that's the futex call), we would go to sleep waiting on a semaphore that is already available: deadlock. I guess there's a couple ways to fix it. You could have the "predicate" callback instead return a tri-state value: "all done, stop waiting" (like current true), "value passed is not acceptable" (like current false), and "value was acceptable but something else went wrong". Only the second case should result in calling __wait_impl(). In the third case, __atomic_wait_address() should just reload the value (using __vfn()) and loop again. Or, make the callback __pred() a pure predicate that only tests its input value for acceptability, without any other side effects. Then have __atomic_wait_address() simply return as soon as __pred(__val) returns true. It would be up to the caller to actually decrement the semaphore or whatever, and to call __atomic_wait_address() again if this fails. In that case, __atomic_wait_address should probably return the final value that was read, so the caller can immediately do something like a compare-exchange using it, and not have to do an additional load and predicate test. Or, make __pred() a pure predicate as before, and give __atomic_wait_address yet one more callback function argument, call it __taker(), whose job is to acquire the semaphore etc, and have __atomic_wait_address call it after __pred(__val) returns true. -- Nate Eldredge nate@thatsmathematics.com