stdcxx-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Travis Vitek (JIRA)" <j...@apache.org>
Subject [jira] Issue Comment Edited: (STDCXX-449) [ITC/Linux] std::string Write -> Read data-race errors
Date Tue, 04 Mar 2008 16:59:40 GMT

    [ 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.


Mime
View raw message