xref: /freebsd/share/man/man9/KASSERT.9 (revision e9ac41698b2f322d55ccf9da50a3596edb2c1800)
1.\" SPDX-License-Identifier: BSD-2-Clause
2.\"
3.\" Copyright (c) 2000 Jonathan M. Bresler
4.\" All rights reserved.
5.\" Copyright (c) 2023-2024 The FreeBSD Foundation
6.\"
7.\" Portions of this documentation were written by Mitchell Horne
8.\" under sponsorship from the FreeBSD Foundation.
9.\"
10.\" This program is free software.
11.\"
12.\" Redistribution and use in source and binary forms, with or without
13.\" modification, are permitted provided that the following conditions
14.\" are met:
15.\" 1. Redistributions of source code must retain the above copyright
16.\"    notice, this list of conditions and the following disclaimer.
17.\" 2. Redistributions in binary form must reproduce the above copyright
18.\"    notice, this list of conditions and the following disclaimer in the
19.\"    documentation and/or other materials provided with the distribution.
20.\"
21.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
22.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
25.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31.\"
32.Dd March 19, 2024
33.Dt KASSERT 9
34.Os
35.Sh NAME
36.Nm KASSERT
37.Nd kernel expression verification macros
38.Sh SYNOPSIS
39.Cd "options INVARIANTS"
40.Pp
41.In sys/param.h
42.In sys/systm.h
43.Fn KASSERT expression msg
44.Fn MPASS expression
45.Sh DESCRIPTION
46Assertions are widely used within the
47.Fx
48kernel to verify programmatic assumptions.
49For violations of run-time assumptions and invariants, it is desirable to fail
50as soon and as loudly as possible.
51Assertions are optional code; for non-recoverable error conditions an explicit
52call to
53.Xr panic 9
54is usually preferred.
55.Pp
56The
57.Fn KASSERT
58macro tests the given boolean
59.Fa expression .
60If
61.Fa expression
62evaluates to
63.Dv false ,
64and the kernel is compiled with
65.Cd "options INVARIANTS" ,
66the
67.Xr panic 9
68function is called.
69This terminates the running system at the point of the error, possibly dropping
70into the kernel debugger or initiating a kernel core dump.
71The second argument,
72.Fa msg ,
73is a
74.Xr printf 9
75format string and its arguments,
76enclosed in parentheses.
77The formatted string will become the panic string.
78.Pp
79In a kernel that is built without
80.Cd "options INVARIANTS" ,
81the assertion macros are defined to be no-ops.
82This eliminates the runtime overhead of widespread assertions from release
83builds of the kernel.
84Therefore, checks which can be performed in a constant amount of time can be
85added as assertions without concern about their performance impact.
86More expensive checks, such as those that output to console, or verify the
87integrity of a chain of objects are generally best hidden behind the
88.Cd DIAGNOSTIC
89kernel option.
90.Pp
91The
92.Fn MPASS
93macro (read as: "must-pass")
94is a convenience wrapper around
95.Fn KASSERT
96that automatically generates a simple assertion message including file and line
97information.
98.Ss Assertion Guidelines
99When adding new assertions, keep in mind their primary purpose: to aid in
100identifying and debugging of complex error conditions.
101.Pp
102The panic messages resulting from assertion failures should be useful without
103the resulting kernel dump; the message may be included in a bug report, and
104should contain the relevant information needed to discern how the assertion was
105violated.
106This is especially important when the error condition is difficult or
107impossible for the developer to reproduce locally.
108.Pp
109Therefore, assertions should adhere to the following guidelines:
110.Bl -enum
111.It
112Whenever possible, the value of a runtime variable checked by an assertion
113condition should appear in its message.
114.It
115Unrelated conditions must appear in separate assertions.
116.It
117Multiple related conditions should be distinguishable (e.g. by value), or split
118into separate assertions.
119.It
120When in doubt, print more information, not less.
121.El
122.Pp
123Combined, this gives greater clarity into the exact cause of an assertion
124panic; see
125.Sx EXAMPLES
126below.
127.Sh EXAMPLES
128A hypothetical
129.Vt struct foo
130object must not have its 'active' flag set when calling
131.Fn foo_dealloc :
132.Bd -literal -offset indent
133void
134foo_dealloc(struct foo *fp)
135{
136
137	KASSERT((fp->foo_flags & FOO_ACTIVE) == 0,
138	    ("%s: fp %p is still active, flags=%x", __func__, fp,
139	    fp->foo_flags));
140	...
141}
142.Ed
143.Pp
144This assertion provides the full flag set for the object, as well as the memory
145pointer, which may be used by a debugger to examine the object in detail
146.Po
147for example with a 'show foo' command in
148.Xr ddb 4
149.Pc .
150.Pp
151The assertion
152.Bd -literal -offset indent
153MPASS(td == curthread);
154.Ed
155.Pp
156located on line 87 of a file named foo.c would generate the following panic
157message:
158.Bd -literal -offset indent
159panic: Assertion td == curthread failed at foo.c:87
160.Ed
161.Pp
162This is a simple condition, and the message provides enough information to
163investigate the failure.
164.Pp
165The assertion
166.Bd -literal -offset indent
167MPASS(td == curthread && (sz >= SIZE_MIN && sz <= SIZE_MAX));
168.Ed
169.Pp
170is
171.Em NOT
172useful enough.
173The message doesn't indicate which part of the assertion was violated, nor
174does it report the value of
175.Dv sz ,
176which may be critical to understanding
177.Em why
178the assertion failed.
179.Pp
180According to the guidelines above, this would be correctly expressed as:
181.Bd -literal -offset indent
182MPASS(td == curthread);
183KASSERT(sz >= SIZE_MIN && sz <= SIZE_MAX,
184    ("invalid size argument: %u", sz));
185.Ed
186.Sh HISTORY
187The
188.Nm MPASS
189macro first appeared in
190.Bsx
191and was imported into
192.Fx 5.0 .
193The name originates as an acronym of "multi-processor assert", but has evolved
194to mean "must pass", or "must-pass assert".
195.Sh SEE ALSO
196.Xr panic 9
197.Sh AUTHORS
198This manual page was written by
199.An Jonathan M. Bresler Aq Mt jmb@FreeBSD.org
200and
201.An Mitchell Horne Aq Mt mhorne@FreeBSD.org .
202