Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Sep 2012 08:13:02 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r240450 - head/sys/sys
Message-ID:  <201209130813.q8D8D2pU050511@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Thu Sep 13 08:13:01 2012
New Revision: 240450
URL: http://svn.freebsd.org/changeset/base/240450

Log:
  Rename __member2struct() to __containerof().
  
  Compared to __member2struct(), this macro has the following advantages:
  
  - It ensures that the type of the pointer is compatible with the member
    field of the structure (or a void pointer).
  - It works properly in combination with volatile and const, though
    unfortunately it drops these qualifiers from the returned value.
  
  mdf@ proposed to add the container_of() macro, just like Linux has.
  Eventually I decided against this, as <sys/param.h> is included all over
  the place. It seems container_of() on Linux is specific to the kernel,
  not userspace. I'd rather not pollute userspace with this.
  
  I also thought about adding __container_of(), but this would have two
  advantages. Xorg seems to already have a __container_of(), which is not
  compatible with this version. Also, the underscore in the middle
  conflicts with our existing macros (__offsetof, __rangeof, etc).
  
  I'm changing member2struct() to use its old code, as the extra
  strictness of this new macro conflicts with existing code (read: cxgb).
  
  MFC after:	1 month

Modified:
  head/sys/sys/cdefs.h
  head/sys/sys/param.h
  head/sys/sys/queue.h

Modified: head/sys/sys/cdefs.h
==============================================================================
--- head/sys/sys/cdefs.h	Thu Sep 13 07:25:41 2012	(r240449)
+++ head/sys/sys/cdefs.h	Thu Sep 13 08:13:01 2012	(r240450)
@@ -402,8 +402,22 @@
 #endif
 #define	__rangeof(type, start, end) \
 	(__offsetof(type, end) - __offsetof(type, start))
-#define	__member2struct(s, m, x)					\
-	((struct s *)(void *)((char *)(x) - __offsetof(struct s, m)))
+
+/*
+ * Given the pointer x to the member m of the struct s, return
+ * a pointer to the containing structure.  When using GCC, we first
+ * assign pointer x to a local variable, to check that its type is
+ * compatible with member m.
+ */
+#if __GNUC_PREREQ__(3, 1)
+#define	__containerof(x, s, m) ({					\
+	const volatile __typeof(((s *)0)->m) *__x = (x);		\
+	__DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\
+})
+#else
+#define	__containerof(x, s, m)						\
+	__DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
+#endif
 
 /*
  * Compiler-dependent macros to declare that functions take printf-like

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h	Thu Sep 13 07:25:41 2012	(r240449)
+++ head/sys/sys/param.h	Thu Sep 13 08:13:01 2012	(r240450)
@@ -331,10 +331,10 @@ __END_DECLS
 	((db) << (PAGE_SHIFT - DEV_BSHIFT))
 
 /*
- * Given the pointer x to the member m of the struct s, return
- * a pointer to the containing structure.
+ * Old spelling of __containerof().
  */
-#define	member2struct(s, m, x) __member2struct(s, m, x)
+#define	member2struct(s, m, x)						\
+	((struct s *)(void *)((char *)(x) - offsetof(struct s, m)))
 
 /*
  * Access a variable length array that has been declared as a fixed

Modified: head/sys/sys/queue.h
==============================================================================
--- head/sys/sys/queue.h	Thu Sep 13 07:25:41 2012	(r240449)
+++ head/sys/sys/queue.h	Thu Sep 13 08:13:01 2012	(r240450)
@@ -287,9 +287,8 @@ struct {								\
 } while (0)
 
 #define	STAILQ_LAST(head, type, field)					\
-	(STAILQ_EMPTY((head)) ?						\
-		NULL :							\
-		__member2struct(type, field.stqe_next, (head)->stqh_last))
+	(STAILQ_EMPTY((head)) ? NULL :					\
+	    __containerof((head)->stqh_last, struct type, field.stqe_next))
 
 #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
 
@@ -425,9 +424,8 @@ struct {								\
 #define	LIST_NEXT(elm, field)	((elm)->field.le_next)
 
 #define	LIST_PREV(elm, head, type, field)				\
-	((elm)->field.le_prev == &LIST_FIRST((head)) ?			\
-		NULL :							\
-		__member2struct(type, field.le_next, (elm)->field.le_prev))
+	((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL :		\
+	    __containerof((elm)->field.le_prev, struct type, field.le_next))
 
 #define	LIST_REMOVE(elm, field) do {					\
 	QMD_SAVELINK(oldnext, (elm)->field.le_next);			\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209130813.q8D8D2pU050511>