linux-old/include/asm-s390/atomic.h
<<
>>
Prefs
   1#ifndef __ARCH_S390_ATOMIC__
   2#define __ARCH_S390_ATOMIC__
   3
   4/*
   5 *  include/asm-s390/atomic.h
   6 *
   7 *  S390 version
   8 *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
   9 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  10 *               Denis Joseph Barrow
  11 *
  12 *  Derived from "include/asm-i386/bitops.h"
  13 *    Copyright (C) 1992, Linus Torvalds
  14 *
  15 */
  16
  17/*
  18 * Atomic operations that C can't guarantee us.  Useful for
  19 * resource counting etc..
  20 * S390 uses 'Compare And Swap' for atomicity in SMP enviroment
  21 */
  22
  23typedef struct { volatile int counter; } __attribute__ ((aligned (4))) atomic_t;
  24#define ATOMIC_INIT(i)  { (i) }
  25
  26#define atomic_eieio()          __asm__ __volatile__ ("BCR 15,0")
  27
  28#define __CS_LOOP(old_val, new_val, ptr, op_val, op_string)             \
  29        __asm__ __volatile__("   l     %0,0(%2)\n"                      \
  30                             "0: lr    %1,%0\n"                         \
  31                             op_string "  %1,%3\n"                      \
  32                             "   cs    %0,%1,0(%2)\n"                   \
  33                             "   jl    0b"                              \
  34                             : "=&d" (old_val), "=&d" (new_val)         \
  35                             : "a" (ptr), "d" (op_val) : "cc" );
  36
  37#define atomic_read(v)          ((v)->counter)
  38#define atomic_set(v,i)         (((v)->counter) = (i))
  39
  40static __inline__ void atomic_add(int i, atomic_t *v)
  41{
  42        int old_val, new_val;
  43        __CS_LOOP(old_val, new_val, v, i, "ar");
  44}
  45
  46static __inline__ int atomic_add_return (int i, atomic_t *v)
  47{
  48        int old_val, new_val;
  49        __CS_LOOP(old_val, new_val, v, i, "ar");
  50        return new_val;
  51}
  52
  53static __inline__ int atomic_add_negative(int i, atomic_t *v)
  54{
  55        int old_val, new_val;
  56        __CS_LOOP(old_val, new_val, v, i, "ar");
  57        return new_val < 0;
  58}
  59
  60static __inline__ void atomic_sub(int i, atomic_t *v)
  61{
  62        int old_val, new_val;
  63        __CS_LOOP(old_val, new_val, v, i, "sr");
  64}
  65
  66static __inline__ void atomic_inc(volatile atomic_t *v)
  67{
  68        int old_val, new_val;
  69        __CS_LOOP(old_val, new_val, v, 1, "ar");
  70}
  71
  72static __inline__ int atomic_inc_return(volatile atomic_t *v)
  73{
  74        int old_val, new_val;
  75        __CS_LOOP(old_val, new_val, v, 1, "ar");
  76        return new_val;
  77}
  78
  79static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
  80{
  81        int old_val, new_val;
  82        __CS_LOOP(old_val, new_val, v, 1, "ar");
  83        return new_val != 0;
  84}
  85
  86static __inline__ void atomic_dec(volatile atomic_t *v)
  87{
  88        int old_val, new_val;
  89        __CS_LOOP(old_val, new_val, v, 1, "sr");
  90}
  91
  92static __inline__ int atomic_dec_return(volatile atomic_t *v)
  93{
  94        int old_val, new_val;
  95        __CS_LOOP(old_val, new_val, v, 1, "sr");
  96        return new_val;
  97}
  98
  99static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
 100{
 101        int old_val, new_val;
 102        __CS_LOOP(old_val, new_val, v, 1, "sr");
 103        return new_val == 0;
 104}
 105
 106static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
 107{
 108        int old_val, new_val;
 109        __CS_LOOP(old_val, new_val, v, ~mask, "nr");
 110}
 111
 112static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
 113{
 114        int old_val, new_val;
 115        __CS_LOOP(old_val, new_val, v, mask, "or");
 116}
 117
 118/*
 119  returns 0  if expected_oldval==value in *v ( swap was successful )
 120  returns 1  if unsuccessful.
 121*/
 122static __inline__ int
 123atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
 124{
 125        int retval;
 126
 127        __asm__ __volatile__(
 128                "  lr   0,%2\n"
 129                "  cs   0,%3,0(%1)\n"
 130                "  ipm  %0\n"
 131                "  srl  %0,28\n"
 132                "0:"
 133                : "=&d" (retval)
 134                : "a" (v), "d" (expected_oldval) , "d" (new_val)
 135                : "0", "cc");
 136        return retval;
 137}
 138
 139/*
 140  Spin till *v = expected_oldval then swap with newval.
 141 */
 142static __inline__ void
 143atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
 144{
 145        __asm__ __volatile__(
 146                "0: lr  0,%1\n"
 147                "   cs  0,%2,0(%0)\n"
 148                "   jl  0b\n"
 149                : : "a" (v), "d" (expected_oldval) , "d" (new_val)
 150                : "cc", "0" );
 151}
 152
 153#define atomic_compare_and_swap_debug(where,from,to) \
 154if (atomic_compare_and_swap ((from), (to), (where))) {\
 155        printk (KERN_WARNING"%s/%d atomic counter:%s couldn't be changed from %d(%s) to %d(%s), was %d\n",\
 156                __FILE__,__LINE__,#where,(from),#from,(to),#to,atomic_read (where));\
 157        atomic_set(where,(to));\
 158}
 159
 160#define smp_mb__before_atomic_dec()     smp_mb()
 161#define smp_mb__after_atomic_dec()      smp_mb()
 162#define smp_mb__before_atomic_inc()     smp_mb()
 163#define smp_mb__after_atomic_inc()      smp_mb()
 164
 165#endif                                 /* __ARCH_S390_ATOMIC __            */
 166
 167
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.