diff options
| author | Dan Albert <danalbert@google.com> | 2015-06-17 11:09:54 -0700 |
|---|---|---|
| committer | Dan Albert <danalbert@google.com> | 2015-06-17 14:15:22 -0700 |
| commit | f378ebf14df0952eae870c9865bab8326aa8f137 (patch) | |
| tree | 31794503eb2a8c64ea5f313b93100f1163afcffb /gcc-4.7/libitm/retry.cc | |
| parent | 2c58169824949d3a597d9fa81931e001ef9b1bd0 (diff) | |
| download | toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.gz toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.bz2 toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.zip | |
Delete old versions of GCC.
Change-Id: I710f125d905290e1024cbd67f48299861790c66c
Diffstat (limited to 'gcc-4.7/libitm/retry.cc')
| -rw-r--r-- | gcc-4.7/libitm/retry.cc | 325 |
1 files changed, 0 insertions, 325 deletions
diff --git a/gcc-4.7/libitm/retry.cc b/gcc-4.7/libitm/retry.cc deleted file mode 100644 index 660bf5244..000000000 --- a/gcc-4.7/libitm/retry.cc +++ /dev/null @@ -1,325 +0,0 @@ -/* Copyright (C) 2008, 2009, 2011 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 <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "libitm_i.h" - -// The default TM method used when starting a new transaction. Initialized -// in number_of_threads_changed() below. -// Access to this variable is always synchronized with help of the serial -// lock, except one read access that happens in decide_begin_dispatch() before -// a transaction has become active (by acquiring the serial lock in read or -// write mode). The default_dispatch is only changed and initialized in -// serial mode. Transactions stay active when they restart (see beginend.cc), -// thus decide_retry_strategy() can expect default_dispatch to be unmodified. -// See decide_begin_dispatch() for further comments. -static std::atomic<GTM::abi_dispatch*> default_dispatch; -// The default TM method as requested by the user, if any. -static GTM::abi_dispatch* default_dispatch_user = 0; - -void -GTM::gtm_thread::decide_retry_strategy (gtm_restart_reason r) -{ - struct abi_dispatch *disp = abi_disp (); - - this->restart_reason[r]++; - this->restart_total++; - - if (r == RESTART_INIT_METHOD_GROUP) - { - // A re-initializations of the method group has been requested. Switch - // to serial mode, initialize, and resume normal operation. - if ((state & STATE_SERIAL) == 0) - { - // We have to eventually re-init the method group. Therefore, - // we cannot just upgrade to a write lock here because this could - // fail forever when other transactions execute in serial mode. - // However, giving up the read lock then means that a change of the - // method group could happen in-between, so check that we're not - // re-initializing without a need. - // ??? Note that we can still re-initialize too often, but avoiding - // that would increase code complexity, which seems unnecessary - // given that re-inits should be very infrequent. - serial_lock.read_unlock(this); - serial_lock.write_lock(); - if (disp->get_method_group() - == default_dispatch.load(memory_order_relaxed) - ->get_method_group()) - // Still the same method group. - disp->get_method_group()->reinit(); - serial_lock.write_unlock(); - // Also, we're making the transaction inactive, so when we become - // active again, some other thread might have changed the default - // dispatch, so we run the same code as for the first execution - // attempt. - disp = decide_begin_dispatch(prop); - set_abi_disp(disp); - } - else - // We are a serial transaction already, which makes things simple. - disp->get_method_group()->reinit(); - - return; - } - - bool retry_irr = (r == RESTART_SERIAL_IRR); - bool retry_serial = (retry_irr || this->restart_total > 100); - - // We assume closed nesting to be infrequently required, so just use - // dispatch_serial (with undo logging) if required. - if (r == RESTART_CLOSED_NESTING) - retry_serial = true; - - if (retry_serial) - { - // In serialirr_mode we can succeed with the upgrade to - // write-lock but fail the trycommit. In any case, if the - // write lock is not yet held, grab it. Don't do this with - // an upgrade, since we've no need to preserve the state we - // acquired with the read. - // Note that we will be restarting with either dispatch_serial or - // dispatch_serialirr, which are compatible with all TM methods; if - // we would retry with a different method, we would have to first check - // whether the default dispatch or the method group have changed. Also, - // the caller must have rolled back the previous transaction, so we - // don't have to worry about things such as privatization. - if ((this->state & STATE_SERIAL) == 0) - { - this->state |= STATE_SERIAL; - serial_lock.read_unlock (this); - serial_lock.write_lock (); - } - - // We can retry with dispatch_serialirr if the transaction - // doesn't contain an abort and if we don't need closed nesting. - if ((this->prop & pr_hasNoAbort) && (r != RESTART_CLOSED_NESTING)) - retry_irr = true; - } - - // Note that we can just use serial mode here without having to switch - // TM method sets because serial mode is compatible with all of them. - if (retry_irr) - { - this->state = (STATE_SERIAL | STATE_IRREVOCABLE); - disp = dispatch_serialirr (); - set_abi_disp (disp); - } - else if (retry_serial) - { - disp = dispatch_serial(); - set_abi_disp (disp); - } -} - - -// Decides which TM method should be used on the first attempt to run this -// transaction. Acquires the serial lock and sets transaction state -// according to the chosen TM method. -GTM::abi_dispatch* -GTM::gtm_thread::decide_begin_dispatch (uint32_t prop) -{ - abi_dispatch* dd; - // TODO Pay more attention to prop flags (eg, *omitted) when selecting - // dispatch. - // ??? We go irrevocable eagerly here, which is not always good for - // performance. Don't do this? - if ((prop & pr_doesGoIrrevocable) || !(prop & pr_instrumentedCode)) - dd = dispatch_serialirr(); - - else - { - // Load the default dispatch. We're not an active transaction and so it - // can change concurrently but will still be some valid dispatch. - // Relaxed memory order is okay because we expect each dispatch to be - // constructed properly already (at least that its closed_nesting() and - // closed_nesting_alternatives() will return sensible values). It is - // harmless if we incorrectly chose the serial or serialirr methods, and - // for all other methods we will acquire the serial lock in read mode - // and load the default dispatch again. - abi_dispatch* dd_orig = default_dispatch.load(memory_order_relaxed); - dd = dd_orig; - - // If we might need closed nesting and the default dispatch has an - // alternative that supports closed nesting, use it. - // ??? We could choose another TM method that we know supports closed - // nesting but isn't the default (e.g., dispatch_serial()). However, we - // assume that aborts that need closed nesting are infrequent, so don't - // choose a non-default method until we have to actually restart the - // transaction. - if (!(prop & pr_hasNoAbort) && !dd->closed_nesting() - && dd->closed_nesting_alternative()) - dd = dd->closed_nesting_alternative(); - - if (dd != dispatch_serial() && dd != dispatch_serialirr()) - { - // The current dispatch is supposedly a non-serial one. Become an - // active transaction and verify this. Relaxed memory order is fine - // because the serial lock itself will have established - // happens-before for any change to the selected dispatch. - serial_lock.read_lock (this); - if (default_dispatch.load(memory_order_relaxed) == dd_orig) - return dd; - - // If we raced with a concurrent modification of default_dispatch, - // just fall back to serialirr. The dispatch choice might not be - // up-to-date anymore, but this is harmless. - serial_lock.read_unlock (this); - dd = dispatch_serialirr(); - } - } - - // We are some kind of serial transaction. - serial_lock.write_lock(); - if (dd == dispatch_serialirr()) - state = STATE_SERIAL | STATE_IRREVOCABLE; - else - state = STATE_SERIAL; - return dd; -} - - -void -GTM::gtm_thread::set_default_dispatch(GTM::abi_dispatch* disp) -{ - abi_dispatch* dd = default_dispatch.load(memory_order_relaxed); - if (dd == disp) - return; - if (dd) - { - // If we are switching method groups, initialize and shut down properly. - if (dd->get_method_group() != disp->get_method_group()) - { - dd->get_method_group()->fini(); - disp->get_method_group()->init(); - } - } - else - disp->get_method_group()->init(); - default_dispatch.store(disp, memory_order_relaxed); -} - - -static GTM::abi_dispatch* -parse_default_method() -{ - const char *env = getenv("ITM_DEFAULT_METHOD"); - GTM::abi_dispatch* disp = 0; - if (env == NULL) - return 0; - - while (isspace((unsigned char) *env)) - ++env; - if (strncmp(env, "serialirr_onwrite", 17) == 0) - { - disp = GTM::dispatch_serialirr_onwrite(); - env += 17; - } - else if (strncmp(env, "serialirr", 9) == 0) - { - disp = GTM::dispatch_serialirr(); - env += 9; - } - else if (strncmp(env, "serial", 6) == 0) - { - disp = GTM::dispatch_serial(); - env += 6; - } - else if (strncmp(env, "gl_wt", 5) == 0) - { - disp = GTM::dispatch_gl_wt(); - env += 5; - } - else if (strncmp(env, "ml_wt", 5) == 0) - { - disp = GTM::dispatch_ml_wt(); - env += 5; - } - else - goto unknown; - - while (isspace((unsigned char) *env)) - ++env; - if (*env == '\0') - return disp; - - unknown: - GTM::GTM_error("Unknown TM method in environment variable " - "ITM_DEFAULT_METHOD\n"); - return 0; -} - -// Gets notifications when the number of registered threads changes. This is -// used to initialize the method set choice and trigger straightforward choice -// adaption. -// This must be called only by serial threads. -void -GTM::gtm_thread::number_of_threads_changed(unsigned previous, unsigned now) -{ - if (previous == 0) - { - // No registered threads before, so initialize. - static bool initialized = false; - if (!initialized) - { - initialized = true; - // Check for user preferences here. - default_dispatch = 0; - default_dispatch_user = parse_default_method(); - } - } - else if (now == 0) - { - // No registered threads anymore. The dispatch based on serial mode do - // not have any global state, so this effectively shuts down properly. - set_default_dispatch(dispatch_serialirr()); - } - - if (now == 1) - { - // Only one thread, so use a serializing method. - // ??? If we don't have a fast serial mode implementation, it might be - // better to use the global lock method set here. - if (default_dispatch_user && default_dispatch_user->supports(now)) - set_default_dispatch(default_dispatch_user); - else - set_default_dispatch(dispatch_serialirr()); - } - else if (now > 1 && previous <= 1) - { - // More than one thread, use the default method. - if (default_dispatch_user && default_dispatch_user->supports(now)) - set_default_dispatch(default_dispatch_user); - else - { - abi_dispatch* a = dispatch_ml_wt(); - if (a->supports(now)) - set_default_dispatch(a); - else - // Serial-irrevocable mode always works. - set_default_dispatch(dispatch_serialirr()); - } - } -} |
