Back to index

glibc  2.9
atomic.h
Go to the documentation of this file.
00001 /* Copyright (C) 2003 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Carlos O'Donell <carlos@baldric.uwo.ca>, 2005.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <stdint.h>
00021 #include <sysdep.h>
00022 #include <abort-instr.h>
00023 #include <kernel-features.h>
00024 
00025 /* We need EFAULT, ENONSYS */
00026 #if !defined EFAULT && !defined ENOSYS
00027 #define EFAULT       14
00028 #define ENOSYS       251
00029 #endif
00030 
00031 #ifndef _BITS_ATOMIC_H
00032 #define _BITS_ATOMIC_H      1
00033 
00034 typedef int8_t atomic8_t;
00035 typedef uint8_t uatomic8_t;
00036 typedef int_fast8_t atomic_fast8_t;
00037 typedef uint_fast8_t uatomic_fast8_t;
00038 
00039 typedef int32_t atomic32_t;
00040 typedef uint32_t uatomic32_t;
00041 typedef int_fast32_t atomic_fast32_t;
00042 typedef uint_fast32_t uatomic_fast32_t;
00043 
00044 typedef intptr_t atomicptr_t;
00045 typedef uintptr_t uatomicptr_t;
00046 typedef intmax_t atomic_max_t;
00047 typedef uintmax_t uatomic_max_t;
00048 
00049 /* prev = *addr;
00050    if (prev == old)
00051      *addr = new;
00052    return prev; */
00053 
00054 /* Use the kernel atomic light weight syscalls on hppa.  */ 
00055 #define _LWS "0xb0"
00056 #define _LWS_CAS "0"
00057 /* Note r31 is the link register.  */
00058 #define _LWS_CLOBBER "r1", "r26", "r25", "r24", "r23", "r22", "r21", "r20", "r28", "r31", "memory"
00059 /* String constant for -EAGAIN.  */
00060 #define _ASM_EAGAIN "-11" 
00061 /* String constant for -EDEADLOCK.  */
00062 #define _ASM_EDEADLOCK "-45"
00063 
00064 #if __ASSUME_LWS_CAS
00065 /* The only basic operation needed is compare and exchange.  */
00066 # define atomic_compare_and_exchange_val_acq(mem, newval, oldval)     \
00067   ({                                                           \
00068      volatile int lws_errno;                                          \
00069      volatile int lws_ret;                                     \
00070      asm volatile(                                             \
00071        "0:                                \n\t"                \
00072        "copy  %2, %%r26                   \n\t"                \
00073        "copy  %3, %%r25                   \n\t"                \
00074        "copy  %4, %%r24                   \n\t"                \
00075        "ble   " _LWS "(%%sr2, %%r0)              \n\t"                \
00076        "ldi   " _LWS_CAS ", %%r20         \n\t"                \
00077        "ldi   " _ASM_EAGAIN ", %%r24             \n\t"                \
00078        "cmpb,=,n %%r24, %%r21, 0b         \n\t"                \
00079        "nop                               \n\t"                \
00080        "ldi   " _ASM_EDEADLOCK ", %%r25   \n\t"                \
00081        "cmpb,=,n %%r25, %%r21, 0b         \n\t"                \
00082        "nop                               \n\t"                \
00083        "stw   %%r28, %0                   \n\t"                \
00084         "sub  %%r0, %%r21, %%r21          \n\t"                \
00085        "stw   %%r21, %1                   \n\t"                \
00086        : "=m" (lws_ret), "=m" (lws_errno)                             \
00087         : "r" (mem), "r" (oldval), "r" (newval)                       \
00088        : _LWS_CLOBBER                                                 \
00089      );                                                               \
00090                                                                \
00091      if(lws_errno == EFAULT || lws_errno == ENOSYS)                   \
00092        ABORT_INSTRUCTION;                                      \
00093                                                                \
00094      lws_ret;                                                  \
00095    })
00096 
00097 # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval)    \
00098   ({                                                           \
00099      int ret;                                                  \
00100      ret = atomic_compare_and_exchange_val_acq(mem, newval, oldval);  \
00101      /* Return 1 if it was already acquired.  */               \
00102      (ret != oldval);                                                 \
00103    })
00104 #else
00105 # error __ASSUME_LWS_CAS is required to build glibc.
00106 #endif 
00107 /* __ASSUME_LWS_CAS */
00108 
00109 #endif
00110 /* _BITS_ATOMIC_H */