You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@stdcxx.apache.org by "Travis Vitek (JIRA)" <ji...@apache.org> on 2008/03/04 01:24:50 UTC

[jira] Commented: (STDCXX-449) [ITC/Linux] std::string Write -> Read data-race errors

    [ https://issues.apache.org/jira/browse/STDCXX-449?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12574801#action_12574801 ] 

Travis Vitek commented on STDCXX-449:
-------------------------------------

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.