mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-28 19:47:08 +03:00
66d97267c7
This excludes all headers in /usr/include/dev because that directory is bonkers huge (18M). We can add these on an as-needed basis.
292 lines
6.8 KiB
C
Vendored
292 lines
6.8 KiB
C
Vendored
/* $OpenBSD: atomic.h,v 1.3 2022/08/29 02:01:18 jsg Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2015 Martin Pieuchot
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
|
|
#ifndef _MACHINE_ATOMIC_H_
|
|
#define _MACHINE_ATOMIC_H_
|
|
|
|
#if defined(_KERNEL)
|
|
|
|
static __inline void
|
|
atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" or %0, %1, %0 \n"
|
|
" stwcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
" sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory");
|
|
}
|
|
|
|
static __inline void
|
|
atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" andc %0, %0, %1 \n"
|
|
" stwcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
" sync" : "=&r" (tmp) : "r" (v), "r" (uip) : "cc", "memory");
|
|
}
|
|
|
|
#endif /* defined(_KERNEL) */
|
|
|
|
static inline unsigned int
|
|
_atomic_cas_uint(volatile unsigned int *p, unsigned int o, unsigned int n)
|
|
{
|
|
unsigned int rv;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" cmpw 0, %0, %4 \n"
|
|
" bne- 2f \n"
|
|
" stwcx. %3, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
"2: \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (n), "r" (o)
|
|
: "cc");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n))
|
|
|
|
static inline unsigned long
|
|
_atomic_cas_ulong(volatile unsigned long *p, unsigned long o, unsigned long n)
|
|
{
|
|
unsigned long rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" cmpd 0, %0, %4 \n"
|
|
" bne- 2f \n"
|
|
" stdcx. %3, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
"2: \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (n), "r" (o)
|
|
: "cc");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n))
|
|
|
|
static inline void *
|
|
_atomic_cas_ptr(volatile void *pp, void *o, void *n)
|
|
{
|
|
void * volatile *p = pp;
|
|
void *rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" cmpd 0, %0, %4 \n"
|
|
" bne- 2f \n"
|
|
" stdcx. %3, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
"2: \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (n), "r" (o)
|
|
: "cc");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n))
|
|
|
|
static inline unsigned int
|
|
_atomic_swap_uint(volatile unsigned int *p, unsigned int v)
|
|
{
|
|
unsigned int rv;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" stwcx. %3, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_swap_uint(_p, _v) _atomic_swap_uint((_p), (_v))
|
|
|
|
static inline unsigned long
|
|
_atomic_swap_ulong(volatile unsigned long *p, unsigned long v)
|
|
{
|
|
unsigned long rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" stdcx. %3, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_swap_ulong(_p, _v) _atomic_swap_ulong((_p), (_v))
|
|
|
|
static inline void *
|
|
_atomic_swap_ptr(volatile void *pp, void *v)
|
|
{
|
|
void * volatile *p = pp;
|
|
void *rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" stdcx. %3, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_swap_ptr(_p, _v) _atomic_swap_ptr((_p), (_v))
|
|
|
|
static inline unsigned int
|
|
_atomic_add_int_nv(volatile unsigned int *p, unsigned int v)
|
|
{
|
|
unsigned int rv;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" add %0, %3, %0 \n"
|
|
" stwcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc", "xer");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_add_int_nv(_p, _v) _atomic_add_int_nv((_p), (_v))
|
|
|
|
static inline unsigned long
|
|
_atomic_add_long_nv(volatile unsigned long *p, unsigned long v)
|
|
{
|
|
unsigned long rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" add %0, %3, %0 \n"
|
|
" stdcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc", "xer");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_add_long_nv(_p, _v) _atomic_add_long_nv((_p), (_v))
|
|
|
|
static inline unsigned int
|
|
_atomic_sub_int_nv(volatile unsigned int *p, unsigned int v)
|
|
{
|
|
unsigned int rv;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" subf %0, %3, %0 \n"
|
|
" stwcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc", "xer");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_sub_int_nv(_p, _v) _atomic_sub_int_nv((_p), (_v))
|
|
|
|
static inline unsigned long
|
|
_atomic_sub_long_nv(volatile unsigned long *p, unsigned long v)
|
|
{
|
|
unsigned long rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" subf %0, %3, %0 \n"
|
|
" stdcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "r" (v)
|
|
: "cc", "xer");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_sub_long_nv(_p, _v) _atomic_sub_long_nv((_p), (_v))
|
|
|
|
static inline unsigned int
|
|
_atomic_addic_int_nv(volatile unsigned int *p, unsigned int v)
|
|
{
|
|
unsigned int rv;
|
|
|
|
__asm volatile (
|
|
"1: lwarx %0, 0, %2 \n"
|
|
" addic %0, %0, %3 \n"
|
|
" stwcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "i" (v)
|
|
: "cc", "xer");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_inc_int_nv(_p) _atomic_addic_int_nv((_p), 1)
|
|
#define atomic_dec_int_nv(_p) _atomic_addic_int_nv((_p), -1)
|
|
|
|
static inline unsigned long
|
|
_atomic_addic_long_nv(volatile unsigned long *p, unsigned long v)
|
|
{
|
|
unsigned long rv;
|
|
|
|
__asm volatile (
|
|
"1: ldarx %0, 0, %2 \n"
|
|
" addic %0, %0, %3 \n"
|
|
" stdcx. %0, 0, %2 \n"
|
|
" bne- 1b \n"
|
|
: "=&r" (rv), "+m" (*p)
|
|
: "r" (p), "i" (v)
|
|
: "cc", "xer");
|
|
|
|
return (rv);
|
|
}
|
|
#define atomic_inc_long_nv(_p) _atomic_addic_long_nv((_p), 1)
|
|
#define atomic_dec_long_nv(_p) _atomic_addic_long_nv((_p), -1)
|
|
|
|
#define __membar(_f) do { __asm volatile(_f ::: "memory"); } while (0)
|
|
|
|
#if defined(MULTIPROCESSOR) || !defined(_KERNEL)
|
|
#define membar_enter() __membar("isync")
|
|
#define membar_exit() __membar("sync")
|
|
#define membar_producer() __membar("sync")
|
|
#define membar_consumer() __membar("isync")
|
|
#define membar_sync() __membar("sync")
|
|
#else
|
|
#define membar_enter() __membar("")
|
|
#define membar_exit() __membar("")
|
|
#define membar_producer() __membar("")
|
|
#define membar_consumer() __membar("")
|
|
#define membar_sync() __membar("")
|
|
#endif
|
|
|
|
#endif /* _MACHINE_ATOMIC_H_ */ |