123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /* Copyright (C) 2009-2015 Free Software Foundation, Inc.
- Contributed by Richard Henderson <rth@redhat.com>.
- This file is part of the GNU Transactional Memory Library (libitm).
- Libitm is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- #include "libitm_i.h"
- using namespace GTM;
- struct clone_entry
- {
- void *orig, *clone;
- };
- struct clone_table
- {
- clone_entry *table;
- size_t size;
- clone_table *next;
- };
- static clone_table *all_tables;
- static void *
- find_clone (void *ptr)
- {
- clone_table *table;
- for (table = all_tables; table ; table = table->next)
- {
- clone_entry *t = table->table;
- size_t lo = 0, hi = table->size, i;
- /* Quick test for whether PTR is present in this table. */
- if (ptr < t[0].orig || ptr > t[hi - 1].orig)
- continue;
- /* Otherwise binary search. */
- while (lo < hi)
- {
- i = (lo + hi) / 2;
- if (ptr < t[i].orig)
- hi = i;
- else if (ptr > t[i].orig)
- lo = i + 1;
- else
- return t[i].clone;
- }
- /* Given the quick test above, if we don't find the entry in
- this table then it doesn't exist. */
- break;
- }
- return NULL;
- }
- void * ITM_REGPARM
- _ITM_getTMCloneOrIrrevocable (void *ptr)
- {
- void *ret = find_clone (ptr);
- if (ret)
- return ret;
- gtm_thr()->serialirr_mode ();
- return ptr;
- }
- void * ITM_REGPARM
- _ITM_getTMCloneSafe (void *ptr)
- {
- void *ret = find_clone (ptr);
- if (ret == NULL)
- abort ();
- return ret;
- }
- static int
- clone_entry_compare (const void *a, const void *b)
- {
- const clone_entry *aa = (const clone_entry *)a;
- const clone_entry *bb = (const clone_entry *)b;
- if (aa->orig < bb->orig)
- return -1;
- else if (aa->orig > bb->orig)
- return 1;
- else
- return 0;
- }
- namespace {
- // Within find_clone, we know that we are inside a transaction. Because
- // of that, we have already synchronized with serial_lock. By taking the
- // serial_lock for write, we exclude all transactions while we make this
- // change to the clone tables, without having to synchronize on a separate
- // lock. Do be careful not to attempt a recursive write lock.
- class ExcludeTransaction
- {
- bool do_lock;
- public:
- ExcludeTransaction()
- {
- gtm_thread *tx = gtm_thr();
- do_lock = !(tx && (tx->state & gtm_thread::STATE_SERIAL));
- if (do_lock)
- gtm_thread::serial_lock.write_lock ();
- }
- ~ExcludeTransaction()
- {
- if (do_lock)
- gtm_thread::serial_lock.write_unlock ();
- }
- };
- } // end anon namespace
- void
- _ITM_registerTMCloneTable (void *xent, size_t size)
- {
- clone_entry *ent = static_cast<clone_entry *>(xent);
- clone_table *table;
- table = (clone_table *) xmalloc (sizeof (clone_table));
- table->table = ent;
- table->size = size;
- qsort (ent, size, sizeof (clone_entry), clone_entry_compare);
- // Hold the serial_lock while we update the ALL_TABLES datastructure.
- {
- ExcludeTransaction exclude;
- table->next = all_tables;
- all_tables = table;
- }
- }
- void
- _ITM_deregisterTMCloneTable (void *xent)
- {
- clone_entry *ent = static_cast<clone_entry *>(xent);
- clone_table *tab;
- // Hold the serial_lock while we update the ALL_TABLES datastructure.
- {
- ExcludeTransaction exclude;
- clone_table **pprev;
- for (pprev = &all_tables;
- tab = *pprev, tab->table != ent;
- pprev = &tab->next)
- continue;
- *pprev = tab->next;
- }
- free (tab);
- }
|