From owner-svn-src-all@FreeBSD.ORG Thu Sep 13 08:13:02 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8EDDC106566B; Thu, 13 Sep 2012 08:13:02 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 798438FC0A; Thu, 13 Sep 2012 08:13:02 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8D8D292050516; Thu, 13 Sep 2012 08:13:02 GMT (envelope-from ed@svn.freebsd.org) Received: (from ed@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8D8D2pU050511; Thu, 13 Sep 2012 08:13:02 GMT (envelope-from ed@svn.freebsd.org) Message-Id: <201209130813.q8D8D2pU050511@svn.freebsd.org> From: Ed Schouten Date: Thu, 13 Sep 2012 08:13:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240450 - head/sys/sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Sep 2012 08:13:02 -0000 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 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); \