LCOV - code coverage report
Current view: top level - lib/eal/x86/include - rte_spinlock.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 6 22 27.3 %
Date: 2025-10-01 17:51:42 Functions: 0 1 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 26 3.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #ifndef _RTE_SPINLOCK_X86_64_H_
       6                 :            : #define _RTE_SPINLOCK_X86_64_H_
       7                 :            : 
       8                 :            : #include "generic/rte_spinlock.h"
       9                 :            : #include "rte_rtm.h"
      10                 :            : #include "rte_branch_prediction.h"
      11                 :            : #include "rte_common.h"
      12                 :            : #include "rte_pause.h"
      13                 :            : #include "rte_cycles.h"
      14                 :            : 
      15                 :            : #ifdef __cplusplus
      16                 :            : extern "C" {
      17                 :            : #endif
      18                 :            : 
      19                 :            : #define RTE_RTM_MAX_RETRIES (20)
      20                 :            : #define RTE_XABORT_LOCK_BUSY (0xff)
      21                 :            : 
      22                 :            : #ifndef RTE_FORCE_INTRINSICS
      23                 :            : static inline void
      24                 :            : rte_spinlock_lock(rte_spinlock_t *sl)
      25                 :            :         __rte_no_thread_safety_analysis
      26                 :            : {
      27                 :            :         int lock_val = 1;
      28                 :    9259931 :         asm volatile (
      29                 :            :                         "1:\n"
      30                 :            :                         "xchg %[locked], %[lv]\n"
      31                 :            :                         "test %[lv], %[lv]\n"
      32                 :            :                         "jz 3f\n"
      33                 :            :                         "2:\n"
      34                 :            :                         "pause\n"
      35                 :            :                         "cmpl $0, %[locked]\n"
      36                 :            :                         "jnz 2b\n"
      37                 :            :                         "jmp 1b\n"
      38                 :            :                         "3:\n"
      39                 :            :                         : [locked] "=m" (sl->locked), [lv] "=q" (lock_val)
      40                 :            :                         : "[lv]" (lock_val)
      41                 :            :                         : "memory");
      42                 :     480145 : }
      43                 :            : 
      44                 :            : static inline void
      45                 :            : rte_spinlock_unlock (rte_spinlock_t *sl)
      46                 :            :         __rte_no_thread_safety_analysis
      47                 :            : {
      48                 :            :         int unlock_val = 0;
      49                 :   13468475 :         asm volatile (
      50                 :            :                         "xchg %[locked], %[ulv]\n"
      51                 :            :                         : [locked] "=m" (sl->locked), [ulv] "=q" (unlock_val)
      52                 :            :                         : "[ulv]" (unlock_val)
      53                 :            :                         : "memory");
      54                 :    1900152 : }
      55                 :            : 
      56                 :            : static inline int
      57                 :            : rte_spinlock_trylock (rte_spinlock_t *sl)
      58                 :            :         __rte_no_thread_safety_analysis
      59                 :            : {
      60                 :            :         int lockval = 1;
      61                 :            : 
      62                 :    4207530 :         asm volatile (
      63                 :            :                         "xchg %[locked], %[lockval]"
      64                 :            :                         : [locked] "=m" (sl->locked), [lockval] "=q" (lockval)
      65                 :            :                         : "[lockval]" (lockval)
      66                 :            :                         : "memory");
      67                 :            : 
      68         [ +  - ]:       3832 :         return lockval == 0;
      69                 :            : }
      70                 :            : #endif
      71                 :            : 
      72                 :            : extern uint8_t rte_rtm_supported;
      73                 :            : 
      74                 :            : static inline int rte_tm_supported(void)
      75                 :            : {
      76   [ #  #  #  # ]:          0 :         return rte_rtm_supported;
      77                 :            : }
      78                 :            : 
      79                 :            : static inline int
      80                 :          0 : rte_try_tm(volatile RTE_ATOMIC(int) *lock)
      81                 :            : {
      82                 :            :         int i, retries;
      83                 :            : 
      84         [ #  # ]:          0 :         if (!rte_rtm_supported)
      85                 :            :                 return 0;
      86                 :            : 
      87                 :            :         retries = RTE_RTM_MAX_RETRIES;
      88                 :            : 
      89         [ #  # ]:          0 :         while (likely(retries--)) {
      90                 :            : 
      91                 :            :                 unsigned int status = rte_xbegin();
      92                 :            : 
      93         [ #  # ]:          0 :                 if (likely(RTE_XBEGIN_STARTED == status)) {
      94         [ #  # ]:          0 :                         if (unlikely(*lock))
      95                 :            :                                 rte_xabort(RTE_XABORT_LOCK_BUSY);
      96                 :            :                         else
      97                 :            :                                 return 1;
      98                 :            :                 }
      99         [ #  # ]:          0 :                 while (*lock)
     100                 :            :                         rte_pause();
     101                 :            : 
     102         [ #  # ]:          0 :                 if ((status & RTE_XABORT_CONFLICT) ||
     103         [ #  # ]:          0 :                    ((status & RTE_XABORT_EXPLICIT) &&
     104         [ #  # ]:          0 :                     (RTE_XABORT_CODE(status) == RTE_XABORT_LOCK_BUSY))) {
     105                 :            :                         /* add a small delay before retrying, basing the
     106                 :            :                          * delay on the number of times we've already tried,
     107                 :            :                          * to give a back-off type of behaviour. We
     108                 :            :                          * randomize trycount by taking bits from the tsc count
     109                 :            :                          */
     110                 :          0 :                         int try_count = RTE_RTM_MAX_RETRIES - retries;
     111                 :          0 :                         int pause_count = (rte_rdtsc() & 0x7) | 1;
     112                 :          0 :                         pause_count <<= try_count;
     113         [ #  # ]:          0 :                         for (i = 0; i < pause_count; i++)
     114                 :            :                                 rte_pause();
     115                 :          0 :                         continue;
     116                 :            :                 }
     117                 :            : 
     118         [ #  # ]:          0 :                 if ((status & RTE_XABORT_RETRY) == 0) /* do not retry */
     119                 :            :                         break;
     120                 :            :         }
     121                 :            :         return 0;
     122                 :            : }
     123                 :            : 
     124                 :            : static inline void
     125                 :            : rte_spinlock_lock_tm(rte_spinlock_t *sl)
     126                 :            :         __rte_no_thread_safety_analysis
     127                 :            : {
     128                 :            :         if (likely(rte_try_tm(&sl->locked)))
     129                 :            :                 return;
     130                 :            : 
     131                 :            :         rte_spinlock_lock(sl); /* fall-back */
     132                 :            : }
     133                 :            : 
     134                 :            : static inline int
     135                 :            : rte_spinlock_trylock_tm(rte_spinlock_t *sl)
     136                 :            :         __rte_no_thread_safety_analysis
     137                 :            : {
     138                 :            :         if (likely(rte_try_tm(&sl->locked)))
     139                 :            :                 return 1;
     140                 :            : 
     141                 :            :         return rte_spinlock_trylock(sl);
     142                 :            : }
     143                 :            : 
     144                 :            : static inline void
     145                 :            : rte_spinlock_unlock_tm(rte_spinlock_t *sl)
     146                 :            :         __rte_no_thread_safety_analysis
     147                 :            : {
     148                 :            :         if (unlikely(sl->locked))
     149                 :            :                 rte_spinlock_unlock(sl);
     150                 :            :         else
     151                 :            :                 rte_xend();
     152                 :            : }
     153                 :            : 
     154                 :            : static inline void
     155                 :            : rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr)
     156                 :            :         __rte_no_thread_safety_analysis
     157                 :            : {
     158                 :            :         if (likely(rte_try_tm(&slr->sl.locked)))
     159                 :            :                 return;
     160                 :            : 
     161                 :            :         rte_spinlock_recursive_lock(slr); /* fall-back */
     162                 :            : }
     163                 :            : 
     164                 :            : static inline void
     165                 :            : rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr)
     166                 :            :         __rte_no_thread_safety_analysis
     167                 :            : {
     168                 :            :         if (unlikely(slr->sl.locked))
     169                 :            :                 rte_spinlock_recursive_unlock(slr);
     170                 :            :         else
     171                 :            :                 rte_xend();
     172                 :            : }
     173                 :            : 
     174                 :            : static inline int
     175                 :            : rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr)
     176                 :            :         __rte_no_thread_safety_analysis
     177                 :            : {
     178                 :            :         if (likely(rte_try_tm(&slr->sl.locked)))
     179                 :            :                 return 1;
     180                 :            : 
     181                 :            :         return rte_spinlock_recursive_trylock(slr);
     182                 :            : }
     183                 :            : 
     184                 :            : #ifdef __cplusplus
     185                 :            : }
     186                 :            : #endif
     187                 :            : 
     188                 :            : #endif /* _RTE_SPINLOCK_X86_64_H_ */

Generated by: LCOV version 1.14