Changeset 6831475 in mainline for kernel/arch/amd64/include/atomic.h


Ignore:
Timestamp:
2012-11-19T21:13:01Z (12 years ago)
Author:
Adam Hraska <adam.hraska+hos@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
82719589
Parents:
657ddbd
Message:

Added amd64-specific local atomic exchange (faster than the generic version).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/include/atomic.h

    r657ddbd r6831475  
    141141
    142142
     143#define _atomic_cas_impl(pptr, exp_val, new_val, old_val, prefix) \
     144({ \
     145        switch (sizeof(typeof(*(pptr)))) { \
     146        case 1: \
     147                asm volatile ( \
     148                        prefix " cmpxchgb %[newval], %[ptr]\n" \
     149                        : /* Output operands. */ \
     150                        /* Old/current value is returned in eax. */ \
     151                        [oldval] "=a" (old_val), \
     152                        /* (*ptr) will be read and written to, hence "+" */ \
     153                        [ptr] "+m" (*pptr) \
     154                        : /* Input operands. */ \
     155                        /* Expected value must be in eax. */ \
     156                        [expval] "a" (exp_val), \
     157                        /* The new value may be in any register. */ \
     158                        [newval] "r" (new_val) \
     159                        : "memory" \
     160                ); \
     161                break; \
     162        case 2: \
     163                asm volatile ( \
     164                        prefix " cmpxchgw %[newval], %[ptr]\n" \
     165                        : /* Output operands. */ \
     166                        /* Old/current value is returned in eax. */ \
     167                        [oldval] "=a" (old_val), \
     168                        /* (*ptr) will be read and written to, hence "+" */ \
     169                        [ptr] "+m" (*pptr) \
     170                        : /* Input operands. */ \
     171                        /* Expected value must be in eax. */ \
     172                        [expval] "a" (exp_val), \
     173                        /* The new value may be in any register. */ \
     174                        [newval] "r" (new_val) \
     175                        : "memory" \
     176                ); \
     177                break; \
     178        case 4: \
     179                asm volatile ( \
     180                        prefix " cmpxchgl %[newval], %[ptr]\n" \
     181                        : /* Output operands. */ \
     182                        /* Old/current value is returned in eax. */ \
     183                        [oldval] "=a" (old_val), \
     184                        /* (*ptr) will be read and written to, hence "+" */ \
     185                        [ptr] "+m" (*pptr) \
     186                        : /* Input operands. */ \
     187                        /* Expected value must be in eax. */ \
     188                        [expval] "a" (exp_val), \
     189                        /* The new value may be in any register. */ \
     190                        [newval] "r" (new_val) \
     191                        : "memory" \
     192                ); \
     193                break; \
     194        case 8: \
     195                asm volatile ( \
     196                        prefix " cmpxchgq %[newval], %[ptr]\n" \
     197                        : /* Output operands. */ \
     198                        /* Old/current value is returned in eax. */ \
     199                        [oldval] "=a" (old_val), \
     200                        /* (*ptr) will be read and written to, hence "+" */ \
     201                        [ptr] "+m" (*pptr) \
     202                        : /* Input operands. */ \
     203                        /* Expected value must be in eax. */ \
     204                        [expval] "a" (exp_val), \
     205                        /* The new value may be in any register. */ \
     206                        [newval] "r" (new_val) \
     207                        : "memory" \
     208                ); \
     209                break; \
     210        } \
     211})
     212
     213
     214#ifndef local_atomic_cas
     215
     216#define local_atomic_cas(pptr, exp_val, new_val) \
     217({ \
     218        typeof(*(pptr)) old_val; \
     219        _atomic_cas_impl(pptr, exp_val, new_val, old_val, ""); \
     220        \
     221        old_val; \
     222})
     223
     224#else
     225/* Check if arch/atomic.h does not accidentally include /atomic.h .*/
     226#error Architecture specific cpu local atomics already defined! Check your includes.
    143227#endif
    144228
     229
     230#ifndef local_atomic_exchange
     231/*
     232 * Issuing a xchg instruction always implies lock prefix semantics.
     233 * Therefore, it is cheaper to use a cmpxchg without a lock prefix
     234 * in a loop.
     235 */
     236#define local_atomic_exchange(pptr, new_val) \
     237({ \
     238        typeof(*(pptr)) exp_val; \
     239        typeof(*(pptr)) old_val; \
     240        \
     241        do { \
     242                exp_val = *pptr; \
     243                old_val = local_atomic_cas(pptr, exp_val, new_val); \
     244        } while (old_val != exp_val); \
     245        \
     246        old_val; \
     247})
     248
     249#else
     250/* Check if arch/atomic.h does not accidentally include /atomic.h .*/
     251#error Architecture specific cpu local atomics already defined! Check your includes.
     252#endif
     253
     254
     255#endif
     256
    145257/** @}
    146258 */
Note: See TracChangeset for help on using the changeset viewer.