linux/arch/tile/lib/spinlock_common.h
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
   3 *
   4 *   This program is free software; you can redistribute it and/or
   5 *   modify it under the terms of the GNU General Public License
   6 *   as published by the Free Software Foundation, version 2.
   7 *
   8 *   This program is distributed in the hope that it will be useful, but
   9 *   WITHOUT ANY WARRANTY; without even the implied warranty of
  10 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  11 *   NON INFRINGEMENT.  See the GNU General Public License for
  12 *   more details.
  13 * This file is included into spinlock_32.c or _64.c.
  14 */
  15
  16/*
  17 * The mfspr in __spinlock_relax() is 5 or 6 cycles plus 2 for loop
  18 * overhead.
  19 */
  20#ifdef __tilegx__
  21#define CYCLES_PER_RELAX_LOOP 7
  22#else
  23#define CYCLES_PER_RELAX_LOOP 8
  24#endif
  25
  26/*
  27 * Idle the core for CYCLES_PER_RELAX_LOOP * iterations cycles.
  28 */
  29static inline void
  30relax(int iterations)
  31{
  32        for (/*above*/; iterations > 0; iterations--)
  33                __insn_mfspr(SPR_PASS);
  34        barrier();
  35}
  36
  37/* Perform bounded exponential backoff.*/
  38static void delay_backoff(int iterations)
  39{
  40        u32 exponent, loops;
  41
  42        /*
  43         * 2^exponent is how many times we go around the loop,
  44         * which takes 8 cycles.  We want to start with a 16- to 31-cycle
  45         * loop, so we need to go around minimum 2 = 2^1 times, so we
  46         * bias the original value up by 1.
  47         */
  48        exponent = iterations + 1;
  49
  50        /*
  51         * Don't allow exponent to exceed 7, so we have 128 loops,
  52         * or 1,024 (to 2,047) cycles, as our maximum.
  53         */
  54        if (exponent > 8)
  55                exponent = 8;
  56
  57        loops = 1 << exponent;
  58
  59        /* Add a randomness factor so two cpus never get in lock step. */
  60        loops += __insn_crc32_32(stack_pointer, get_cycles_low()) &
  61                (loops - 1);
  62
  63        relax(loops);
  64}
  65