Ignore:
File:
1 edited

Legend:

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

    r9d58539 rb17518e  
    140140}
    141141
     142
     143#define _atomic_cas_impl(pptr, exp_val, new_val, old_val, prefix) \
     144        asm volatile ( \
     145                prefix " cmpxchgq %[newval], %[ptr]\n" \
     146                : /* Output operands. */ \
     147                /* Old/current value is returned in eax. */ \
     148                [oldval] "=a" (old_val), \
     149                /* (*ptr) will be read and written to, hence "+" */ \
     150                [ptr] "+m" (*pptr) \
     151                : /* Input operands. */ \
     152                /* Expected value must be in eax. */ \
     153                [expval] "a" (exp_val), \
     154                /* The new value may be in any register. */ \
     155                [newval] "r" (new_val) \
     156                : "memory" \
     157        )
     158       
     159/** Atomically compares and swaps the pointer at pptr. */
     160NO_TRACE static inline void * atomic_cas_ptr(void **pptr,
     161        void *exp_val, void *new_val)
     162{
     163        void *old_val;
     164        _atomic_cas_impl(pptr, exp_val, new_val, old_val, "lock\n");
     165        return old_val;
     166}
     167
     168/** Compare-and-swap of a pointer that is atomic wrt to local cpu's interrupts.
     169 *
     170 * This function is NOT smp safe and is not atomic with respect to other cpus.
     171 */
     172NO_TRACE static inline void * atomic_cas_ptr_local(void **pptr,
     173        void *exp_val, void *new_val)
     174{
     175        void *old_val;
     176        _atomic_cas_impl(pptr, exp_val, new_val, old_val, "");
     177        return old_val;
     178}
     179
     180
     181#define _atomic_swap_impl(pptr, new_val) \
     182({ \
     183        typeof(*(pptr)) new_in_old_out = new_val; \
     184        asm volatile ( \
     185                "xchgq %[val], %[p_ptr]\n" \
     186                : [val] "+r" (new_in_old_out), \
     187                  [p_ptr] "+m" (*pptr) \
     188        ); \
     189        \
     190        new_in_old_out; \
     191})
     192
     193/*
     194 * Issuing a xchg instruction always implies lock prefix semantics.
     195 * Therefore, it is cheaper to use a cmpxchg without a lock prefix
     196 * in a loop.
     197 */
     198#define _atomic_swap_local_impl(pptr, new_val) \
     199({ \
     200        typeof(*(pptr)) exp_val; \
     201        typeof(*(pptr)) old_val; \
     202        \
     203        do { \
     204                exp_val = *pptr; \
     205                _atomic_cas_impl(pptr, exp_val, new_val, old_val, ""); \
     206        } while (old_val != exp_val); \
     207        \
     208        old_val; \
     209})
     210
     211
     212/** Atomicaly sets *ptr to val and returns the previous value. */
     213NO_TRACE static inline void * atomic_set_return_ptr(void **pptr, void *val)
     214{
     215        return _atomic_swap_impl(pptr, val);
     216}
     217
     218/** Sets *ptr to new_val and returns the previous value. NOT smp safe.
     219 *
     220 * This function is only atomic wrt to local interrupts and it is
     221 * NOT atomic wrt to other cpus.
     222 */
     223NO_TRACE static inline void * atomic_set_return_ptr_local(
     224        void **pptr, void *new_val)
     225{
     226        return _atomic_swap_local_impl(pptr, new_val);
     227}
     228
     229/** Atomicaly sets *ptr to val and returns the previous value. */
     230NO_TRACE static inline native_t atomic_set_return_native_t(
     231        native_t *p, native_t val)
     232{
     233        return _atomic_swap_impl(p, val);
     234}
     235
     236/** Sets *ptr to new_val and returns the previous value. NOT smp safe.
     237 *
     238 * This function is only atomic wrt to local interrupts and it is
     239 * NOT atomic wrt to other cpus.
     240 */
     241NO_TRACE static inline native_t atomic_set_return_native_t_local(
     242        native_t *p, native_t new_val)
     243{
     244        return _atomic_swap_local_impl(p, new_val);
     245}
     246
     247
     248#undef _atomic_cas_ptr_impl
     249#undef _atomic_swap_impl
     250#undef _atomic_swap_local_impl
     251
    142252#endif
    143253
Note: See TracChangeset for help on using the changeset viewer.