Module Name:    src
Committed By:   christos
Date:           Sat Nov 23 14:41:38 UTC 2013

Modified Files:
        src/sys/sys: queue.h

Log Message:
Add __launder_type() from mrg to get the CIRCLEQ macros working again under
gcc-4.8. Mention that we discourage their use and that we retain the macros
for compatibility only.


To generate a diff of this commit:
cvs rdiff -u -r1.57 -r1.58 src/sys/sys/queue.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/sys/queue.h
diff -u src/sys/sys/queue.h:1.57 src/sys/sys/queue.h:1.58
--- src/sys/sys/queue.h:1.57	Thu Nov 21 14:04:19 2013
+++ src/sys/sys/queue.h	Sat Nov 23 09:41:38 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: queue.h,v 1.57 2013/11/21 19:04:19 christos Exp $	*/
+/*	$NetBSD: queue.h,v 1.58 2013/11/23 14:41:38 christos Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -600,8 +600,29 @@ struct {								\
 
 
 /*
- * Circular queue definitions.
+ * Circular queue definitions. Do not use. We still keep the macros
+ * for compatibility but because of pointer aliasing issues their use
+ * is discouraged!
  */
+
+/*
+ * We use this ugly hack to work around the fact that the CIRCLEQ
+ * macros violate the C aliasing rules by comparing 'struct name *'
+ * and 'struct type *' (see CIRCLEQ_HEAD() below).  Modern compilers
+ * (such as GCC 4.8) declare this to be always false and this makes
+ * most of the macros below not function correctly.
+ *
+ * This hack is only to be used for comparisons and thus can be
+ * fully const.  Do not use for assignment.
+ */
+static inline const void * __launder_type(const void *x);
+static inline const void *
+__launder_type(const void *x)
+{
+	__asm volatile("" : "+r" (x));
+	return x;
+}
+ 
 #if defined(_KERNEL) && defined(QUEUEDEBUG)
 #define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)				\
 	if ((head)->cqh_first != CIRCLEQ_ENDC(head) &&			\
@@ -609,11 +630,11 @@ struct {								\
 		panic("CIRCLEQ head forw %p %s:%d", (head),		\
 		      __FILE__, __LINE__);				\
 	if ((head)->cqh_last != CIRCLEQ_ENDC(head) &&			\
-	    (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head))		\
+	    (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head))	\
 		panic("CIRCLEQ head back %p %s:%d", (head),		\
 		      __FILE__, __LINE__);
 #define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)			\
-	if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) {			\
+	if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) {		\
 		if ((head)->cqh_last != (elm))				\
 			panic("CIRCLEQ elm last %p %s:%d", (elm),	\
 			      __FILE__, __LINE__);			\
@@ -622,7 +643,7 @@ struct {								\
 			panic("CIRCLEQ elm forw %p %s:%d", (elm),	\
 			      __FILE__, __LINE__);			\
 	}								\
-	if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) {			\
+	if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) {		\
 		if ((head)->cqh_first != (elm))				\
 			panic("CIRCLEQ elm first %p %s:%d", (elm),	\
 			      __FILE__, __LINE__);			\
@@ -741,7 +762,7 @@ struct {								\
 #define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
 #define	CIRCLEQ_LAST(head)		((head)->cqh_last)
 /* For comparisons */
-#define	CIRCLEQ_ENDC(head)		((const void *)(head))
+#define	CIRCLEQ_ENDC(head)		(__launder_type(head))
 /* For assignments */
 #define	CIRCLEQ_END(head)		((void *)(head))
 #define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)

Reply via email to