[
https://issues.apache.org/jira/browse/STDCXX-449?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12574801#action_12574801
]
vitek edited comment on STDCXX-449 at 3/4/08 8:58 AM:
-------------------------------------------------------------
According to
[this|http://msdn2.microsoft.com/en-us/library/ms684122(VS.85).aspx]
{quote}
Simple reads and writes to properly-aligned 32-bit variables are atomic
operations. In other words, you will not end up with only one portion of the
variable updated; all bits are updated in an atomic fashion. However, access is
not guaranteed to be synchronized. If two threads are reading and writing from
the same variable, you cannot determine if one thread will perform its read
operation before the other performs its write operation.
Simple reads and writes to properly aligned 64-bit variables are atomic on
64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be
atomic on 32-bit Windows. Reads and writes to variables of other sizes are not
guaranteed to be atomic on any platform.
{quote}
The type of _C_ref is int, which is only 32-bits on a LLP64 systems. I
_believe_ that this is okay on EMT64/AMD64 systems because they are actually
32-bit architectures with 64-bit extensions, but I'm not absolutely sure. Need
to find out.
According to [this|http://www.linuxjournal.com/article/8211] there are similar
rules for other architectures...
{quote}
When it comes to how memory ordering works on different CPUs, there is good
news and bad news. The bad news is each CPU's memory ordering is a bit
different. The good news is you can count on a few things:
1. A given CPU always perceives its own memory operations as occurring in
program order. That is, memory-reordering issues arise only when a CPU is
observing other CPUs' memory operations.
2. An operation is reordered with a store only if the operation accesses a
different location than does the store.
3. Aligned simple loads and stores are atomic.
4. Linux-kernel synchronization primitives contain any needed memory barriers,
which is a good reason to use these primitives.
{quote}
That same page also says this
{quote}
However, code that uses standard synchronization primitives—spinlocks,
semaphores, RCU—should not need explicit memory barriers, because any required
barriers already are present in these primitives. Only tricky code that
bypasses these synchronization primitives needs barriers. It is important to
note that most atomic operations, for example, atomic_inc() and atomic_add(),
do not include any memory barriers.
{quote}
Assuming that the first two quotes are accurate, and the _C_refs member is
properly aligned and of the appropriate size on all platforms, we _should_ be
safe. Even if all of that works out, I don't feel good about it.
My initial inclination is to say that we need something to guard the read of
_C_refs. We need to make sure that all writes are flushed before we read the
current value. I was originally considering something like atomic_add(_C_refs,
0), assuming it would ensure that the returned value was consistent, but the
last quote leaves me a little unsure if that is sufficient.
was (Author: vitek):
According to
[this|http://msdn2.microsoft.com/en-us/library/ms684122(VS.85).aspx]
{quote}
Simple reads and writes to properly-aligned 32-bit variables are atomic
operations. In other words, you will not end up with only one portion of the
variable updated; all bits are updated in an atomic fashion. However, access is
not guaranteed to be synchronized. If two threads are reading and writing from
the same variable, you cannot determine if one thread will perform its read
operation before the other performs its write operation.
Simple reads and writes to properly aligned 64-bit variables are atomic on
64-bit Windows. Reads and writes to 64-bit values are not guaranteed to be
atomic on 32-bit Windows. Reads and writes to variables of other sizes are not
guaranteed to be atomic on any platform.
{quote}
The type of _C_ref is int, which is only 32-bits on a LLP64 systems. I
_believe_ that this is okay on EMT64/AMD64 systems because they are actually
32-bit architectures with 64-bit extensions, but I'm not absolutely sure. Need
to find out.
According to [this|http://www.linuxjournal.com/article/8211] there are similar
rules for other architectures...
{quote}
When it comes to how memory ordering works on different CPUs, there is good
news and bad news. The bad news is each CPU's memory ordering is a bit
different. The good news is you can count on a few things:
1. A given CPU always perceives its own memory operations as occurring in
program order. That is, memory-reordering issues arise only when a CPU is
observing other CPUs' memory operations.
2. An operation is reordered with a store only if the operation accesses a
different location than does the store.
3. Aligned simple loads and stores are atomic.
4. Linux-kernel synchronization primitives contain any needed memory barriers,
which is a good reason to use these primitives.
{quote}
That same page also says this
{quote}
However, code that uses standard synchronization primitives—spinlocks,
semaphores, RCU—should not need explicit memory barriers, because any required
barriers already are present in these primitives. Only tricky code that
bypasses these synchronization primitives needs barriers. It is important to
note that most atomic operations, for example, atomic_inc() and atomic_add(),
do not include any memory barriers.
{quote}
Assuming that the first two quotes are accurate, and the _C_refs member is
properly aligned and of the appropriate size on all platforms, we _should_ be
safe. Even if all of that works out, I don't feel good about it.
My initial inclination is to say that we need something to guard the read of
_C_refs. We need to make sure that all writes are flushed before we read the
current value. I was originally considering something like atomic_add(_C_refs,
0), assuming it would ensure that the returned value was consistent, but the
last quote leaves me a little unsure if that is sufficient.
Other hardware architectures may not work in this way. On these platforms, we
need a memory barrier to ensure that we are reading the most up-to-date value.
The member __rw_stringref::_C_refs is of type _int_, so it is
> [ITC/Linux] std::string Write -> Read data-race errors
> ------------------------------------------------------
>
> Key: STDCXX-449
> URL: https://issues.apache.org/jira/browse/STDCXX-449
> Project: C++ Standard Library
> Issue Type: Bug
> Components: 21. Strings
> Affects Versions: 4.1.2, 4.1.3, 4.1.4, 4.2.0
> Environment: Intel Thread Checker 3.1 on Red Hat Enterprise Linux AS
> release 4 (Nahant Update 4)
> Reporter: Martin Sebor
> Assignee: Travis Vitek
> Priority: Minor
> Fix For: 4.2.1
>
> Attachments: 21.string.cons.mt.itc-report.html
>
>
> Running the Intel Thread Checker on the string thread safety tests
> 21.string.cons.mt and 21.string.push_back.mt produces errors suggesting
> potential thread safety problems even though the tests run successfully to
> completion. See the text output below:
> {noformat}
> $ tcheck_cl -w 200 ./21.string.cons.mt --nloops=100 --nthreads=2
> Intel(R) Thread Checker 3.1 command line instrumentation driver (24400)
> Copyright (c) 2007 Intel Corporation. All rights reserved.
> Building project
> Running: /build/sebor/stdcxx-icc-9.1_042-15s/tests/21.string.cons.mt
> --nloops=100 --nthreads=2
> # INFO (S1) (10 lines):
> # TEXT:
> # COMPILER: Intel C++, __INTEL_COMPILER = 910, __INTEL_COMPILER_BUILD_DATE =
> 20060706, __EDG_VERSION__ = 306
> # ENVIRONMENT: i386 running linux-elf 2.4.20 with glibc 2.3
> # FILE: 21.string.cons.mt.cpp
> # COMPILED: Jun 13 2007, 13:00:49
> # COMMENT: thread safety
> ############################################################
> # CLAUSE: lib.string.cons
> # INFO (S1) (3 lines):
> # TEXT: testing std::string with 2 threads, 100 iterations each
> # CLAUSE: lib.string.cons
> # INFO (S1) (3 lines):
> # TEXT: testing std::wstring with 2 threads, 100 iterations each
> # CLAUSE: lib.string.cons
> # +-----------------------+----------+----------+----------+
> # | DIAGNOSTIC | ACTIVE | TOTAL | INACTIVE |
> # +-----------------------+----------+----------+----------+
> # | (S1) INFO | 3 | 3 | 0% |
> # | (S7) ASSERTION | 0 | 16 | 100% |
> # +-----------------------+----------+----------+----------+
> Application finished
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |ID |Short Description |Severity |Cou|Context[Best] |Description
>
> |1st Access[Best] |2nd Access[Best] |
> | | |Name |nt | |
>
> | | |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |1 |Write -> Read |Error |128|[21.string.cons.mt,|Memory read at
> "_strref.h":159 conflicts with a prior memory write at [21.string.cons.mt,
> |[21.string.cons.mt, |"_strref.h":159 |
> | |data-race | | |0xadf0] |0x3475f] (flow
> dependence)
> |0x3475f] | |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |2 |Read -> Write |Error |5 |[21.string.cons.mt,|Memory write
> at [21.string.cons.mt, 0x3475f] conflicts with a prior memory read at
> |"_strref.h":159 |[21.string.cons.mt, |
> | |data-race | | |0x34755]
> |"_strref.h":159 (anti dependence)
> | |0x3475f] |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |3 |Thread termination |Information|1 |Whole Program 1 |Thread
> termination at "thread.cpp":76 - includes stack allocation of 10.004 MB and
> use of |"thread.cpp":76 |"thread.cpp":76 |
> | | | | | |4.516 KB
>
> | | |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |4 |Thread termination |Information|1 |Whole Program 2 |Thread
> termination at "thread.cpp":76 - includes stack allocation of 10.004 MB and
> use of |"thread.cpp":76 |"thread.cpp":76 |
> | | | | | |4.516 KB
>
> | | |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |5 |Read -> Write |Error |7 |[21.string.cons.mt,|Memory write
> at [21.string.cons.mt, 0x3475f] conflicts with a prior memory read at
> |"_strref.h":159 |[21.string.cons.mt, |
> | |data-race | | |0x34755]
> |"_strref.h":159 (anti dependence)
> | |0x3475f] |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |6 |Thread termination |Information|1 |Whole Program 3 |Thread
> termination at "thread.cpp":76 - includes stack allocation of 10.004 MB and
> use of |"thread.cpp":76 |"thread.cpp":76 |
> | | | | | |4.516 KB
>
> | | |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |7 |Thread termination |Information|1 |Whole Program 4 |Thread
> termination at "thread.cpp":76 - includes stack allocation of 10.004 MB and
> use of |"thread.cpp":76 |"thread.cpp":76 |
> | | | | | |4.516 KB
>
> | | |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> |8 |Thread termination |Information|1 |Whole Program 5 |Thread
> termination at "21.string.cons.mt.cpp":237 - includes stack allocation of 10
> MB and |"21.string.cons.mt.c|"21.string.cons.mt.cpp|
> | | | | | |use of 8.578
> KB
> |pp":237 |":237 |
> ________________________________________________________________________________________________________________________________________________________________________________________________________
> {noformat}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.