Changeset View
Changeset View
Standalone View
Standalone View
sys/sys/kassert.h
- This file was added.
/*- | |||||
* SPDX-License-Identifier: BSD-3-Clause | |||||
* | |||||
* Copyright (c) 1999 Eivind Eklund <eivind@FreeBSD.org> | |||||
* | |||||
* 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. | |||||
* 3. Neither the name of the University nor the names of its contributors | |||||
* may be used to endorse or promote products derived from this software | |||||
* without specific prior written permission. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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_KASSERT_H_ | |||||
#define _SYS_KASSERT_H_ | |||||
#include <sys/cdefs.h> | |||||
#ifdef _KERNEL | |||||
extern const char *panicstr; /* panic message */ | |||||
extern bool panicked; | |||||
#define KERNEL_PANICKED() __predict_false(panicked) | |||||
#ifdef INVARIANTS /* The option is always available */ | |||||
#define VNASSERT(exp, vp, msg) do { \ | |||||
if (__predict_false(!(exp))) { \ | |||||
vn_printf(vp, "VNASSERT failed: %s not true at %s:%d (%s)\n",\ | |||||
#exp, __FILE__, __LINE__, __func__); \ | |||||
kassert_panic msg; \ | |||||
} \ | |||||
} while (0) | |||||
#define VNPASS(exp, vp) do { \ | |||||
const char *_exp = #exp; \ | |||||
VNASSERT(exp, vp, ("condition %s not met at %s:%d (%s)", \ | |||||
_exp, __FILE__, __LINE__, __func__)); \ | |||||
} while (0) | |||||
#define __assert_unreachable() \ | |||||
panic("executing segment marked as unreachable at %s:%d (%s)\n", \ | |||||
__FILE__, __LINE__, __func__) | |||||
#else /* INVARIANTS */ | |||||
#define VNASSERT(exp, vp, msg) do { \ | |||||
} while (0) | |||||
#define VNPASS(exp, vp) do { \ | |||||
} while (0) | |||||
#define __assert_unreachable() __unreachable() | |||||
#endif /* INVARIANTS */ | |||||
#ifndef CTASSERT /* Allow lint to override */ | |||||
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") | |||||
#endif | |||||
/* | |||||
* These functions need to be declared before the KASSERT macro is invoked in | |||||
* !KASSERT_PANIC_OPTIONAL builds, so their declarations are sort of out of | |||||
* place compared to other function definitions in this header. On the other | |||||
* hand, this header is a bit disorganized anyway. | |||||
*/ | |||||
void panic(const char *, ...) __dead2 __printflike(1, 2); | |||||
void vpanic(const char *, __va_list) __dead2 __printflike(1, 0); | |||||
#endif /* _KERNEL */ | |||||
#if defined(_STANDALONE) | |||||
/* | |||||
* Until we have more experience with KASSERTS that are called | |||||
* from the boot loader, they are off. The bootloader does this | |||||
* a little differently than the kernel (we just call printf atm). | |||||
* we avoid most of the common functions in the boot loader, so | |||||
* declare printf() here too. | |||||
*/ | |||||
int printf(const char *, ...) __printflike(1, 2); | |||||
# define kassert_panic printf | |||||
#else /* !_STANDALONE */ | |||||
# if defined(WITNESS) || defined(INVARIANT_SUPPORT) | |||||
# ifdef KASSERT_PANIC_OPTIONAL | |||||
void kassert_panic(const char *fmt, ...) __printflike(1, 2); | |||||
# else | |||||
# define kassert_panic panic | |||||
# endif /* KASSERT_PANIC_OPTIONAL */ | |||||
# endif /* defined(WITNESS) || defined(INVARIANT_SUPPORT) */ | |||||
#endif /* _STANDALONE */ | |||||
#if (defined(_KERNEL) && defined(INVARIANTS)) || defined(_STANDALONE) | |||||
#define KASSERT(exp,msg) do { \ | |||||
if (__predict_false(!(exp))) \ | |||||
kassert_panic msg; \ | |||||
} while (0) | |||||
#else /* !(KERNEL && INVARIANTS) && !_STANDALONE */ | |||||
#define KASSERT(exp,msg) do { \ | |||||
} while (0) | |||||
#endif /* (_KERNEL && INVARIANTS) || _STANDALONE */ | |||||
#ifdef _KERNEL | |||||
/* | |||||
* Helpful macros for quickly coming up with assertions with informative | |||||
* panic messages. | |||||
*/ | |||||
#define MPASS(ex) MPASS4(ex, #ex, __FILE__, __LINE__) | |||||
#define MPASS2(ex, what) MPASS4(ex, what, __FILE__, __LINE__) | |||||
#define MPASS3(ex, file, line) MPASS4(ex, #ex, file, line) | |||||
imp: Should these also be _STANDALONE, except for the SCHEDULER_STOPPED_TD()? | |||||
Done Inline ActionsI built stand/ with the patch applied, and it passed (I did not yet tinderboxed the patch). In principle MPASSX() can be useful in stand/, but it seems to be unused. Do you want to have them enabled there, I do not believe that they are right now? kib: I built stand/ with the patch applied, and it passed (I did not yet tinderboxed the patch).
In… | |||||
Not Done Inline ActionsI'm torn, but I think leaving at it is might be a tiny bit better. imp: I'm torn, but I think leaving at it is might be a tiny bit better.
stand uses stuff from the… | |||||
#define MPASS4(ex, what, file, line) \ | |||||
KASSERT((ex), ("Assertion %s failed at %s:%d", what, file, line)) | |||||
/* | |||||
* Assert that a pointer can be loaded from memory atomically. | |||||
* | |||||
* This assertion enforces stronger alignment than necessary. For example, | |||||
* on some architectures, atomicity for unaligned loads will depend on | |||||
* whether or not the load spans multiple cache lines. | |||||
*/ | |||||
#define ASSERT_ATOMIC_LOAD_PTR(var, msg) \ | |||||
KASSERT(sizeof(var) == sizeof(void *) && \ | |||||
((uintptr_t)&(var) & (sizeof(void *) - 1)) == 0, msg) | |||||
/* | |||||
* Assert that a thread is in critical(9) section. | |||||
*/ | |||||
#define CRITICAL_ASSERT(td) \ | |||||
KASSERT((td)->td_critnest >= 1, ("Not in critical section")) | |||||
/* | |||||
* If we have already panic'd and this is the thread that called | |||||
* panic(), then don't block on any mutexes but silently succeed. | |||||
* Otherwise, the kernel will deadlock since the scheduler isn't | |||||
* going to run the thread that holds any lock we need. | |||||
*/ | |||||
#define SCHEDULER_STOPPED_TD(td) ({ \ | |||||
MPASS((td) == curthread); \ | |||||
__predict_false((td)->td_stopsched); \ | |||||
}) | |||||
#define SCHEDULER_STOPPED() SCHEDULER_STOPPED_TD(curthread) | |||||
#endif /* _KERNEL */ | |||||
#endif /* _SYS_KASSERT_H_ */ |
Should these also be _STANDALONE, except for the SCHEDULER_STOPPED_TD()?