NetBSD Problem Report #58729

From www@netbsd.org  Tue Oct  8 13:47:39 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits)
	 client-signature RSA-PSS (2048 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 18F961A923B
	for <gnats-bugs@gnats.NetBSD.org>; Tue,  8 Oct 2024 13:47:39 +0000 (UTC)
Message-Id: <20241008134737.EE4561A923D@mollari.NetBSD.org>
Date: Tue,  8 Oct 2024 13:47:37 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: container_of is not documented or available in userland
X-Send-Pr-Version: www-1.0

>Number:         58729
>Category:       lib
>Synopsis:       container_of is not documented or available in userland
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 08 13:50:00 +0000 2024
>Last-Modified:  Tue Oct 08 22:55:01 +0000 2024
>Originator:     Taylor R Campbell
>Release:        current, 10, 9, ...
>Organization:
The Struct &NetBSD->foundation
>Environment:
>Description:
1. container_of is missing a man page
2. container_of is defined in libkern.h, not, say, sys/container_of.h, so it isn't available in userland
>How-To-Repeat:
discussion on tech-userlevel
>Fix:
Yes, please!

>Audit-Trail:
From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Cc: 
Subject: Re: lib/58729: container_of is not documented or available in userland
Date: Tue, 8 Oct 2024 14:28:33 +0000

 Small complication: container_of is defined in libkern.h and uses
 offsetof which, for the kernel, is also defined in libkern.h.

 So just moving container_of to another header file would create a
 circular dependency (libkern.h uses sys/container_of.h for
 container_of, and is used by sys/container_of.h for offsetof).

 To avoid that, we could:

 (a) split offsetof into another header file (maybe we should add
     sys/stddef.h), or

 (b) update all container_of users in kernel to use sys/container_of.h
     explicitly so libkern.h doesn't have to expose container_of
     itself.

From: Jason Thorpe <thorpej@me.com>
To: Taylor Campbell <riastradh@netbsd.org>
Cc: "gnats-bugs@netbsd.org" <gnats-bugs@NetBSD.org>,
 "netbsd-bugs@netbsd.org" <netbsd-bugs@NetBSD.org>
Subject: Re: lib/58729: container_of is not documented or available in
 userland
Date: Tue, 8 Oct 2024 09:28:31 -0700

 > On Oct 8, 2024, at 7:28=E2=80=AFAM, Taylor R Campbell =
 <riastradh@netbsd.org> wrote:
 >=20
 > (a) split offsetof into another header file (maybe we should add
 >    sys/stddef.h), or

 This seems like the best solution.

 -- thorpej

From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Cc: 
Subject: Re: lib/58729: container_of is not documented or available in userland
Date: Tue, 8 Oct 2024 17:18:20 +0000

 This is a multi-part message in MIME format.
 --=_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS

 Here's a draft that just duplicates the include/stddef.h definition of
 offsetof for now.  It coexists peacefully in the kernel with the
 libkern.h definition -- with #ifndef offsetof hacks in both places.
 Not great but it'll serve to address the immediate issue without
 deciding how best to disentangle things.

 Another thought I had is that it might be worthwhile to have
 __container_of and __offsetof macros that would avoid namespace
 pollution, and only expose container_of and offsetof if you explicitly
 ask for a header file defined to use them.  But I don't have a use
 case for this right now so I won't do anything about this.

 --=_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS
 Content-Type: text/plain; charset="ISO-8859-1"; name="pr58729-containerofh"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment; filename="pr58729-containerofh.patch"

 # HG changeset patch
 # User Taylor R Campbell <riastradh@NetBSD.org>
 # Date 1728402416 0
 #      Tue Oct 08 15:46:56 2024 +0000
 # Branch trunk
 # Node ID 32a19974e47ea523810619381ab6d96671c537c9
 # Parent  324886ee2905fda3948217e0fd3c6ca7f4cf32dc
 # EXP-Topic riastradh-pr58729-containerof
 container_of: New header file sys/container_of.h for this.

 PR lib/58729: container_of is not documented or available in userland

 diff -r 324886ee2905 -r 32a19974e47e sys/lib/libkern/libkern.h
 --- a/sys/lib/libkern/libkern.h	Tue Oct 08 12:49:01 2024 +0000
 +++ b/sys/lib/libkern/libkern.h	Tue Oct 08 15:46:56 2024 +0000
 @@ -323,46 +323,7 @@ tolower(int ch)
  #endif
  #endif
 =20
 -/*
 - * Return the container of an embedded struct.  Given x =3D &c->f,
 - * container_of(x, T, f) yields c, where T is the type of c.  Example:
 - *
 - *	struct foo { ... };
 - *	struct bar {
 - *		int b_x;
 - *		struct foo b_foo;
 - *		...
 - *	};
 - *
 - *	struct bar b;
 - *	struct foo *fp =3D &b.b_foo;
 - *
 - * Now we can get at b from fp by:
 - *
 - *	struct bar *bp =3D container_of(fp, struct bar, b_foo);
 - *
 - * The 0*sizeof((PTR) - ...) causes the compiler to warn if the type of
 - * *fp does not match the type of struct bar::b_foo.
 - * We skip the validation for coverity runs to avoid warnings.
 - */
 -#if defined(__COVERITY__) || defined(__LGTM_BOT__)
 -#define __validate_container_of(PTR, TYPE, FIELD) 0
 -#define __validate_const_container_of(PTR, TYPE, FIELD) 0
 -#else
 -#define __validate_container_of(PTR, TYPE, FIELD)			\
 -    (0 * sizeof((PTR) - &((TYPE *)(((char *)(PTR)) -			\
 -    offsetof(TYPE, FIELD)))->FIELD))
 -#define __validate_const_container_of(PTR, TYPE, FIELD)			\
 -    (0 * sizeof((PTR) - &((const TYPE *)(((const char *)(PTR)) -	\
 -    offsetof(TYPE, FIELD)))->FIELD))
 -#endif
 -
 -#define	container_of(PTR, TYPE, FIELD)					\
 -    ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, FIELD))			\
 -	+ __validate_container_of(PTR, TYPE, FIELD))
 -#define	const_container_of(PTR, TYPE, FIELD)				\
 -    ((const TYPE *)(((const char *)(PTR)) - offsetof(TYPE, FIELD))	\
 -	+ __validate_const_container_of(PTR, TYPE, FIELD))
 +#include <sys/container_of.h>
 =20
  /* Prototypes for which GCC built-ins exist. */
  void	*memcpy(void *, const void *, size_t);
 diff -r 324886ee2905 -r 32a19974e47e sys/sys/container_of.h
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 +++ b/sys/sys/container_of.h	Tue Oct 08 15:46:56 2024 +0000
 @@ -0,0 +1,101 @@
 +/*	$NetBSD$	*/
 +
 +/*-
 + * Copyright (c) 2013 The NetBSD Foundation, Inc.
 + * All rights reserved.
 + *
 + * This code is derived from software contributed to The NetBSD Foundation
 + * by Taylor R. Campbell.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTO=
 RS
 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIM=
 ITED
 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICU=
 LAR
 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTO=
 RS
 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF =
 THE
 + * POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#ifndef	_SYS_CONTAINER_OF_H_
 +#define	_SYS_CONTAINER_OF_H_
 +
 +#include <sys/ansi.h>
 +
 +#ifdef	_BSD_SIZE_T_
 +typedef	_BSD_SIZE_T_	size_t;
 +#undef	_BSD_SIZE_T_
 +#endif
 +
 +/*
 + * XXX Avoid duplicating this with sys/lib/libkern/libkern.h and
 + * include/stddef.h.
 + */
 +#ifndef offsetof
 +#if __GNUC_PREREQ__(4, 0)
 +#define	offsetof(type, member)	__builtin_offsetof(type, member)
 +#elif !defined(__cplusplus)
 +#define	offsetof(type, member)	((size_t)(unsigned long)(&((type *)0)->memb=
 er))
 +#else
 +#if !__GNUC_PREREQ__(3, 4)
 +#define __offsetof__(a) a
 +#endif
 +#define	offsetof(type, member) __offsetof__((reinterpret_cast<size_t> \
 +    (&reinterpret_cast<const volatile char &>(static_cast<type *>(0)->memb=
 er))))
 +#endif
 +#endif
 +
 +/*
 + * Return the container of an embedded struct.  Given x =3D &c->f,
 + * container_of(x, T, f) yields c, where T is the type of c.  Example:
 + *
 + *	struct foo { ... };
 + *	struct bar {
 + *		int b_x;
 + *		struct foo b_foo;
 + *		...
 + *	};
 + *
 + *	struct bar b;
 + *	struct foo *fp =3D &b.b_foo;
 + *
 + * Now we can get at b from fp by:
 + *
 + *	struct bar *bp =3D container_of(fp, struct bar, b_foo);
 + *
 + * The 0*sizeof((PTR) - ...) causes the compiler to warn if the type of
 + * *fp does not match the type of struct bar::b_foo.
 + * We skip the validation for coverity runs to avoid warnings.
 + */
 +#if defined(__COVERITY__) || defined(__LGTM_BOT__)
 +#define __validate_container_of(PTR, TYPE, FIELD) 0
 +#define __validate_const_container_of(PTR, TYPE, FIELD) 0
 +#else
 +#define __validate_container_of(PTR, TYPE, FIELD)			\
 +    (0 * sizeof((PTR) - &((TYPE *)(((char *)(PTR)) -			\
 +    offsetof(TYPE, FIELD)))->FIELD))
 +#define __validate_const_container_of(PTR, TYPE, FIELD)			\
 +    (0 * sizeof((PTR) - &((const TYPE *)(((const char *)(PTR)) -	\
 +    offsetof(TYPE, FIELD)))->FIELD))
 +#endif
 +
 +#define	container_of(PTR, TYPE, FIELD)					\
 +    ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, FIELD))			\
 +	+ __validate_container_of(PTR, TYPE, FIELD))
 +#define	const_container_of(PTR, TYPE, FIELD)				\
 +    ((const TYPE *)(((const char *)(PTR)) - offsetof(TYPE, FIELD))	\
 +	+ __validate_const_container_of(PTR, TYPE, FIELD))
 +
 +#endif	/* _SYS_CONTAINER_OF_H_ */
 # HG changeset patch
 # User Taylor R Campbell <riastradh@NetBSD.org>
 # Date 1728407830 0
 #      Tue Oct 08 17:17:10 2024 +0000
 # Branch trunk
 # Node ID 4529dd9470d4274e62fb97bbbfc358f45342be28
 # Parent  32a19974e47ea523810619381ab6d96671c537c9
 # EXP-Topic riastradh-pr58729-containerof
 container_of(3): New man page.

 PR lib/58729: container_of is not documented or available in userland

 diff -r 32a19974e47e -r 4529dd9470d4 distrib/sets/lists/comp/mi
 --- a/distrib/sets/lists/comp/mi	Tue Oct 08 15:46:56 2024 +0000
 +++ b/distrib/sets/lists/comp/mi	Tue Oct 08 17:17:10 2024 +0000
 @@ -7024,8 +7024,10 @@
  ./usr/share/man/cat3/conj.0			comp-c-catman		complex,.cat
  ./usr/share/man/cat3/conjf.0			comp-c-catman		complex,.cat
  ./usr/share/man/cat3/conjl.0			comp-c-catman		complex,.cat
 +./usr/share/man/cat3/const_container_of.0	comp-c-catman		.cat
  ./usr/share/man/cat3/consttime_bcmp.0		comp-obsolete		obsolete
  ./usr/share/man/cat3/consttime_memequal.0	comp-c-catman		.cat
 +./usr/share/man/cat3/container_of.0		comp-c-catman		.cat
  ./usr/share/man/cat3/copysign.0			comp-c-catman		.cat
  ./usr/share/man/cat3/copysignf.0		comp-c-catman		.cat
  ./usr/share/man/cat3/copysignl.0		comp-c-catman		.cat
 @@ -15552,8 +15554,10 @@
  ./usr/share/man/html3/conj.html			comp-c-htmlman		complex,html
  ./usr/share/man/html3/conjf.html		comp-c-htmlman		complex,html
  ./usr/share/man/html3/conjl.html		comp-c-htmlman		complex,html
 +./usr/share/man/html3/const_container_of.html	comp-c-htmlman		html
  ./usr/share/man/html3/consttime_bcmp.html	comp-obsolete		obsolete
  ./usr/share/man/html3/consttime_memequal.html	comp-c-htmlman		html
 +./usr/share/man/html3/container_of.html		comp-c-htmlman		html
  ./usr/share/man/html3/copysign.html		comp-c-htmlman		html
  ./usr/share/man/html3/copysignf.html		comp-c-htmlman		html
  ./usr/share/man/html3/copysignl.html		comp-c-htmlman		html
 @@ -24025,8 +24029,10 @@
  ./usr/share/man/man3/conj.3			comp-c-man		complex,.man
  ./usr/share/man/man3/conjf.3			comp-c-man		complex,.man
  ./usr/share/man/man3/conjl.3			comp-c-man		complex,.man
 +./usr/share/man/man3/const_container_of.3	comp-c-man		.man
  ./usr/share/man/man3/consttime_bcmp.3		comp-obsolete		obsolete
  ./usr/share/man/man3/consttime_memequal.3	comp-c-man		.man
 +./usr/share/man/man3/container_of.3		comp-c-man		.man
  ./usr/share/man/man3/copysign.3			comp-c-man		.man
  ./usr/share/man/man3/copysignf.3		comp-c-man		.man
  ./usr/share/man/man3/copysignl.3		comp-c-man		.man
 diff -r 32a19974e47e -r 4529dd9470d4 share/man/man3/Makefile
 --- a/share/man/man3/Makefile	Tue Oct 08 15:46:56 2024 +0000
 +++ b/share/man/man3/Makefile	Tue Oct 08 17:17:10 2024 +0000
 @@ -7,7 +7,8 @@ MAN=3D	_DIAGASSERT.3 __CONCAT.3 __FPTRCAST
  	__builtin_return_address.3 \
  	__builtin_types_compatible_p.3 __insn_barrier.3 \
  	assert.3 attribute.3 bitmap.3 bitops.3 bits.3 bitstring.3 \
 -	cdefs.3 dirent.3 dlfcn.3 dlinfo.3 dl_iterate_phdr.3 end.3 \
 +	cdefs.3 container_of.3 \
 +	dirent.3 dlfcn.3 dlinfo.3 dl_iterate_phdr.3 end.3 \
  	fast_divide32.3 ffs32.3 gcq.3 \
  	ilog2.3 intro.3 inttypes.3 iso646.3 limits.3 \
  	makedev.3 offsetof.3 param.3 paths.3 queue.3 rbtree.3 sigevent.3 \
 @@ -54,6 +55,7 @@ MLINKS+=3Dbits.3 __BIT.3 \
  	bits.3 __SHIFTOUT_MASK.3
  MLINKS+=3Dcdefs.3 __RCSID.3 \
  	cdefs.3 __KERNEL_RCSID.3
 +MLINKS+=3Dcontainer_of.3 const_container_of.3
  MLINKS+=3Dend.3 edata.3 end.3 etext.3
  MLINKS+=3Dfast_divide32.3 fast_divide32_prepare.3 \
  	fast_divide32.3 fast_remainder32.3
 diff -r 32a19974e47e -r 4529dd9470d4 share/man/man3/container_of.3
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 +++ b/share/man/man3/container_of.3	Tue Oct 08 17:17:10 2024 +0000
 @@ -0,0 +1,109 @@
 +.\"	$NetBSD$
 +.\"
 +.\" Copyright (c) 2024 The NetBSD Foundation, Inc.
 +.\" All rights reserved.
 +.\"
 +.\" Redistribution and use in source and binary forms, with or without
 +.\" modification, are permitted provided that the following conditions
 +.\" are met:
 +.\" 1. Redistributions of source code must retain the above copyright
 +.\"    notice, this list of conditions and the following disclaimer.
 +.\" 2. Redistributions in binary form must reproduce the above copyright
 +.\"    notice, this list of conditions and the following disclaimer in the
 +.\"    documentation and/or other materials provided with the distribution.
 +.\"
 +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUT=
 ORS
 +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LI=
 MITED
 +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTIC=
 ULAR
 +.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUT=
 ORS
 +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINE=
 SS
 +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF=
  THE
 +.\" POSSIBILITY OF SUCH DAMAGE.
 +.\"
 +.Dd October 8, 2024
 +.Dt CONTAINER_OF 3
 +.Os
 +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 """""
 +.Sh NAME
 +.Nm container_of ,
 +.Nm const_container_of
 +.Nd struct container accessor macros
 +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 """""
 +.Sh SYNOPSIS
 +.In sys/container_of.h
 +.Ft struct_type *
 +.Fn container_of "member_type *ptr" "struct_type" "member"
 +.Ft const struct_type *
 +.Fn const_container_of "const member_type *ptr" "struct_type" "member"
 +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 """""
 +.Sh DESCRIPTION
 +Given a pointer to a member of a structure, the
 +.Fn container_of
 +macro returns a pointer to the containing structure.
 +.Pp
 +The caller must specify the containing structure's type and the name of
 +the member in the containing structure, which must have type compatible
 +with what the input pointer points to.
 +.Pp
 +The
 +.Fn const_container_of
 +macro does similarly for a const-qualified pointer.
 +.Pp
 +The call
 +.Fn container_of P T M
 +is essentially equivalent to
 +.Dl "(" Ns Fa T Li "*)((char *)" Ns Fa P Li "-" Fn offsetof T M Ns ")" ,
 +but it is safer because it checks the type of
 +.Fa P
 +against the type of member
 +.Fa M
 +of structure type
 +.Fa T .
 +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 """""
 +.Sh EXAMPLES
 +.Bd -literal
 +/* Gizmo data structure */
 +struct gizmo {
 +	...
 +	struct work	gz_work;
 +	...
 +};
 +
 +/* Enqueue gizmo-related work */
 +	struct gizmo *gz =3D ...;
 +	struct work =3D &gz->gz_work;
 +
 +	workqueue_enqueue(gizmo_workqueue, work, NULL);
 +
 +/* Function to process queued gizmo-related work */
 +void
 +gizmo_work(struct work *work, void *cookie)
 +{
 +	struct gizmo *gz =3D container_of(work, struct gizmo, gz_work);
 +
 +	...
 +}
 +.Ed
 +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 """""
 +.Sh SEE ALSO
 +.Xr offsetof 3
 +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 """""
 +.Sh HISTORY
 +The
 +.Fn container_of
 +and
 +.Fn const_container_of
 +macros first appeared in
 +.Nx 8.0
 +in
 +.In libkern.h
 +for kernel use.
 +They were moved in
 +.Nx 11.0
 +to
 +.In sys/container_of.h
 +for use by both kernel and userland.

 --=_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS--

From: Christos Zoulas <christos@zoulas.com>
To: gnats-bugs@netbsd.org
Cc: lib-bug-people@netbsd.org, gnats-admin@netbsd.org,
 netbsd-bugs@netbsd.org, campbell+netbsd@mumble.net
Subject: Re: lib/58729: container_of is not documented or available in userland
Date: Tue, 8 Oct 2024 16:15:35 -0400

 I am testing a diff that moves sttdef.h to sys

 christos

 > On Oct 8, 2024, at 1:20=E2=80=AFPM, Taylor R Campbell via gnats <gnats-adm=
 in@netbsd.org> wrote:
 >=20
 > =EF=BB=BFThe following reply was made to PR lib/58729; it has been noted b=
 y GNATS.
 >=20
 > From: Taylor R Campbell <riastradh@NetBSD.org>
 > To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
 > Cc:
 > Subject: Re: lib/58729: container_of is not documented or available in use=
 rland
 > Date: Tue, 8 Oct 2024 17:18:20 +0000
 >=20
 > This is a multi-part message in MIME format.
 > --=3D_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS
 >=20
 > Here's a draft that just duplicates the include/stddef.h definition of
 > offsetof for now.  It coexists peacefully in the kernel with the
 > libkern.h definition -- with #ifndef offsetof hacks in both places.
 > Not great but it'll serve to address the immediate issue without
 > deciding how best to disentangle things.
 >=20
 > Another thought I had is that it might be worthwhile to have
 > __container_of and __offsetof macros that would avoid namespace
 > pollution, and only expose container_of and offsetof if you explicitly
 > ask for a header file defined to use them.  But I don't have a use
 > case for this right now so I won't do anything about this.
 >=20
 > --=3D_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS
 > Content-Type: text/plain; charset=3D"ISO-8859-1"; name=3D"pr58729-containe=
 rofh"
 > Content-Transfer-Encoding: quoted-printable
 > Content-Disposition: attachment; filename=3D"pr58729-containerofh.patch"
 >=20
 > # HG changeset patch
 > # User Taylor R Campbell <riastradh@NetBSD.org>
 > # Date 1728402416 0
 > #      Tue Oct 08 15:46:56 2024 +0000
 > # Branch trunk
 > # Node ID 32a19974e47ea523810619381ab6d96671c537c9
 > # Parent  324886ee2905fda3948217e0fd3c6ca7f4cf32dc
 > # EXP-Topic riastradh-pr58729-containerof
 > container_of: New header file sys/container_of.h for this.
 >=20
 > PR lib/58729: container_of is not documented or available in userland
 >=20
 > diff -r 324886ee2905 -r 32a19974e47e sys/lib/libkern/libkern.h
 > --- a/sys/lib/libkern/libkern.h    Tue Oct 08 12:49:01 2024 +0000
 > +++ b/sys/lib/libkern/libkern.h    Tue Oct 08 15:46:56 2024 +0000
 > @@ -323,46 +323,7 @@ tolower(int ch)
 >  #endif
 >  #endif
 > =3D20
 > -/*
 > - * Return the container of an embedded struct.  Given x =3D3D &c->f,
 > - * container_of(x, T, f) yields c, where T is the type of c.  Example:
 > - *
 > - *    struct foo { ... };
 > - *    struct bar {
 > - *        int b_x;
 > - *        struct foo b_foo;
 > - *        ...
 > - *    };
 > - *
 > - *    struct bar b;
 > - *    struct foo *fp =3D3D &b.b_foo;
 > - *
 > - * Now we can get at b from fp by:
 > - *
 > - *    struct bar *bp =3D3D container_of(fp, struct bar, b_foo);
 > - *
 > - * The 0*sizeof((PTR) - ...) causes the compiler to warn if the type of
 > - * *fp does not match the type of struct bar::b_foo.
 > - * We skip the validation for coverity runs to avoid warnings.
 > - */
 > -#if defined(__COVERITY__) || defined(__LGTM_BOT__)
 > -#define __validate_container_of(PTR, TYPE, FIELD) 0
 > -#define __validate_const_container_of(PTR, TYPE, FIELD) 0
 > -#else
 > -#define __validate_container_of(PTR, TYPE, FIELD)            \
 > -    (0 * sizeof((PTR) - &((TYPE *)(((char *)(PTR)) -            \
 > -    offsetof(TYPE, FIELD)))->FIELD))
 > -#define __validate_const_container_of(PTR, TYPE, FIELD)            \
 > -    (0 * sizeof((PTR) - &((const TYPE *)(((const char *)(PTR)) -    \
 > -    offsetof(TYPE, FIELD)))->FIELD))
 > -#endif
 > -
 > -#define    container_of(PTR, TYPE, FIELD)                    \
 > -    ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, FIELD))            \
 > -    + __validate_container_of(PTR, TYPE, FIELD))
 > -#define    const_container_of(PTR, TYPE, FIELD)                \
 > -    ((const TYPE *)(((const char *)(PTR)) - offsetof(TYPE, FIELD))    \
 > -    + __validate_const_container_of(PTR, TYPE, FIELD))
 > +#include <sys/container_of.h>
 > =3D20
 >  /* Prototypes for which GCC built-ins exist. */
 >  void    *memcpy(void *, const void *, size_t);
 > diff -r 324886ee2905 -r 32a19974e47e sys/sys/container_of.h
 > --- /dev/null    Thu Jan 01 00:00:00 1970 +0000
 > +++ b/sys/sys/container_of.h    Tue Oct 08 15:46:56 2024 +0000
 > @@ -0,0 +1,101 @@
 > +/*    $NetBSD$    */
 > +
 > +/*-
 > + * Copyright (c) 2013 The NetBSD Foundation, Inc.
 > + * All rights reserved.
 > + *
 > + * This code is derived from software contributed to The NetBSD Foundatio=
 n
 > + * by Taylor R. Campbell.
 > + *
 > + * Redistribution and use in source and binary forms, with or without
 > + * modification, are permitted provided that the following conditions
 > + * are met:
 > + * 1. Redistributions of source code must retain the above copyright
 > + *    notice, this list of conditions and the following disclaimer.
 > + * 2. Redistributions in binary form must reproduce the above copyright
 > + *    notice, this list of conditions and the following disclaimer in the=

 > + *    documentation and/or other materials provided with the distribution=
 .
 > + *
 > + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUT=
 O=3D
 > RS
 > + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LI=
 M=3D
 > ITED
 > + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTIC=
 U=3D
 > LAR
 > + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUT=
 O=3D
 > RS
 > + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR=

 > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINE=
 SS
 > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER I=
 N
 > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE=
 )
 > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF=
  =3D
 > THE
 > + * POSSIBILITY OF SUCH DAMAGE.
 > + */
 > +
 > +#ifndef    _SYS_CONTAINER_OF_H_
 > +#define    _SYS_CONTAINER_OF_H_
 > +
 > +#include <sys/ansi.h>
 > +
 > +#ifdef    _BSD_SIZE_T_
 > +typedef    _BSD_SIZE_T_    size_t;
 > +#undef    _BSD_SIZE_T_
 > +#endif
 > +
 > +/*
 > + * XXX Avoid duplicating this with sys/lib/libkern/libkern.h and
 > + * include/stddef.h.
 > + */
 > +#ifndef offsetof
 > +#if __GNUC_PREREQ__(4, 0)
 > +#define    offsetof(type, member)    __builtin_offsetof(type, member)
 > +#elif !defined(__cplusplus)
 > +#define    offsetof(type, member)    ((size_t)(unsigned long)(&((type *)0=
 )->memb=3D
 > er))
 > +#else
 > +#if !__GNUC_PREREQ__(3, 4)
 > +#define __offsetof__(a) a
 > +#endif
 > +#define    offsetof(type, member) __offsetof__((reinterpret_cast<size_t> \=

 > +    (&reinterpret_cast<const volatile char &>(static_cast<type *>(0)->mem=
 b=3D
 > er))))
 > +#endif
 > +#endif
 > +
 > +/*
 > + * Return the container of an embedded struct.  Given x =3D3D &c->f,
 > + * container_of(x, T, f) yields c, where T is the type of c.  Example:
 > + *
 > + *    struct foo { ... };
 > + *    struct bar {
 > + *        int b_x;
 > + *        struct foo b_foo;
 > + *        ...
 > + *    };
 > + *
 > + *    struct bar b;
 > + *    struct foo *fp =3D3D &b.b_foo;
 > + *
 > + * Now we can get at b from fp by:
 > + *
 > + *    struct bar *bp =3D3D container_of(fp, struct bar, b_foo);
 > + *
 > + * The 0*sizeof((PTR) - ...) causes the compiler to warn if the type of
 > + * *fp does not match the type of struct bar::b_foo.
 > + * We skip the validation for coverity runs to avoid warnings.
 > + */
 > +#if defined(__COVERITY__) || defined(__LGTM_BOT__)
 > +#define __validate_container_of(PTR, TYPE, FIELD) 0
 > +#define __validate_const_container_of(PTR, TYPE, FIELD) 0
 > +#else
 > +#define __validate_container_of(PTR, TYPE, FIELD)            \
 > +    (0 * sizeof((PTR) - &((TYPE *)(((char *)(PTR)) -            \
 > +    offsetof(TYPE, FIELD)))->FIELD))
 > +#define __validate_const_container_of(PTR, TYPE, FIELD)            \
 > +    (0 * sizeof((PTR) - &((const TYPE *)(((const char *)(PTR)) -    \
 > +    offsetof(TYPE, FIELD)))->FIELD))
 > +#endif
 > +
 > +#define    container_of(PTR, TYPE, FIELD)                    \
 > +    ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, FIELD))            \
 > +    + __validate_container_of(PTR, TYPE, FIELD))
 > +#define    const_container_of(PTR, TYPE, FIELD)                \
 > +    ((const TYPE *)(((const char *)(PTR)) - offsetof(TYPE, FIELD))    \
 > +    + __validate_const_container_of(PTR, TYPE, FIELD))
 > +
 > +#endif    /* _SYS_CONTAINER_OF_H_ */
 > # HG changeset patch
 > # User Taylor R Campbell <riastradh@NetBSD.org>
 > # Date 1728407830 0
 > #      Tue Oct 08 17:17:10 2024 +0000
 > # Branch trunk
 > # Node ID 4529dd9470d4274e62fb97bbbfc358f45342be28
 > # Parent  32a19974e47ea523810619381ab6d96671c537c9
 > # EXP-Topic riastradh-pr58729-containerof
 > container_of(3): New man page.
 >=20
 > PR lib/58729: container_of is not documented or available in userland
 >=20
 > diff -r 32a19974e47e -r 4529dd9470d4 distrib/sets/lists/comp/mi
 > --- a/distrib/sets/lists/comp/mi    Tue Oct 08 15:46:56 2024 +0000
 > +++ b/distrib/sets/lists/comp/mi    Tue Oct 08 17:17:10 2024 +0000
 > @@ -7024,8 +7024,10 @@
 >  ./usr/share/man/cat3/conj.0            comp-c-catman        complex,.cat
 >  ./usr/share/man/cat3/conjf.0            comp-c-catman        complex,.cat=

 >  ./usr/share/man/cat3/conjl.0            comp-c-catman        complex,.cat=

 > +./usr/share/man/cat3/const_container_of.0    comp-c-catman        .cat
 >  ./usr/share/man/cat3/consttime_bcmp.0        comp-obsolete        obsolet=
 e
 >  ./usr/share/man/cat3/consttime_memequal.0    comp-c-catman        .cat
 > +./usr/share/man/cat3/container_of.0        comp-c-catman        .cat
 >  ./usr/share/man/cat3/copysign.0            comp-c-catman        .cat
 >  ./usr/share/man/cat3/copysignf.0        comp-c-catman        .cat
 >  ./usr/share/man/cat3/copysignl.0        comp-c-catman        .cat
 > @@ -15552,8 +15554,10 @@
 >  ./usr/share/man/html3/conj.html            comp-c-htmlman        complex,=
 html
 >  ./usr/share/man/html3/conjf.html        comp-c-htmlman        complex,htm=
 l
 >  ./usr/share/man/html3/conjl.html        comp-c-htmlman        complex,htm=
 l
 > +./usr/share/man/html3/const_container_of.html    comp-c-htmlman        ht=
 ml
 >  ./usr/share/man/html3/consttime_bcmp.html    comp-obsolete        obsolet=
 e
 >  ./usr/share/man/html3/consttime_memequal.html    comp-c-htmlman        ht=
 ml
 > +./usr/share/man/html3/container_of.html        comp-c-htmlman        html=

 >  ./usr/share/man/html3/copysign.html        comp-c-htmlman        html
 >  ./usr/share/man/html3/copysignf.html        comp-c-htmlman        html
 >  ./usr/share/man/html3/copysignl.html        comp-c-htmlman        html
 > @@ -24025,8 +24029,10 @@
 >  ./usr/share/man/man3/conj.3            comp-c-man        complex,.man
 >  ./usr/share/man/man3/conjf.3            comp-c-man        complex,.man
 >  ./usr/share/man/man3/conjl.3            comp-c-man        complex,.man
 > +./usr/share/man/man3/const_container_of.3    comp-c-man        .man
 >  ./usr/share/man/man3/consttime_bcmp.3        comp-obsolete        obsolet=
 e
 >  ./usr/share/man/man3/consttime_memequal.3    comp-c-man        .man
 > +./usr/share/man/man3/container_of.3        comp-c-man        .man
 >  ./usr/share/man/man3/copysign.3            comp-c-man        .man
 >  ./usr/share/man/man3/copysignf.3        comp-c-man        .man
 >  ./usr/share/man/man3/copysignl.3        comp-c-man        .man
 > diff -r 32a19974e47e -r 4529dd9470d4 share/man/man3/Makefile
 > --- a/share/man/man3/Makefile    Tue Oct 08 15:46:56 2024 +0000
 > +++ b/share/man/man3/Makefile    Tue Oct 08 17:17:10 2024 +0000
 > @@ -7,7 +7,8 @@ MAN=3D3D    _DIAGASSERT.3 __CONCAT.3 __FPTRCAST
 >      __builtin_return_address.3 \
 >      __builtin_types_compatible_p.3 __insn_barrier.3 \
 >      assert.3 attribute.3 bitmap.3 bitops.3 bits.3 bitstring.3 \
 > -    cdefs.3 dirent.3 dlfcn.3 dlinfo.3 dl_iterate_phdr.3 end.3 \
 > +    cdefs.3 container_of.3 \
 > +    dirent.3 dlfcn.3 dlinfo.3 dl_iterate_phdr.3 end.3 \
 >      fast_divide32.3 ffs32.3 gcq.3 \
 >      ilog2.3 intro.3 inttypes.3 iso646.3 limits.3 \
 >      makedev.3 offsetof.3 param.3 paths.3 queue.3 rbtree.3 sigevent.3 \
 > @@ -54,6 +55,7 @@ MLINKS+=3D3Dbits.3 __BIT.3 \
 >      bits.3 __SHIFTOUT_MASK.3
 >  MLINKS+=3D3Dcdefs.3 __RCSID.3 \
 >      cdefs.3 __KERNEL_RCSID.3
 > +MLINKS+=3D3Dcontainer_of.3 const_container_of.3
 >  MLINKS+=3D3Dend.3 edata.3 end.3 etext.3
 >  MLINKS+=3D3Dfast_divide32.3 fast_divide32_prepare.3 \
 >      fast_divide32.3 fast_remainder32.3
 > diff -r 32a19974e47e -r 4529dd9470d4 share/man/man3/container_of.3
 > --- /dev/null    Thu Jan 01 00:00:00 1970 +0000
 > +++ b/share/man/man3/container_of.3    Tue Oct 08 17:17:10 2024 +0000
 > @@ -0,0 +1,109 @@
 > +.\"    $NetBSD$
 > +.\"
 > +.\" Copyright (c) 2024 The NetBSD Foundation, Inc.
 > +.\" All rights reserved.
 > +.\"
 > +.\" Redistribution and use in source and binary forms, with or without
 > +.\" modification, are permitted provided that the following conditions
 > +.\" are met:
 > +.\" 1. Redistributions of source code must retain the above copyright
 > +.\"    notice, this list of conditions and the following disclaimer.
 > +.\" 2. Redistributions in binary form must reproduce the above copyright
 > +.\"    notice, this list of conditions and the following disclaimer in th=
 e
 > +.\"    documentation and/or other materials provided with the distributio=
 n.
 > +.\"
 > +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBU=
 T=3D
 > ORS
 > +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT L=
 I=3D
 > MITED
 > +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTI=
 C=3D
 > ULAR
 > +.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBU=
 T=3D
 > ORS
 > +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, O=
 R
 > +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 > +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSIN=
 E=3D
 > SS
 > +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER I=
 N
 > +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS=
 E)
 > +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED O=
 F=3D
 >  THE
 > +.\" POSSIBILITY OF SUCH DAMAGE.
 > +.\"
 > +.Dd October 8, 2024
 > +.Dt CONTAINER_OF 3
 > +.Os
 > +.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 "=3D
 > """""
 > +.Sh NAME
 > +.Nm container_of ,
 > +.Nm const_container_of
 > +.Nd struct container accessor macros
 > +.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 "=3D
 > """""
 > +.Sh SYNOPSIS
 > +.In sys/container_of.h
 > +.Ft struct_type *
 > +.Fn container_of "member_type *ptr" "struct_type" "member"
 > +.Ft const struct_type *
 > +.Fn const_container_of "const member_type *ptr" "struct_type" "member"
 > +.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 "=3D
 > """""
 > +.Sh DESCRIPTION
 > +Given a pointer to a member of a structure, the
 > +.Fn container_of
 > +macro returns a pointer to the containing structure.
 > +.Pp
 > +The caller must specify the containing structure's type and the name of
 > +the member in the containing structure, which must have type compatible
 > +with what the input pointer points to.
 > +.Pp
 > +The
 > +.Fn const_container_of
 > +macro does similarly for a const-qualified pointer.
 > +.Pp
 > +The call
 > +.Fn container_of P T M
 > +is essentially equivalent to
 > +.Dl "(" Ns Fa T Li "*)((char *)" Ns Fa P Li "-" Fn offsetof T M Ns ")" ,
 > +but it is safer because it checks the type of
 > +.Fa P
 > +against the type of member
 > +.Fa M
 > +of structure type
 > +.Fa T .
 > +.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 "=3D
 > """""
 > +.Sh EXAMPLES
 > +.Bd -literal
 > +/* Gizmo data structure */
 > +struct gizmo {
 > +    ...
 > +    struct work    gz_work;
 > +    ...
 > +};
 > +
 > +/* Enqueue gizmo-related work */
 > +    struct gizmo *gz =3D3D ...;
 > +    struct work =3D3D &gz->gz_work;
 > +
 > +    workqueue_enqueue(gizmo_workqueue, work, NULL);
 > +
 > +/* Function to process queued gizmo-related work */
 > +void
 > +gizmo_work(struct work *work, void *cookie)
 > +{
 > +    struct gizmo *gz =3D3D container_of(work, struct gizmo, gz_work);
 > +
 > +    ...
 > +}
 > +.Ed
 > +.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 "=3D
 > """""
 > +.Sh SEE ALSO
 > +.Xr offsetof 3
 > +.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""=
 "=3D
 > """""
 > +.Sh HISTORY
 > +The
 > +.Fn container_of
 > +and
 > +.Fn const_container_of
 > +macros first appeared in
 > +.Nx 8.0
 > +in
 > +.In libkern.h
 > +for kernel use.
 > +They were moved in
 > +.Nx 11.0
 > +to
 > +.In sys/container_of.h
 > +for use by both kernel and userland.
 >=20
 > --=3D_9iRVuQui7SP0XI0my0i42KB+RbbJU+ZS--
 >=20

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/58729 CVS commit: src
Date: Tue, 8 Oct 2024 18:53:21 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Tue Oct  8 22:53:21 UTC 2024

 Modified Files:
 	src/distrib/sets/lists/comp: mi
 	src/include: Makefile
 	src/sys/sys: Makefile
 Added Files:
 	src/sys/sys: container_of.h stddef.h
 Removed Files:
 	src/include: stddef.h

 Log Message:
 PR/58729: Taylor R Campbell: container_of is not documented or available
 in userland


 To generate a diff of this commit:
 cvs rdiff -u -r1.2474 -r1.2475 src/distrib/sets/lists/comp/mi
 cvs rdiff -u -r1.148 -r1.149 src/include/Makefile
 cvs rdiff -u -r1.24 -r0 src/include/stddef.h
 cvs rdiff -u -r1.184 -r1.185 src/sys/sys/Makefile
 cvs rdiff -u -r0 -r1.1 src/sys/sys/container_of.h src/sys/sys/stddef.h

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

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.