]>
Commit | Line | Data |
---|---|---|
fb211fce | 1 | // { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-rtems* *-*-darwin* } } |
8868286e | 2 | // { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* } } |
3 | // { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } } | |
fb211fce | 4 | // { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-rtems* *-*-darwin* } } |
8e9bca59 | 5 | // { dg-require-cstdint "" } |
6 | // { dg-require-gthreads "" } | |
7 | // { dg-require-debug-mode "" } | |
f1717362 | 8 | // Copyright (C) 2010-2016 Free Software Foundation, Inc. |
8e9bca59 | 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. | |
36 | size_t | |
37 | get_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 | ||
47 | void 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 | ||
96 | int main() | |
97 | { | |
98 | test01(); | |
99 | return 0; | |
100 | } |