c++config (_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE, [...]): Add.

2010-08-12  Kostya Serebryany <kcc@google.com>
	    Paolo Carlini  <paolo.carlini@oracle.com>

	* include/bits/c++config (_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE,
	_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER): Add.
	* src/ios_init.cc (ios_base::Init::~Init): Decorate with the
	latter.
	* include/tr1_impl/boost_sp_counted_base.h: Likewise.
	* include/ext/rc_string_base.h: Likewise.
	* include/bits/locale_classes.h: Likewise.
	* include/bits/basic_string.h: Likewise.
	* include/bits/ios_base.h: Likewise.
	* testsuite/27_io/ios_base/cons/assign_neg.cc: Adjust dg-error
	line number.
	* testsuite/27_io/ios_base/cons/copy_neg.cc: Likewise.
	* testsuite/ext/profile/mutex_extensions.cc: Likewise.

Co-Authored-By: Paolo Carlini <paolo.carlini@oracle.com>

From-SVN: r163210
This commit is contained in:
Kostya Serebryany 2010-08-12 22:56:59 +00:00 committed by Paolo Carlini
parent 644fa7acbd
commit be335b18a9
11 changed files with 101 additions and 13 deletions

View File

@ -1,3 +1,20 @@
2010-08-12 Kostya Serebryany <kcc@google.com>
Paolo Carlini <paolo.carlini@oracle.com>
* include/bits/c++config (_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE,
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER): Add.
* src/ios_init.cc (ios_base::Init::~Init): Decorate with the
latter.
* include/tr1_impl/boost_sp_counted_base.h: Likewise.
* include/ext/rc_string_base.h: Likewise.
* include/bits/locale_classes.h: Likewise.
* include/bits/basic_string.h: Likewise.
* include/bits/ios_base.h: Likewise.
* testsuite/27_io/ios_base/cons/assign_neg.cc: Adjust dg-error
line number.
* testsuite/27_io/ios_base/cons/copy_neg.cc: Likewise.
* testsuite/ext/profile/mutex_extensions.cc: Likewise.
2010-08-11 Paolo Carlini <paolo.carlini@oracle.com> 2010-08-11 Paolo Carlini <paolo.carlini@oracle.com>
* include/bits/hashtable.h (_Hashtable<>::erase(const key_type&)): * include/bits/hashtable.h (_Hashtable<>::erase(const key_type&)):

View File

@ -232,9 +232,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING #ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(this != &_S_empty_rep(), false)) if (__builtin_expect(this != &_S_empty_rep(), false))
#endif #endif
if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, {
-1) <= 0) // Be race-detector-friendly. For more info see bits/c++config.
_M_destroy(__a); _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount)
if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
-1) <= 0)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount)
_M_destroy(__a);
}
}
} // XXX MT } // XXX MT
void void

View File

@ -60,6 +60,35 @@
# define _GLIBCXX_DEPRECATED_ATTR # define _GLIBCXX_DEPRECATED_ATTR
#endif #endif
// Macros for race detectors.
// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and
// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain
// atomic (lock-free) synchronization to race detectors:
// the race detector will infer a happens-before arc from the former to the
// latter when they share the same argument pointer.
//
// The most frequent use case for these macros (and the only case in the
// current implementation of the library) is atomic reference counting:
// void _M_remove_reference()
// {
// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount)
// if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, -1) <= 0)
// {
// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount)
// _M_destroy(__a);
// }
// }
// The annotations in this example tell the race detector that all memory
// accesses occurred when the refcount was positive do not race with
// memory accesses which occurred after the refcount became zero.
#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE
# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A)
#endif
#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER
# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A)
#endif
// Macros for activating various namespace association modes. // Macros for activating various namespace association modes.
// _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG // _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
// _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL // _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL

View File

@ -474,7 +474,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
// 0 => OK to delete. // 0 => OK to delete.
int int
_M_remove_reference() _M_remove_reference()
{ return __gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1); } {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_refcount)
int __res = __gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1);
if (__res == 0)
{
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_refcount)
}
return __res;
}
}; };
_Callback_list* _M_callbacks; _Callback_list* _M_callbacks;
@ -962,4 +971,3 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
_GLIBCXX_END_NAMESPACE _GLIBCXX_END_NAMESPACE
#endif /* _IOS_BASE_H */ #endif /* _IOS_BASE_H */

View File

@ -402,8 +402,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
void void
_M_remove_reference() const throw() _M_remove_reference() const throw()
{ {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_refcount)
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1) == 1) if (__gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1) == 1)
{ {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_refcount)
__try __try
{ delete this; } { delete this; }
__catch(...) __catch(...)
@ -508,8 +511,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
void void
_M_remove_reference() throw() _M_remove_reference() throw()
{ {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_refcount)
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1) == 1) if (__gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1) == 1)
{ {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_refcount)
__try __try
{ delete this; } { delete this; }
__catch(...) __catch(...)

View File

@ -199,9 +199,16 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
void void
_M_dispose() _M_dispose()
{ {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_rep()->_M_info.
_M_refcount)
if (__exchange_and_add_dispatch(&_M_rep()->_M_info._M_refcount, if (__exchange_and_add_dispatch(&_M_rep()->_M_info._M_refcount,
-1) <= 0) -1) <= 0)
_M_rep()->_M_destroy(_M_get_allocator()); {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_rep()->_M_info.
_M_refcount)
_M_rep()->_M_destroy(_M_get_allocator());
}
} // XXX MT } // XXX MT
bool bool

View File

@ -1,6 +1,6 @@
// <tr1_impl/boost_sp_counted_base.h> -*- C++ -*- // <tr1_impl/boost_sp_counted_base.h> -*- C++ -*-
// Copyright (C) 2007, 2009 Free Software Foundation, Inc. // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
@ -139,8 +139,11 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
void void
_M_release() // nothrow _M_release() // nothrow
{ {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count)
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1) if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
{ {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count)
_M_dispose(); _M_dispose();
// There must be a memory barrier between dispose() and destroy() // There must be a memory barrier between dispose() and destroy()
// to ensure that the effects of dispose() are observed in the // to ensure that the effects of dispose() are observed in the
@ -152,9 +155,14 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
_GLIBCXX_WRITE_MEM_BARRIER; _GLIBCXX_WRITE_MEM_BARRIER;
} }
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count)
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
-1) == 1) -1) == 1)
_M_destroy(); {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count)
_M_destroy();
}
} }
} }
@ -165,8 +173,11 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
void void
_M_weak_release() // nothrow _M_weak_release() // nothrow
{ {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count)
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1) if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
{ {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count)
if (_Mutex_base<_Lp>::_S_need_barriers) if (_Mutex_base<_Lp>::_S_need_barriers)
{ {
// See _M_release(), // See _M_release(),

View File

@ -1,7 +1,7 @@
// Iostreams base classes -*- C++ -*- // Iostreams base classes -*- C++ -*-
// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
// 2006, 2007, 2008, 2009 // 2006, 2007, 2008, 2009, 2010
// Free Software Foundation, Inc. // Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
@ -122,8 +122,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
ios_base::Init::~Init() ios_base::Init::~Init()
{ {
// Be race-detector-friendly. For more info see bits/c++config.
_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_S_refcount)
if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, -1) == 2) if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, -1) == 2)
{ {
_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_S_refcount)
// Catch any exceptions thrown by basic_ostream::flush() // Catch any exceptions thrown by basic_ostream::flush()
__try __try
{ {

View File

@ -34,5 +34,5 @@ void test01()
} }
// { dg-error "synthesized" "" { target *-*-* } 33 } // { dg-error "synthesized" "" { target *-*-* } 33 }
// { dg-error "within this context" "" { target *-*-* } 26 } // { dg-error "within this context" "" { target *-*-* } 26 }
// { dg-error "is private" "" { target *-*-* } 779 } // { dg-error "is private" "" { target *-*-* } 788 }
// { dg-error "operator=" "" { target *-*-* } 0 } // { dg-error "operator=" "" { target *-*-* } 0 }

View File

@ -34,5 +34,5 @@ void test02()
} }
// { dg-error "within this context" "" { target *-*-* } 26 } // { dg-error "within this context" "" { target *-*-* } 26 }
// { dg-error "synthesized" "" { target *-*-* } 33 } // { dg-error "synthesized" "" { target *-*-* } 33 }
// { dg-error "is private" "" { target *-*-* } 776 } // { dg-error "is private" "" { target *-*-* } 785 }
// { dg-error "copy constructor" "" { target *-*-* } 0 } // { dg-error "copy constructor" "" { target *-*-* } 0 }

View File

@ -3,7 +3,7 @@
// -*- C++ -*- // -*- C++ -*-
// Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc. // Copyright (C) 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
@ -22,4 +22,4 @@
#include <vector> #include <vector>
// { dg-error "Cannot use -D_GLIBCXX_PROFILE with " "" { target *-*-* } 167 } // { dg-error "Cannot use -D_GLIBCXX_PROFILE with " "" { target *-*-* } 196 }