1// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* } } 2// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } } 3// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } } 4// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } } 5// { dg-require-cstdint "" } 6// { dg-require-gthreads "" } 7// { dg-require-debug-mode "" } 8// Copyright (C) 2010-2015 Free Software Foundation, Inc. 9// 10// This file is part of the GNU ISO C++ Library. This library is free 11// software; you can redistribute it and/or modify it under the 12// terms of the GNU General Public License as published by the 13// Free Software Foundation; either version 3, or (at your option) 14// any later version. 15// 16// This library is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License along 22// with this library; see the file COPYING3. If not see 23// <http://www.gnu.org/licenses/>. 24// 25 26// This test check for potential deadlock when swaping sequences in debug 27// mode as it requires acquiring 2 locks at the same time. 28 29#include <vector> 30#include <thread> 31#include <functional> 32#include <testsuite_hooks.h> 33 34// The following function mimic the one in src/debug.cc to associate a mutex 35// to a given safe sequence instance. 36size_t 37get_index(std::vector<int>& v) 38{ 39 const size_t mask = 0xf; 40 // We have to check the address of the internal safe sequence that starts 41 // after the normal vector memory footprint that is to say a 3 pointers 42 // offset: 43 void* __address = reinterpret_cast<char*>(&v) + 3 * sizeof(void*); 44 return std::_Hash_impl::hash(__address) & mask; 45} 46 47void test01() 48{ 49 using namespace std; 50 bool test __attribute__((unused)) = true; 51 vector<int> v1, v2; 52 vector<shared_ptr<vector<int> > > vs; 53 vector<int> *pv3 = 0, *pv4 = 0; 54 const int nb_attempts = 100; 55 for (int i = 0; i != nb_attempts; ++i) 56 { 57 vs.push_back(shared_ptr<vector<int> >(new vector<int>())); 58 if (!pv3) 59 { 60 if (get_index(*vs.back()) == get_index(v1)) 61 pv3 = vs.back().get(); 62 } 63 else if (!pv4) 64 { 65 if (get_index(*vs.back()) == get_index(v2)) 66 { 67 pv4 = vs.back().get(); 68 break; 69 } 70 } 71 } 72 73 if (!pv3 || !pv4) 74 // Maybe an other time... 75 return; 76 77 vector<int> &v3 = *pv3, &v4 = *pv4; 78 79 // v1 and v3 shares the same mutex instance, like v2 and v4 80 // thread t1 lock v1 and v2 81 thread t1([&v1, &v2]() 82 { 83 for (int i = 0; i != 1000; ++i) 84 v1.swap(v2); 85 }); 86 // thread t2 lock v4 and v3 87 thread t2([&v3, &v4]() 88 { 89 for (int i = 0; i != 1000; ++i) 90 v4.swap(v3); 91 }); 92 t2.join(); 93 t1.join(); 94} 95 96int main() 97{ 98 test01(); 99 return 0; 100} 101