Skip to contentSkip to conversation

arch: Clean up asm/barrier.h implementations using asm-generic/barrier.h

PATCH New Jiri Slaby 1 participant 1 message Oct 27, 2015 Stable branch

lore
Share & tools
lore

Jiri Slaby

author
#0 lore raw

PATCH 1/1 arch: Clean up asm/barrier.h implementations using asm-generic/barrier.h

This patch has been added to the 3.12 stable tree. If you have any objections, please let us know.

===============

commit 93ea02bb84354370e51de803a9405f171f3edf88 upstream.

We're going to be adding a few new barrier primitives, and in order to avoid endless duplication make more agressive use of asm-generic/barrier.h.

Change the asm-generic/barrier.h such that it allows partial barrier definitions and fills out the rest with defaults.

There are a few architectures (m32r, m68k) that could probably do away with their barrier.h file entirely but are kept for now due to their unconventional nop() implementation.

Cc Michael Ellerman <[email protected]>
Cc Michael Neuling <[email protected]>
Cc Russell King <[email protected]>
Cc Heiko Carstens <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Martin Schwidefsky <[email protected]>
Cc Victor Kaplansky <[email protected]>
Cc Tony Luck <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Frederic Weisbecker <[email protected]>
---
 arch/alpha/include/asm/barrier.h      | 25 +++--------
 arch/arc/include/asm/Kbuild           |  1 +
 arch/avr32/include/asm/barrier.h      | 17 +++-----
 arch/blackfin/include/asm/barrier.h   | 18 +-------
 arch/cris/include/asm/Kbuild          |  1 +
 arch/cris/include/asm/barrier.h       | 25 -----------
 arch/frv/include/asm/barrier.h        |  8 +---
 arch/hexagon/include/asm/Kbuild       |  1 +
 arch/m32r/include/asm/barrier.h       | 80
+----------------------------------
 arch/m68k/include/asm/barrier.h       | 14 +-----
 arch/microblaze/include/asm/Kbuild    |  1 +
 arch/microblaze/include/asm/barrier.h | 27 ------------
 arch/mn10300/include/asm/Kbuild       |  1 +
 arch/mn10300/include/asm/barrier.h    | 37 ----------------
 arch/parisc/include/asm/Kbuild        |  1 +
 arch/parisc/include/asm/barrier.h     | 35 ---------------
 arch/score/include/asm/Kbuild         |  1 +
 arch/score/include/asm/barrier.h      | 16 -------
 arch/sh/include/asm/barrier.h         | 21 ++-------
 arch/sparc/include/asm/barrier_32.h   | 12 +-----
 arch/tile/include/asm/barrier.h       | 68 +----------------------------
 arch/unicore32/include/asm/barrier.h  | 11 +----
 arch/xtensa/include/asm/barrier.h     |  9 +---
 include/asm-generic/barrier.h         | 42 ++++++++++++------
 24 files changed, 58 insertions(+), 414 deletions(-)
 delete mode 100644 arch/cris/include/asm/barrier.h
 delete mode 100644 arch/microblaze/include/asm/barrier.h
 delete mode 100644 arch/mn10300/include/asm/barrier.h
 delete mode 100644 arch/parisc/include/asm/barrier.h
 delete mode 100644 arch/score/include/asm/barrier.h
(quoted diff) +0 -0

b/arch/alpha/include/asm/barrier.h
index ce8860a0b32d..3832bdb794fe 100644

arch/alpha/include/asm/barrier.h +5 -17
@@ -3,33 +3,18 @@
  #include <asm/compiler.h>
 -#define mb() \
-__asm__ __volatile__("mb": : :"memory")
+#define mb()	__asm__ __volatile__("mb": : :"memory")
+#define rmb()	__asm__ __volatile__("mb": : :"memory")
+#define wmb()	__asm__ __volatile__("wmb": : :"memory")
 -#define rmb() \
-__asm__ __volatile__("mb": : :"memory")
-
-#define wmb() \
-__asm__ __volatile__("wmb": : :"memory")
-
-#define read_barrier_depends() \
-__asm__ __volatile__("mb": : :"memory")
+#define read_barrier_depends() __asm__ __volatile__("mb": : :"memory")
  #ifdef CONFIG_SMP
 #define __ASM_SMP_MB	"\tmb\n"
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
 #else
 #define __ASM_SMP_MB
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while (0)
 #endif
 -#define set_mb(var, value) \
-do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
  #endif		/* __BARRIER_H */
arch/arc/include/asm/Kbuild +1 -0
index d8dd660898b9..5c359cf55934 100644
@@ -46,3 +46,4 @@ generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += barrier.h
(quoted diff) +0 -0

b/arch/avr32/include/asm/barrier.h
index 0961275373db..715100790fd0 100644

arch/avr32/include/asm/barrier.h +4 -11
@@ -8,22 +8,15 @@
 #ifndef __ASM_AVR32_BARRIER_H
 #define __ASM_AVR32_BARRIER_H
 -#define nop()			asm volatile("nop")
-
-#define mb()			asm volatile("" : : : "memory")
-#define rmb()			mb()
-#define wmb()			asm volatile("sync 0" : : : "memory")
-#define read_barrier_depends()  do { } while(0)
-#define set_mb(var, value)      do { var = value; mb(); } while(0)
+/*
+ * Weirdest thing ever.. no full barrier, but it has a write barrier!
+ */
+#define wmb()	asm volatile("sync 0" : : : "memory")
  #ifdef CONFIG_SMP
 # error "The AVR32 port does not support SMP"
-#else
-# define smp_mb()		barrier()
-# define smp_rmb()		barrier()
-# define smp_wmb()		barrier()
-# define smp_read_barrier_depends() do { } while(0)
 #endif
 +#include <asm-generic/barrier.h>
  #endif /* __ASM_AVR32_BARRIER_H */
(quoted diff) +0 -0

b/arch/blackfin/include/asm/barrier.h
index ebb189507dd7..19283a16ac08 100644

arch/blackfin/include/asm/barrier.h +0 -0
@@ -23,26 +23,10 @@
 # define rmb()	do { barrier(); smp_check_barrier(); } while (0)
 # define wmb()	do { barrier(); smp_mark_barrier(); } while (0)
 # define read_barrier_depends()	do { barrier(); smp_check_barrier(); }

while (0)
-#else
-# define mb() barrier()
-# define rmb() barrier()
-# define wmb() barrier()
-# define read_barrier_depends() do { } while (0)
#endif
-#else /* !CONFIG_SMP */
-
-#define mb() barrier()
-#define rmb() barrier()
-#define wmb() barrier()
-#define read_barrier_depends() do { } while (0)
-
#endif /* !CONFIG_SMP */
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define smp_read_barrier_depends() read_barrier_depends()
+#include <asm-generic/barrier.h>
#endif /* _BLACKFIN_BARRIER_H */

arch/cris/include/asm/Kbuild +1 -0
index c8325455520e..497776e4777d 100644
@@ -11,3 +11,4 @@ generic-y += module.h
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += barrier.h
(quoted diff) +0 -0

b/arch/cris/include/asm/barrier.h
deleted file mode 100644
index 198ad7fa6b25..000000000000

arch/cris/include/asm/barrier.h deleted +0 -25
@@ -1,25 +0,0 @@
-#ifndef __ASM_CRIS_BARRIER_H
-#define __ASM_CRIS_BARRIER_H
-
-#define nop() __asm__ __volatile__ ("nop");
-
-#define barrier() __asm__ __volatile__("": : :"memory")
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define read_barrier_depends() do { } while(0)
-#define set_mb(var, value)  do { var = value; mb(); } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()        mb()
-#define smp_rmb()       rmb()
-#define smp_wmb()       wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
-#else
-#define smp_mb()        barrier()
-#define smp_rmb()       barrier()
-#define smp_wmb()       barrier()
-#define smp_read_barrier_depends()     do { } while(0)
-#endif
-
-#endif /* __ASM_CRIS_BARRIER_H */
arch/frv/include/asm/barrier.h +1 -6
index 06776ad9f5e9..abbef470154c 100644
@@ -17,13 +17,7 @@
 #define mb()			asm volatile ("membar" : : :"memory")
 #define rmb()			asm volatile ("membar" : : :"memory")
 #define wmb()			asm volatile ("membar" : : :"memory")
-#define read_barrier_depends()	do { } while (0)
 -#define smp_mb()			barrier()
-#define smp_rmb()			barrier()
-#define smp_wmb()			barrier()
-#define smp_read_barrier_depends()	do {} while(0)
-#define set_mb(var, value) \
-	do { var = (value); barrier(); } while (0)
+#include <asm-generic/barrier.h>
  #endif /* _ASM_BARRIER_H */
(quoted diff) +0 -0

b/arch/hexagon/include/asm/Kbuild
index 1da17caac23c..a214fa4502f0 100644

arch/hexagon/include/asm/Kbuild +1 -0
@@ -53,3 +53,4 @@ generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += xor.h
+generic-y += barrier.h
(quoted diff) +0 -0

b/arch/m32r/include/asm/barrier.h
index 6976621efd3f..1a40265e8d88 100644

arch/m32r/include/asm/barrier.h +1 -78

82 lines not on this page · raw message

(quoted diff) +0 -0

b/arch/m68k/include/asm/barrier.h
index 445ce22c23cb..15c5f77c1614 100644

arch/m68k/include/asm/barrier.h +1 -11
@@ -1,20 +1,8 @@
 #ifndef _M68K_BARRIER_H
 #define _M68K_BARRIER_H
 -/*
- * Force strict CPU ordering.
- * Not really required on m68k...
- */
 #define nop()		do { asm volatile ("nop"); barrier(); } while (0)
-#define mb()		barrier()
-#define rmb()		barrier()
-#define wmb()		barrier()
-#define read_barrier_depends()	((void)0)
-#define set_mb(var, value)	({ (var) = (value); wmb(); })
 -#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	((void)0)
+#include <asm-generic/barrier.h>
  #endif /* _M68K_BARRIER_H */
(quoted diff) +0 -0

b/arch/microblaze/include/asm/Kbuild
index d3c51a6a601d..9197b379d005 100644

arch/microblaze/include/asm/Kbuild +1 -0
@@ -3,3 +3,4 @@ generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
 generic-y += syscalls.h
+generic-y += barrier.h
(quoted diff) +0 -0

b/arch/microblaze/include/asm/barrier.h
deleted file mode 100644
index df5be3e87044..000000000000

arch/microblaze/include/asm/barrier.h deleted +0 -4
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General

Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_BARRIER_H
-#define _ASM_MICROBLAZE_BARRIER_H
-
-#define nop() asm volatile ("nop")
-
-#define smp_read_barrier_depends() do {} while (0)
-#define read_barrier_depends() do {} while (0)
-
-#define mb() barrier()
-#define rmb() mb()
-#define wmb() mb()
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-
-#endif /* _ASM_MICROBLAZE_BARRIER_H */

(quoted diff) +0 -0

b/arch/mn10300/include/asm/Kbuild
index c5d767028306..a530bca92014 100644

arch/mn10300/include/asm/Kbuild +1 -0
@@ -2,3 +2,4 @@
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
+generic-y += barrier.h
(quoted diff) +0 -0

b/arch/mn10300/include/asm/barrier.h
deleted file mode 100644
index 2bd97a5c8af7..000000000000

arch/mn10300/include/asm/barrier.h deleted +0 -37
@@ -1,37 +0,0 @@
-/* MN10300 memory barrier definitions
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells ([email protected])
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_BARRIER_H
-#define _ASM_BARRIER_H
-
-#define nop()	asm volatile ("nop")
-
-#define mb()	asm volatile ("": : :"memory")
-#define rmb()	mb()
-#define wmb()	asm volatile ("": : :"memory")
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define set_mb(var, value)  do { xchg(&var, value); } while (0)
-#else  /* CONFIG_SMP */
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define set_mb(var, value)  do { var = value;  mb(); } while (0)
-#endif /* CONFIG_SMP */
-
-#define set_wmb(var, value) do { var = value; wmb(); } while (0)
-
-#define read_barrier_depends()		do {} while (0)
-#define smp_read_barrier_depends()	do {} while (0)
-
-#endif /* _ASM_BARRIER_H */
arch/parisc/include/asm/Kbuild +0 -0
index ff4c9faed546..827a8465a536 100644
@@ -4,3 +4,4 @@ generic-y += word-at-a-time.h auxvec.h user.h cputime.h

emergency-restart.h \
div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
poll.h xor.h clkdev.h exec.h
generic-y += trace_clock.h
+generic-y += barrier.h

(quoted diff) +0 -0

b/arch/parisc/include/asm/barrier.h
deleted file mode 100644
index e77d834aa803..000000000000

arch/parisc/include/asm/barrier.h deleted +0 -35
@@ -1,35 +0,0 @@
-#ifndef __PARISC_BARRIER_H
-#define __PARISC_BARRIER_H
-
-/*
-** This is simply the barrier() macro from linux/kernel.h but when serial.c
-** uses tqueue.h uses smp_mb() defined using barrier(), linux/kernel.h
-** hasn't yet been included yet so it fails, thus repeating the macro here.
-**
-** PA-RISC architecture allows for weakly ordered memory accesses although
-** none of the processors use it. There is a strong ordered bit that is
-** set in the O-bit of the page directory entry. Operating systems that
-** can not tolerate out of order accesses should set this bit when mapping
-** pages. The O-bit of the PSW should also be set to 1 (I don't believe any
-** of the processor implemented the PSW O-bit). The PCX-W ERS states that
-** the TLB O-bit is not implemented so the page directory does not need to
-** have the O-bit set when mapping pages (section 3.1). This section also
-** states that the PSW Y, Z, G, and O bits are not implemented.
-** So it looks like nothing needs to be done for parisc-linux (yet).
-** (thanks to chada for the above comment -ggg)
-**
-** The __asm__ op below simple prevents gcc/ld from reordering
-** instructions across the mb() "call".
-*/
-#define mb()		__asm__ __volatile__("":::"memory")	/* barrier() */
-#define rmb()		mb()
-#define wmb()		mb()
-#define smp_mb()	mb()
-#define smp_rmb()	mb()
-#define smp_wmb()	mb()
-#define smp_read_barrier_depends()	do { } while(0)
-#define read_barrier_depends()		do { } while(0)
-
-#define set_mb(var, value)		do { var = value; mb(); } while (0)
-
-#endif /* __PARISC_BARRIER_H */
arch/score/include/asm/Kbuild +1 -0
index e1c7bb999b06..825c7184fced 100644
@@ -4,3 +4,4 @@ header-y +=
 generic-y += clkdev.h
 generic-y += trace_clock.h
 generic-y += xor.h
+generic-y += barrier.h
(quoted diff) +0 -0

b/arch/score/include/asm/barrier.h
deleted file mode 100644
index 0eacb6471e6d..000000000000

arch/score/include/asm/barrier.h deleted +0 -16
@@ -1,16 +0,0 @@
-#ifndef _ASM_SCORE_BARRIER_H
-#define _ASM_SCORE_BARRIER_H
-
-#define mb()		barrier()
-#define rmb()		barrier()
-#define wmb()		barrier()
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-
-#define read_barrier_depends()		do {} while (0)
-#define smp_read_barrier_depends()	do {} while (0)
-
-#define set_mb(var, value) 		do {var = value; wmb(); } while (0)
-
-#endif /* _ASM_SCORE_BARRIER_H */
arch/sh/include/asm/barrier.h +1 -5
index 72c103dae300..43715308b068 100644
@@ -26,29 +26,14 @@
 #if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5)
 #define mb()		__asm__ __volatile__ ("synco": : :"memory")
 #define rmb()		mb()
-#define wmb()		__asm__ __volatile__ ("synco": : :"memory")
+#define wmb()		mb()
 #define ctrl_barrier()	__icbi(PAGE_OFFSET)
-#define read_barrier_depends()	do { } while(0)
 #else
-#define mb()		__asm__ __volatile__ ("": : :"memory")
-#define rmb()		mb()
-#define wmb()		__asm__ __volatile__ ("": : :"memory")
 #define ctrl_barrier()	__asm__ __volatile__

("nop;nop;nop;nop;nop;nop;nop;nop")
-#define read_barrier_depends() do { } while(0)
-#endif
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
#endif
#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+#include <asm-generic/barrier.h>
+
#endif /* __ASM_SH_BARRIER_H */

(quoted diff) +0 -0

b/arch/sparc/include/asm/barrier_32.h
index c1b76654ee76..ae69eda288f4 100644

arch/sparc/include/asm/barrier_32.h +2 -9
@@ -1,15 +1,7 @@
 #ifndef __SPARC_BARRIER_H
 #define __SPARC_BARRIER_H
 -/* XXX Change this if we ever use a PSO mode kernel. */
-#define mb()	__asm__ __volatile__ ("" : : : "memory")
-#define rmb()	mb()
-#define wmb()	mb()
-#define read_barrier_depends()	do { } while(0)
-#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
-#define smp_mb()	__asm__ __volatile__("":::"memory")
-#define smp_rmb()	__asm__ __volatile__("":::"memory")
-#define smp_wmb()	__asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends()	do { } while(0)
+#include <asm/processor.h> /* for nop() */
+#include <asm-generic/barrier.h>
  #endif /* !(__SPARC_BARRIER_H) */
(quoted diff) +0 -0

b/arch/tile/include/asm/barrier.h
index a9a73da5865d..b5a05d050a8f 100644

arch/tile/include/asm/barrier.h +1 -65

76 lines not on this page · raw message

(quoted diff) +0 -0

b/arch/unicore32/include/asm/barrier.h
index a6620e5336b6..83d6a520f4bd 100644

arch/unicore32/include/asm/barrier.h +1 -9
@@ -14,15 +14,6 @@
 #define dsb() __asm__ __volatile__ ("" : : : "memory")
 #define dmb() __asm__ __volatile__ ("" : : : "memory")
 -#define mb()				barrier()
-#define rmb()				barrier()
-#define wmb()				barrier()
-#define smp_mb()			barrier()
-#define smp_rmb()			barrier()
-#define smp_wmb()			barrier()
-#define read_barrier_depends()		do { } while (0)
-#define smp_read_barrier_depends()	do { } while (0)
-
-#define set_mb(var, value)		do { var = value; smp_mb(); } while (0)
+#include <asm-generic/barrier.h>
  #endif /* __UNICORE_BARRIER_H__ */
(quoted diff) +0 -0

b/arch/xtensa/include/asm/barrier.h
index ef021677d536..e1ee6b51dfc5 100644

arch/xtensa/include/asm/barrier.h +1 -6
@@ -9,21 +9,14 @@
 #ifndef _XTENSA_SYSTEM_H
 #define _XTENSA_SYSTEM_H
 -#define smp_read_barrier_depends() do { } while(0)
-#define read_barrier_depends() do { } while(0)
-
 #define mb()  ({ __asm__ __volatile__("memw" : : : "memory"); })
 #define rmb() barrier()
 #define wmb() mb()
  #ifdef CONFIG_SMP
 #error smp_* not defined
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
 #endif
 -#define set_mb(var, value)	do { var = value; mb(); } while (0)
+#include <asm-generic/barrier.h>
  #endif /* _XTENSA_SYSTEM_H */
include/asm-generic/barrier.h +8 -4
index 01613b382b0e..6f692f8ac664 100644
@@ -1,4 +1,5 @@
-/* Generic barrier definitions, based on MN10300 definitions.
+/*
+ * Generic barrier definitions, originally based on MN10300 definitions.
  *
  * It should be possible to use these on really simple architectures,
  * but it serves more as a starting point for new ports.
@@ -16,35 +17,50 @@
  #ifndef __ASSEMBLY__
 -#define nop() asm volatile ("nop")
+#include <linux/compiler.h>
+
+#ifndef nop
+#define nop()	asm volatile ("nop")
+#endif
  /*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
+ * Force strict CPU ordering. And yes, this is required on UP too when

we're
+ * talking to devices.
*
- * This implementation only contains a compiler barrier.
+ * Fall back to compiler barriers if nothing better is provided. */
-#define mb() asm volatile ("": : :"memory")
+#ifndef mb
+#define mb() barrier()
+#endif
+
+#ifndef rmb
#define rmb() mb()
-#define wmb() asm volatile ("": : :"memory")
+#endif
+
+#ifndef wmb
+#define wmb() mb()
+#endif
+
+#ifndef read_barrier_depends
+#define read_barrier_depends() do { } while (0)
+#endif
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
+#define smp_read_barrier_depends() read_barrier_depends()
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
+#define smp_read_barrier_depends() do { } while (0)
#endif
-#define set_mb(var, value) do { var = value; mb(); } while (0)
-#define set_wmb(var, value) do { var = value; wmb(); } while (0) -
-#define read_barrier_depends() do {} while (0)
-#define smp_read_barrier_depends() do {} while (0)
+#ifndef set_mb
+#define set_mb(var, value) do { (var) = (value); mb(); } while (0) +#endif
#define smp_store_release(p, v) \
do { \

Signature · 1 line
2.6.2