Changeset 657ddbd in mainline


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

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

File:
1 edited

Legend:

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

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