From patchwork Mon Apr 4 17:11:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 89668 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 0FC4CB6EF0 for ; Tue, 5 Apr 2011 03:12:00 +1000 (EST) Received: (qmail 24542 invoked by alias); 4 Apr 2011 17:11:53 -0000 Received: (qmail 24529 invoked by uid 22791); 4 Apr 2011 17:11:50 -0000 X-SWARE-Spam-Status: No, hits=-6.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 04 Apr 2011 17:11:40 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p34HBdfG028163 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 4 Apr 2011 13:11:39 -0400 Received: from houston.quesejoda.com (vpn-232-7.phx2.redhat.com [10.3.232.7]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p34HBcIv020692; Mon, 4 Apr 2011 13:11:39 -0400 Message-ID: <4D99FBCA.4030604@redhat.com> Date: Mon, 04 Apr 2011 12:11:38 -0500 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110307 Fedora/3.1.9-0.39.b3pre.fc14 Lightning/1.0b3pre Thunderbird/3.1.9 MIME-Version: 1.0 To: gcc-patches , Benjamin De Kosnik , Jason Merrill Subject: [cxx-mem-model] C++ atomic tests (synchronized and relaxed) 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 [Jason, Benjamin: It'd be nice to get input from y'all, since you are more intimately involved with the standard. I want to make sure I'm not misunderstanding things.] Hopefully a non-controversial feature, but given my luck, I doubt it :). Here are two additional tests to verify our atomic compliance. 1. Synchronized atomic load/stores: atomic_int atomi; long double j; Thread 1: j = 13.0; atomi.store(1); Thread 2: atomi.load(); As I understand it, the load/stores have acquire/release semantics, so the store to must happen before the store to . Currently, this is not the case on x86-64, because GCC reorders the stores and the attached atomics-2.C test fails. We emit the following for thread 1: flds .LC0(%rip) movl $1, atomi(%rip) xorl %eax, %eax fstpt j(%rip) mfence Notice the store of *after* the store to . I consider this a bug and have put this on my laundry list. 2. Unsynchronized atomic load/stores. For the "memory_order_relaxed" directive, load/stores are not synchronized as the previous example, but stores to identical memory locations must be performed in modification order. For the following loop, I assume and test that the stores to x[] do not happen out of order: for (int i=0; i < SIZE; ++i) x[i].store(666, memory_order_relaxed); This is the test in the attached atomics-3.C. The test atomics-2.C fails on x86-64, but atomics-3.C passes. I would like input on my interpretation of the proposed memory model standard, and the sanity of my tests. I will be committing the attached tests if there are no issues today (with the tests, not the sanity of the model :)). Aldy Index: g++.dg/memmodel/atomics-2.C =================================================================== --- g++.dg/memmodel/atomics-2.C (revision 0) +++ g++.dg/memmodel/atomics-2.C (revision 0) @@ -0,0 +1,51 @@ +/* { dg-do link } */ +/* { dg-options "-std=c++0x -O2" } */ +/* { dg-final { memmodel-gdb-test } } */ + +using namespace std; + +#include +#include +#include +#include "memmodel.h" + +atomic_int atomi; + +/* Non-atomic. Use a type wide enough to possibly coerce GCC into + moving things around. */ +long double j; + + +/* Test that an atomic store synchronizes with an atomic load. + + In this case, test that the store to happens-before the atomic + store to . Make sure the compiler does not reorder the + stores. */ +main() +{ + j = 13.0; + atomi.store(1); + memmodel_done(); +} + +void memmodel_other_threads() +{ +} + +/* Verify that side-effects before an atomic store are correctly + synchronized with the an atomic load to the same location. */ +int memmodel_step_verify() +{ + if (atomi.load() == 1 && j != 13.0) + { + printf ("FAIL: invalid synchronization for atomic load/store.\n"); + return 1; + } + return 0; +} + + +int memmodel_final_verify() +{ + return memmodel_step_verify(); +} Index: g++.dg/memmodel/atomics-3.C =================================================================== --- g++.dg/memmodel/atomics-3.C (revision 0) +++ g++.dg/memmodel/atomics-3.C (revision 0) @@ -0,0 +1,55 @@ +/* { dg-do link } */ +/* { dg-options "-std=c++0x -O2" } */ +/* { dg-final { memmodel-gdb-test } } */ + +using namespace std; + +#include +#include +#include +#include "memmodel.h" + +#define SIZE 64 + +atomic_int x[SIZE]; // initially all 0's. +int i; + + +/* Test that atomic stores to the same location are performed in + modification order, despite the use of "memory_order_relaxed". */ +main() +{ + /* These stores must be done consecutively. */ + for (int i=0; i < SIZE; ++i) + x[i].store(666, memory_order_relaxed); + memmodel_done(); +} + +void memmodel_other_threads() +{ +} + +/* Verify that the stores were done in order, that is-- once you get + to an uninitialized value, every subsequent slot is empty as + well. */ +int memmodel_step_verify() +{ + bool seen0 = false; + for (i = 0; i < SIZE; ++i) + { + if (x[i].load() == 0) + seen0 = true; + else if (seen0) + { + printf ("FAIL: out-of-order modification\n"); + return 1; + } + } + return 0; +} + + +int memmodel_final_verify() +{ + return memmodel_step_verify(); +}