[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 3/9] xen/ppc: Implement atomic.h
On 03.08.2023 01:02, Shawn Anastasio wrote: > Implement atomic.h for PPC, based off of the original Xen 3.2 > implementation. Since likely that originally came from Linux, did you cross check that Linux hasn't gained any bug fixes in the meantime? Other than this just a couple of nits; I'm not really qualified to review in particular the inline assembly here, I'm afraid. > --- /dev/null > +++ b/xen/arch/ppc/include/asm/atomic.h > @@ -0,0 +1,387 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * PowerPC64 atomic operations > + * > + * Copyright (C) 2001 Paul Mackerras <paulus@xxxxxxxxxx>, IBM > + * Copyright (C) 2001 Anton Blanchard <anton@xxxxxxxxxx>, IBM > + * Copyright Raptor Engineering LLC > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + */ > + > +#ifndef _ASM_PPC64_ATOMIC_H_ > +#define _ASM_PPC64_ATOMIC_H_ To fit the name, no "64" please. > +#include <xen/atomic.h> > + > +#include <asm/memory.h> > +#include <asm/system.h> > + > +static inline int atomic_read(const atomic_t *v) > +{ > + return *(volatile int *)&v->counter; > +} > + > +static inline int _atomic_read(atomic_t v) > +{ > + return v.counter; > +} > + > +static inline void atomic_set(atomic_t *v, int i) > +{ > + v->counter = i; > +} > + > +static inline void _atomic_set(atomic_t *v, int i) > +{ > + v->counter = i; > +} > + > +void __bad_atomic_read(const volatile void *p, void *res); > +void __bad_atomic_size(void); > + > +#define build_atomic_read(name, insn, type) > \ > + static inline type name(const volatile type *addr) > \ > + { > \ > + type ret; > \ > + asm volatile ( insn "%U1%X1 %0,%1" : "=r"(ret) : "m<>"(*addr) ); > \ As I think I had mentioned before, asm() contraints want a blank between closing quote and opend paren. I.e. like this asm volatile ( insn "%U1%X1 %0,%1" : "=r" (ret) : "m<>" (*addr) ); > +#define read_atomic(p) > \ > + ({ > \ > + union { > \ > + typeof(*(p)) val; > \ > + char c[0]; > \ > + } x_; > \ > + read_atomic_size(p, x_.c, sizeof(*(p))); > \ > + x_.val; > \ > + }) > + > +#define write_atomic(p, x) > \ > + do > \ > + { > \ > + typeof(*(p)) x_ = (x); > \ > + write_atomic_size(p, &x_, sizeof(*(p))); > \ > + } while ( 0 ) Up to here you use underscore-suffixed locals, but then ... > +#define add_sized(p, x) > \ > + ({ > \ > + typeof(*(p)) __x = (x); > \ ... you have even two prefixing underscores here. > + switch ( sizeof(*(p)) ) > \ > + { > \ > + case 1: > \ > + add_u8_sized((uint8_t *) (p), __x); > \ > + break; > \ > + case 2: > \ > + add_u16_sized((uint16_t *) (p), __x); > \ > + break; > \ > + case 4: > \ > + add_u32_sized((uint32_t *) (p), __x); > \ > + break; > \ > + default: > \ > + __bad_atomic_size(); > \ > + break; > \ > + } > \ > + }) > + > +static inline void atomic_add(int a, atomic_t *v) > +{ > + int t; > + > + asm volatile ( "1: lwarx %0,0,%3\n" > + "add %0,%2,%0\n" > + "stwcx. %0,0,%3\n" > + "bne- 1b" > + : "=&r"(t), "=m"(v->counter) > + : "r"(a), "r"(&v->counter), "m"(v->counter) : "cc" ); "+m" and then drop the last input? > +static inline int atomic_dec_if_positive(atomic_t *v) > +{ > + int t; > + > + asm volatile(PPC_ATOMIC_ENTRY_BARRIER > + "1: lwarx %0,0,%1 # atomic_dec_if_positive\n" > + "addic. %0,%0,-1\n" > + "blt- 2f\n" > + "stwcx. %0,0,%1\n" > + "bne- 1b\n" > + PPC_ATOMIC_EXIT_BARRIER > + "2:" : "=&r"(t) > + : "r"(&v->counter) : "cc", "memory"); Missing blanks near the parentheses. Would also be nice if the padding blanks actually vertically aligned the operands. > + return t; > +} > + > +static inline atomic_t atomic_compareandswap(atomic_t old, atomic_t new, > + atomic_t *v) > +{ > + atomic_t rc; > + rc.counter = __cmpxchg(&v->counter, old.counter, new.counter, > sizeof(int)); > + return rc; > +} > + > +#define arch_cmpxchg(ptr, o, n) > \ > + ({ > \ > + __typeof__(*(ptr)) _o_ = (o); > \ > + __typeof__(*(ptr)) _n_ = (n); > \ Problematic leading underscores again. > + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long) _o_, > \ > + (unsigned long) _n_, sizeof(*(ptr))); > \ > + }) > + > +static inline int atomic_cmpxchg(atomic_t *v, int old, int new) > +{ > + return arch_cmpxchg(&v->counter, old, new); > +} > + > +#define ATOMIC_OP(op, insn, suffix, sign) \ > + static inline void atomic_##op(int a, atomic_t *v) > \ > + { > \ > + int t; > \ > + asm volatile ( "1: lwarx %0,0,%3\n" > \ > + insn "%I2" suffix " %0,%0,%2\n" > \ > + "stwcx. %0,0,%3 \n" > \ > + "bne- 1b\n" > \ > + : "=&r"(t), "+m"(v->counter) > \ > + : "r" #sign(a), "r"(&v->counter) > \ > + : "cc" ); > \ > + } > + > +ATOMIC_OP(and, "and", ".", K) > + > +static inline int atomic_sub_and_test(int i, atomic_t *v) > +{ > + return atomic_sub_return(i, v) == 0; > +} > + > +static inline int atomic_inc_and_test(atomic_t *v) > +{ > + return atomic_add_return(1, v) == 0; > +} > + > +static inline int atomic_dec_and_test(atomic_t *v) > +{ > + return atomic_sub_return(1, v) == 0; > +} > + > +static inline int atomic_add_negative(int i, atomic_t *v) > +{ > + return atomic_add_return(i, v) < 0; > +} > + > +static inline int __atomic_add_unless(atomic_t *v, int a, int u) > +{ > + int c, old; > + > + c = atomic_read(v); > + while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) Btw, no real need to parenthesize v in cases like this one. Otoh a needs parenthesizing. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |