Blame sysdeps/s390/atomic-machine.h

Packit Service 82fcde
/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
Packit Service 82fcde
typedef int8_t atomic8_t;
Packit Service 82fcde
typedef uint8_t uatomic8_t;
Packit Service 82fcde
typedef int_fast8_t atomic_fast8_t;
Packit Service 82fcde
typedef uint_fast8_t uatomic_fast8_t;
Packit Service 82fcde
Packit Service 82fcde
typedef int16_t atomic16_t;
Packit Service 82fcde
typedef uint16_t uatomic16_t;
Packit Service 82fcde
typedef int_fast16_t atomic_fast16_t;
Packit Service 82fcde
typedef uint_fast16_t uatomic_fast16_t;
Packit Service 82fcde
Packit Service 82fcde
typedef int32_t atomic32_t;
Packit Service 82fcde
typedef uint32_t uatomic32_t;
Packit Service 82fcde
typedef int_fast32_t atomic_fast32_t;
Packit Service 82fcde
typedef uint_fast32_t uatomic_fast32_t;
Packit Service 82fcde
Packit Service 82fcde
typedef int64_t atomic64_t;
Packit Service 82fcde
typedef uint64_t uatomic64_t;
Packit Service 82fcde
typedef int_fast64_t atomic_fast64_t;
Packit Service 82fcde
typedef uint_fast64_t uatomic_fast64_t;
Packit Service 82fcde
Packit Service 82fcde
typedef intptr_t atomicptr_t;
Packit Service 82fcde
typedef uintptr_t uatomicptr_t;
Packit Service 82fcde
typedef intmax_t atomic_max_t;
Packit Service 82fcde
typedef uintmax_t uatomic_max_t;
Packit Service 82fcde
Packit Service 82fcde
/* Activate all C11 atomic builtins.
Packit Service 82fcde
Packit Service 82fcde
   Note:
Packit Service 82fcde
   E.g. in nptl/pthread_key_delete.c if compiled with GCCs 6 and before,
Packit Service 82fcde
   an extra stack-frame is generated and the old value is stored on stack
Packit Service 82fcde
   before cs instruction but it never loads this value from stack.
Packit Service 82fcde
   An unreleased GCC 7 omit those stack operations.
Packit Service 82fcde
Packit Service 82fcde
   E.g. in nptl/pthread_once.c the condition code of cs instruction is
Packit Service 82fcde
   evaluated by a sequence of ipm, sra, compare and jump instructions instead
Packit Service 82fcde
   of one conditional jump instruction.  This also occurs with an unreleased
Packit Service 82fcde
   GCC 7.
Packit Service 82fcde
Packit Service 82fcde
   The atomic_fetch_abc_def C11 builtins are now using load-and-abc instructions
Packit Service 82fcde
   on z196 zarch and higher cpus instead of a loop with compare-and-swap
Packit Service 82fcde
   instruction.  */
Packit Service 82fcde
#define USE_ATOMIC_COMPILER_BUILTINS 1
Packit Service 82fcde
Packit Service 82fcde
#ifdef __s390x__
Packit Service 82fcde
# define __HAVE_64B_ATOMICS 1
Packit Service 82fcde
#else
Packit Service 82fcde
# define __HAVE_64B_ATOMICS 0
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#define ATOMIC_EXCHANGE_USES_CAS 1
Packit Service 82fcde
Packit Service 82fcde
/* Implement some of the non-C11 atomic macros from include/atomic.h
Packit Service 82fcde
   with help of the C11 atomic builtins.  The other non-C11 atomic macros
Packit Service 82fcde
   are using the macros defined here.  */
Packit Service 82fcde
Packit Service 82fcde
/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
Packit Service 82fcde
   Return the old *MEM value.  */
Packit Service 82fcde
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval)	\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
    typeof ((__typeof (*(mem))) *(mem)) __atg1_oldval = (oldval);	\
Packit Service 82fcde
    __atomic_compare_exchange_n (mem, (void *) &__atg1_oldval,		\
Packit Service 82fcde
				 newval, 1, __ATOMIC_ACQUIRE,		\
Packit Service 82fcde
				 __ATOMIC_RELAXED);			\
Packit Service 82fcde
    __atg1_oldval; })
Packit Service 82fcde
#define atomic_compare_and_exchange_val_rel(mem, newval, oldval)	\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
    typeof ((__typeof (*(mem))) *(mem)) __atg1_2_oldval = (oldval);	\
Packit Service 82fcde
    __atomic_compare_exchange_n (mem, (void *) &__atg1_2_oldval,	\
Packit Service 82fcde
				 newval, 1, __ATOMIC_RELEASE,		\
Packit Service 82fcde
				 __ATOMIC_RELAXED);			\
Packit Service 82fcde
    __atg1_2_oldval; })
Packit Service 82fcde
Packit Service 82fcde
/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
Packit Service 82fcde
   Return zero if *MEM was changed or non-zero if no exchange happened.  */
Packit Service 82fcde
#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval)	\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
    typeof ((__typeof (*(mem))) *(mem)) __atg2_oldval = (oldval);	\
Packit Service 82fcde
    !__atomic_compare_exchange_n (mem, (void *) &__atg2_oldval, newval,	\
Packit Service 82fcde
				  1, __ATOMIC_ACQUIRE,			\
Packit Service 82fcde
				  __ATOMIC_RELAXED); })
Packit Service 82fcde
#define catomic_compare_and_exchange_bool_acq(mem, newval, oldval)	\
Packit Service 82fcde
  atomic_compare_and_exchange_bool_acq (mem, newval, oldval)
Packit Service 82fcde
Packit Service 82fcde
/* Store NEWVALUE in *MEM and return the old value.  */
Packit Service 82fcde
#define atomic_exchange_acq(mem, newvalue)				\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
    __atomic_exchange_n (mem, newvalue, __ATOMIC_ACQUIRE); })
Packit Service 82fcde
#define atomic_exchange_rel(mem, newvalue)				\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
    __atomic_exchange_n (mem, newvalue, __ATOMIC_RELEASE); })
Packit Service 82fcde
Packit Service 82fcde
/* Add VALUE to *MEM and return the old value of *MEM.  */
Packit Service 82fcde
/* The gcc builtin uses load-and-add instruction on z196 zarch and higher cpus
Packit Service 82fcde
   instead of a loop with compare-and-swap instruction.  */
Packit Service 82fcde
# define atomic_exchange_and_add_acq(mem, operand)			\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
  __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQUIRE); })
Packit Service 82fcde
# define atomic_exchange_and_add_rel(mem, operand)			\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
  __atomic_fetch_add ((mem), (operand), __ATOMIC_RELEASE); })
Packit Service 82fcde
#define catomic_exchange_and_add(mem, value)	\
Packit Service 82fcde
  atomic_exchange_and_add (mem, value)
Packit Service 82fcde
Packit Service 82fcde
/* Atomically *mem |= mask and return the old value of *mem.  */
Packit Service 82fcde
/* The gcc builtin uses load-and-or instruction on z196 zarch and higher cpus
Packit Service 82fcde
   instead of a loop with compare-and-swap instruction.  */
Packit Service 82fcde
#define atomic_or_val(mem, operand)					\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
  __atomic_fetch_or ((mem), (operand), __ATOMIC_ACQUIRE); })
Packit Service 82fcde
/* Atomically *mem |= mask.  */
Packit Service 82fcde
#define atomic_or(mem, mask)			\
Packit Service 82fcde
  do {						\
Packit Service 82fcde
    atomic_or_val (mem, mask);			\
Packit Service 82fcde
  } while (0)
Packit Service 82fcde
#define catomic_or(mem, mask)			\
Packit Service 82fcde
  atomic_or (mem, mask)
Packit Service 82fcde
Packit Service 82fcde
/* Atomically *mem |= 1 << bit and return true if the bit was set in old value
Packit Service 82fcde
   of *mem.  */
Packit Service 82fcde
/* The load-and-or instruction is used on z196 zarch and higher cpus
Packit Service 82fcde
   instead of a loop with compare-and-swap instruction.  */
Packit Service 82fcde
#define atomic_bit_test_set(mem, bit)					\
Packit Service 82fcde
  ({ __typeof (*(mem)) __atg14_old;					\
Packit Service 82fcde
    __typeof (mem) __atg14_memp = (mem);				\
Packit Service 82fcde
    __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit));	\
Packit Service 82fcde
    __atg14_old = atomic_or_val (__atg14_memp, __atg14_mask);		\
Packit Service 82fcde
    __atg14_old & __atg14_mask; })
Packit Service 82fcde
Packit Service 82fcde
/* Atomically *mem &= mask and return the old value of *mem.  */
Packit Service 82fcde
/* The gcc builtin uses load-and-and instruction on z196 zarch and higher cpus
Packit Service 82fcde
   instead of a loop with compare-and-swap instruction.  */
Packit Service 82fcde
#define atomic_and_val(mem, operand)					\
Packit Service 82fcde
  ({ __atomic_check_size((mem));					\
Packit Service 82fcde
  __atomic_fetch_and ((mem), (operand), __ATOMIC_ACQUIRE); })
Packit Service 82fcde
/* Atomically *mem &= mask.  */
Packit Service 82fcde
#define atomic_and(mem, mask)			\
Packit Service 82fcde
  do {						\
Packit Service 82fcde
    atomic_and_val (mem, mask);			\
Packit Service 82fcde
  } while (0)
Packit Service 82fcde
#define catomic_and(mem, mask)			\
Packit Service 82fcde
  atomic_and(mem, mask)