aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.7/libitm/retry.cc
diff options
context:
space:
mode:
authorDan Albert <danalbert@google.com>2015-06-17 11:09:54 -0700
committerDan Albert <danalbert@google.com>2015-06-17 14:15:22 -0700
commitf378ebf14df0952eae870c9865bab8326aa8f137 (patch)
tree31794503eb2a8c64ea5f313b93100f1163afcffb /gcc-4.7/libitm/retry.cc
parent2c58169824949d3a597d9fa81931e001ef9b1bd0 (diff)
downloadtoolchain_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.cc325
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());
- }
- }
-}