From 1bc5aee63eb72b341f506ad058502cd0361f0d10 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Tue, 25 Mar 2014 22:37:19 -0700 Subject: Initial checkin of GCC 4.9.0 from trunk (r208799). Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba --- gcc-4.9/libitm/clone.cc | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 gcc-4.9/libitm/clone.cc (limited to 'gcc-4.9/libitm/clone.cc') diff --git a/gcc-4.9/libitm/clone.cc b/gcc-4.9/libitm/clone.cc new file mode 100644 index 000000000..b7ad9a707 --- /dev/null +++ b/gcc-4.9/libitm/clone.cc @@ -0,0 +1,184 @@ +/* Copyright (C) 2009-2014 Free Software Foundation, Inc. + Contributed by Richard Henderson . + + 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 + . */ + +#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(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(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); +} -- cgit v1.2.3