New upstream version 18.11-rc3
[deb_dpdk.git] / lib / librte_eal / common / include / arch / x86 / rte_spinlock.h
index 02f95cb..e2e2b26 100644 (file)
@@ -1,34 +1,5 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
  */
 
 #ifndef _RTE_SPINLOCK_X86_64_H_
@@ -43,8 +14,10 @@ extern "C" {
 #include "rte_cpuflags.h"
 #include "rte_branch_prediction.h"
 #include "rte_common.h"
+#include "rte_pause.h"
+#include "rte_cycles.h"
 
-#define RTE_RTM_MAX_RETRIES (10)
+#define RTE_RTM_MAX_RETRIES (20)
 #define RTE_XABORT_LOCK_BUSY (0xff)
 
 #ifndef RTE_FORCE_INTRINSICS
@@ -94,27 +67,22 @@ rte_spinlock_trylock (rte_spinlock_t *sl)
 }
 #endif
 
-static uint8_t rtm_supported; /* cache the flag to avoid the overhead
-                                of the rte_cpu_get_flag_enabled function */
-
-static inline void __attribute__((constructor))
-rte_rtm_init(void)
-{
-       rtm_supported = rte_cpu_get_flag_enabled(RTE_CPUFLAG_RTM);
-}
+extern uint8_t rte_rtm_supported;
 
 static inline int rte_tm_supported(void)
 {
-       return rtm_supported;
+       return rte_rtm_supported;
 }
 
 static inline int
 rte_try_tm(volatile int *lock)
 {
-       if (!rtm_supported)
+       int i, retries;
+
+       if (!rte_rtm_supported)
                return 0;
 
-       int retries = RTE_RTM_MAX_RETRIES;
+       retries = RTE_RTM_MAX_RETRIES;
 
        while (likely(retries--)) {
 
@@ -129,9 +97,21 @@ rte_try_tm(volatile int *lock)
                while (*lock)
                        rte_pause();
 
-               if ((status & RTE_XABORT_EXPLICIT) &&
-                       (RTE_XABORT_CODE(status) == RTE_XABORT_LOCK_BUSY))
+               if ((status & RTE_XABORT_CONFLICT) ||
+                  ((status & RTE_XABORT_EXPLICIT) &&
+                   (RTE_XABORT_CODE(status) == RTE_XABORT_LOCK_BUSY))) {
+                       /* add a small delay before retrying, basing the
+                        * delay on the number of times we've already tried,
+                        * to give a back-off type of behaviour. We
+                        * randomize trycount by taking bits from the tsc count
+                        */
+                       int try_count = RTE_RTM_MAX_RETRIES - retries;
+                       int pause_count = (rte_rdtsc() & 0x7) | 1;
+                       pause_count <<= try_count;
+                       for (i = 0; i < pause_count; i++)
+                               rte_pause();
                        continue;
+               }
 
                if ((status & RTE_XABORT_RETRY) == 0) /* do not retry */
                        break;