145
|
1 /* Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
111
|
2 Contributed by Richard Henderson <rth@redhat.com>.
|
|
3
|
|
4 This file is part of the GNU Transactional Memory Library (libitm).
|
|
5
|
|
6 Libitm is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 3 of the License, or
|
|
9 (at your option) any later version.
|
|
10
|
|
11 Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
14 more details.
|
|
15
|
|
16 Under Section 7 of GPL version 3, you are granted additional
|
|
17 permissions described in the GCC Runtime Library Exception, version
|
|
18 3.1, as published by the Free Software Foundation.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License and
|
|
21 a copy of the GCC Runtime Library Exception along with this program;
|
|
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
23 <http://www.gnu.org/licenses/>. */
|
|
24
|
|
25 #include "libitm_i.h"
|
|
26
|
|
27 using namespace GTM;
|
|
28
|
|
29 struct clone_entry
|
|
30 {
|
|
31 void *orig, *clone;
|
|
32 };
|
|
33
|
|
34 struct clone_table
|
|
35 {
|
|
36 clone_entry *table;
|
|
37 size_t size;
|
|
38 clone_table *next;
|
|
39 };
|
|
40
|
|
41 static clone_table *all_tables;
|
|
42
|
|
43 static void *
|
|
44 find_clone (void *ptr)
|
|
45 {
|
|
46 clone_table *table;
|
|
47
|
|
48 for (table = all_tables; table ; table = table->next)
|
|
49 {
|
|
50 clone_entry *t = table->table;
|
|
51 size_t lo = 0, hi = table->size, i;
|
|
52
|
|
53 /* Quick test for whether PTR is present in this table. */
|
|
54 if (ptr < t[0].orig || ptr > t[hi - 1].orig)
|
|
55 continue;
|
|
56
|
|
57 /* Otherwise binary search. */
|
|
58 while (lo < hi)
|
|
59 {
|
|
60 i = (lo + hi) / 2;
|
|
61 if (ptr < t[i].orig)
|
|
62 hi = i;
|
|
63 else if (ptr > t[i].orig)
|
|
64 lo = i + 1;
|
|
65 else
|
|
66 return t[i].clone;
|
|
67 }
|
|
68
|
|
69 /* Given the quick test above, if we don't find the entry in
|
|
70 this table then it doesn't exist. */
|
|
71 break;
|
|
72 }
|
|
73
|
|
74 return NULL;
|
|
75 }
|
|
76
|
|
77
|
|
78 void * ITM_REGPARM
|
|
79 _ITM_getTMCloneOrIrrevocable (void *ptr)
|
|
80 {
|
|
81 void *ret = find_clone (ptr);
|
|
82 if (ret)
|
|
83 return ret;
|
|
84
|
|
85 gtm_thr()->serialirr_mode ();
|
|
86
|
|
87 return ptr;
|
|
88 }
|
|
89
|
|
90 void * ITM_REGPARM
|
|
91 _ITM_getTMCloneSafe (void *ptr)
|
|
92 {
|
|
93 void *ret = find_clone (ptr);
|
|
94 if (ret == NULL)
|
|
95 abort ();
|
|
96 return ret;
|
|
97 }
|
|
98
|
|
99 static int
|
|
100 clone_entry_compare (const void *a, const void *b)
|
|
101 {
|
|
102 const clone_entry *aa = (const clone_entry *)a;
|
|
103 const clone_entry *bb = (const clone_entry *)b;
|
|
104
|
|
105 if (aa->orig < bb->orig)
|
|
106 return -1;
|
|
107 else if (aa->orig > bb->orig)
|
|
108 return 1;
|
|
109 else
|
|
110 return 0;
|
|
111 }
|
|
112
|
|
113 namespace {
|
|
114
|
|
115 // Within find_clone, we know that we are inside a transaction. Because
|
|
116 // of that, we have already synchronized with serial_lock. By taking the
|
|
117 // serial_lock for write, we exclude all transactions while we make this
|
|
118 // change to the clone tables, without having to synchronize on a separate
|
|
119 // lock. Do be careful not to attempt a recursive write lock.
|
|
120
|
|
121 class ExcludeTransaction
|
|
122 {
|
|
123 bool do_lock;
|
|
124
|
|
125 public:
|
|
126 ExcludeTransaction()
|
|
127 {
|
|
128 gtm_thread *tx = gtm_thr();
|
|
129 do_lock = !(tx && (tx->state & gtm_thread::STATE_SERIAL));
|
|
130
|
|
131 if (do_lock)
|
|
132 gtm_thread::serial_lock.write_lock ();
|
|
133 }
|
|
134
|
|
135 ~ExcludeTransaction()
|
|
136 {
|
|
137 if (do_lock)
|
|
138 gtm_thread::serial_lock.write_unlock ();
|
|
139 }
|
|
140 };
|
|
141
|
|
142 } // end anon namespace
|
|
143
|
|
144
|
|
145 void
|
|
146 _ITM_registerTMCloneTable (void *xent, size_t size)
|
|
147 {
|
|
148 clone_entry *ent = static_cast<clone_entry *>(xent);
|
|
149 clone_table *table;
|
|
150
|
|
151 table = (clone_table *) xmalloc (sizeof (clone_table));
|
|
152 table->table = ent;
|
|
153 table->size = size;
|
|
154
|
|
155 qsort (ent, size, sizeof (clone_entry), clone_entry_compare);
|
|
156
|
|
157 // Hold the serial_lock while we update the ALL_TABLES datastructure.
|
|
158 {
|
|
159 ExcludeTransaction exclude;
|
|
160 table->next = all_tables;
|
|
161 all_tables = table;
|
|
162 }
|
|
163 }
|
|
164
|
|
165 void
|
|
166 _ITM_deregisterTMCloneTable (void *xent)
|
|
167 {
|
|
168 clone_entry *ent = static_cast<clone_entry *>(xent);
|
|
169 clone_table *tab;
|
|
170
|
|
171 // Hold the serial_lock while we update the ALL_TABLES datastructure.
|
|
172 {
|
|
173 ExcludeTransaction exclude;
|
|
174 clone_table **pprev;
|
|
175
|
|
176 for (pprev = &all_tables;
|
|
177 tab = *pprev, tab->table != ent;
|
|
178 pprev = &tab->next)
|
|
179 continue;
|
|
180 *pprev = tab->next;
|
|
181 }
|
|
182
|
|
183 free (tab);
|
|
184 }
|