mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
![Josh Triplett](/assets/img/avatar_default.png)
When !CONFIG_BUG and !HAVE_ARCH_BUG, define the generic BUG() as an infinite loop rather than a no-op. This avoids undefined behavior if execution ever actually reaches BUG(), and avoids warnings about code after BUG() (such as on non-void functions calling BUG() and then not returning). bloat-o-meter results: add/remove: 0/0 grow/shrink: 43/10 up/down: 235/-98 (137) function old new delta umount_collect 119 138 +19 notify_change 306 324 +18 xstate_enable_boot_cpu 252 269 +17 kunmap 54 70 +16 balloon_page_dequeue 112 126 +14 mm_take_all_locks 223 233 +10 list_lru_walk_node 143 152 +9 vma_adjust 1059 1067 +8 pcpu_setup_first_chunk 1130 1138 +8 mm_drop_all_locks 143 151 +8 ns_capable 55 62 +7 anon_transport_class_unregister 8 15 +7 srcu_init_notifier_head 35 41 +6 shrink_dcache_for_umount 174 180 +6 kunmap_high 99 105 +6 end_page_writeback 43 49 +6 do_exit 1339 1345 +6 __kfifo_dma_out_prepare_r 86 92 +6 __kfifo_dma_in_prepare_r 90 96 +6 fixup_user_fault 120 125 +5 repair_env_string 73 77 +4 read_cache_pages_invalidate_page 56 60 +4 isolate_lru_pages.isra 142 146 +4 do_notify_parent_cldstop 255 259 +4 cpu_init 370 374 +4 utimes_common 270 272 +2 tasklet_hi_action 91 93 +2 tasklet_action 91 93 +2 set_pte_vaddr 46 48 +2 find_get_pages_tag 202 204 +2 early_iounmap 185 187 +2 __native_set_fixmap 36 38 +2 __get_user_pages 822 824 +2 __early_ioremap 299 301 +2 yield_task_stop 1 2 +1 tick_resume 37 38 +1 switched_to_stop 1 2 +1 switched_to_idle 1 2 +1 prio_changed_stop 1 2 +1 prio_changed_idle 1 2 +1 pm_qos_power_read 111 112 +1 arch_cpu_idle_dead 1 2 +1 __insert_vmap_area 140 141 +1 sys_renameat 614 612 -2 mm_fault_error 297 295 -2 SyS_renameat 614 612 -2 sys_linkat 416 413 -3 SyS_linkat 416 413 -3 chmod_common 129 122 -7 proc_cap_handler 240 225 -15 __schedule 849 831 -18 sys_madvise 1077 1054 -23 SyS_madvise 1077 1054 -23 Signed-off-by: Josh Triplett <josh@joshtriplett.org> Reported-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
211 lines
5.7 KiB
C
211 lines
5.7 KiB
C
#ifndef _ASM_GENERIC_BUG_H
|
|
#define _ASM_GENERIC_BUG_H
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
#ifdef CONFIG_GENERIC_BUG
|
|
#define BUGFLAG_WARNING (1 << 0)
|
|
#define BUGFLAG_TAINT(taint) (BUGFLAG_WARNING | ((taint) << 8))
|
|
#define BUG_GET_TAINT(bug) ((bug)->flags >> 8)
|
|
#endif
|
|
|
|
#ifndef __ASSEMBLY__
|
|
#include <linux/kernel.h>
|
|
|
|
#ifdef CONFIG_BUG
|
|
|
|
#ifdef CONFIG_GENERIC_BUG
|
|
struct bug_entry {
|
|
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
|
|
unsigned long bug_addr;
|
|
#else
|
|
signed int bug_addr_disp;
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
|
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
|
|
const char *file;
|
|
#else
|
|
signed int file_disp;
|
|
#endif
|
|
unsigned short line;
|
|
#endif
|
|
unsigned short flags;
|
|
};
|
|
#endif /* CONFIG_GENERIC_BUG */
|
|
|
|
/*
|
|
* Don't use BUG() or BUG_ON() unless there's really no way out; one
|
|
* example might be detecting data structure corruption in the middle
|
|
* of an operation that can't be backed out of. If the (sub)system
|
|
* can somehow continue operating, perhaps with reduced functionality,
|
|
* it's probably not BUG-worthy.
|
|
*
|
|
* If you're tempted to BUG(), think again: is completely giving up
|
|
* really the *only* solution? There are usually better options, where
|
|
* users don't need to reboot ASAP and can mostly shut down cleanly.
|
|
*/
|
|
#ifndef HAVE_ARCH_BUG
|
|
#define BUG() do { \
|
|
printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
|
panic("BUG!"); \
|
|
} while (0)
|
|
#endif
|
|
|
|
#ifndef HAVE_ARCH_BUG_ON
|
|
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
|
|
#endif
|
|
|
|
/*
|
|
* WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
|
|
* significant issues that need prompt attention if they should ever
|
|
* appear at runtime. Use the versions with printk format strings
|
|
* to provide better diagnostics.
|
|
*/
|
|
#ifndef __WARN_TAINT
|
|
extern __printf(3, 4)
|
|
void warn_slowpath_fmt(const char *file, const int line,
|
|
const char *fmt, ...);
|
|
extern __printf(4, 5)
|
|
void warn_slowpath_fmt_taint(const char *file, const int line, unsigned taint,
|
|
const char *fmt, ...);
|
|
extern void warn_slowpath_null(const char *file, const int line);
|
|
#define WANT_WARN_ON_SLOWPATH
|
|
#define __WARN() warn_slowpath_null(__FILE__, __LINE__)
|
|
#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg)
|
|
#define __WARN_printf_taint(taint, arg...) \
|
|
warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg)
|
|
#else
|
|
#define __WARN() __WARN_TAINT(TAINT_WARN)
|
|
#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0)
|
|
#define __WARN_printf_taint(taint, arg...) \
|
|
do { printk(arg); __WARN_TAINT(taint); } while (0)
|
|
#endif
|
|
|
|
#ifndef WARN_ON
|
|
#define WARN_ON(condition) ({ \
|
|
int __ret_warn_on = !!(condition); \
|
|
if (unlikely(__ret_warn_on)) \
|
|
__WARN(); \
|
|
unlikely(__ret_warn_on); \
|
|
})
|
|
#endif
|
|
|
|
#ifndef WARN
|
|
#define WARN(condition, format...) ({ \
|
|
int __ret_warn_on = !!(condition); \
|
|
if (unlikely(__ret_warn_on)) \
|
|
__WARN_printf(format); \
|
|
unlikely(__ret_warn_on); \
|
|
})
|
|
#endif
|
|
|
|
#define WARN_TAINT(condition, taint, format...) ({ \
|
|
int __ret_warn_on = !!(condition); \
|
|
if (unlikely(__ret_warn_on)) \
|
|
__WARN_printf_taint(taint, format); \
|
|
unlikely(__ret_warn_on); \
|
|
})
|
|
|
|
#define WARN_ON_ONCE(condition) ({ \
|
|
static bool __section(.data.unlikely) __warned; \
|
|
int __ret_warn_once = !!(condition); \
|
|
\
|
|
if (unlikely(__ret_warn_once)) \
|
|
if (WARN_ON(!__warned)) \
|
|
__warned = true; \
|
|
unlikely(__ret_warn_once); \
|
|
})
|
|
|
|
#define WARN_ONCE(condition, format...) ({ \
|
|
static bool __section(.data.unlikely) __warned; \
|
|
int __ret_warn_once = !!(condition); \
|
|
\
|
|
if (unlikely(__ret_warn_once)) \
|
|
if (WARN(!__warned, format)) \
|
|
__warned = true; \
|
|
unlikely(__ret_warn_once); \
|
|
})
|
|
|
|
#define WARN_TAINT_ONCE(condition, taint, format...) ({ \
|
|
static bool __section(.data.unlikely) __warned; \
|
|
int __ret_warn_once = !!(condition); \
|
|
\
|
|
if (unlikely(__ret_warn_once)) \
|
|
if (WARN_TAINT(!__warned, taint, format)) \
|
|
__warned = true; \
|
|
unlikely(__ret_warn_once); \
|
|
})
|
|
|
|
#else /* !CONFIG_BUG */
|
|
#ifndef HAVE_ARCH_BUG
|
|
#define BUG() do {} while (1)
|
|
#endif
|
|
|
|
#ifndef HAVE_ARCH_BUG_ON
|
|
#define BUG_ON(condition) do { if (condition) ; } while (0)
|
|
#endif
|
|
|
|
#ifndef HAVE_ARCH_WARN_ON
|
|
#define WARN_ON(condition) ({ \
|
|
int __ret_warn_on = !!(condition); \
|
|
unlikely(__ret_warn_on); \
|
|
})
|
|
#endif
|
|
|
|
#ifndef WARN
|
|
#define WARN(condition, format...) ({ \
|
|
int __ret_warn_on = !!(condition); \
|
|
no_printk(format); \
|
|
unlikely(__ret_warn_on); \
|
|
})
|
|
#endif
|
|
|
|
#define WARN_ON_ONCE(condition) WARN_ON(condition)
|
|
#define WARN_ONCE(condition, format...) WARN(condition, format)
|
|
#define WARN_TAINT(condition, taint, format...) WARN(condition, format)
|
|
#define WARN_TAINT_ONCE(condition, taint, format...) WARN(condition, format)
|
|
|
|
#endif
|
|
|
|
/*
|
|
* WARN_ON_SMP() is for cases that the warning is either
|
|
* meaningless for !SMP or may even cause failures.
|
|
* This is usually used for cases that we have
|
|
* WARN_ON(!spin_is_locked(&lock)) checks, as spin_is_locked()
|
|
* returns 0 for uniprocessor settings.
|
|
* It can also be used with values that are only defined
|
|
* on SMP:
|
|
*
|
|
* struct foo {
|
|
* [...]
|
|
* #ifdef CONFIG_SMP
|
|
* int bar;
|
|
* #endif
|
|
* };
|
|
*
|
|
* void func(struct foo *zoot)
|
|
* {
|
|
* WARN_ON_SMP(!zoot->bar);
|
|
*
|
|
* For CONFIG_SMP, WARN_ON_SMP() should act the same as WARN_ON(),
|
|
* and should be a nop and return false for uniprocessor.
|
|
*
|
|
* if (WARN_ON_SMP(x)) returns true only when CONFIG_SMP is set
|
|
* and x is true.
|
|
*/
|
|
#ifdef CONFIG_SMP
|
|
# define WARN_ON_SMP(x) WARN_ON(x)
|
|
#else
|
|
/*
|
|
* Use of ({0;}) because WARN_ON_SMP(x) may be used either as
|
|
* a stand alone line statement or as a condition in an if ()
|
|
* statement.
|
|
* A simple "0" would cause gcc to give a "statement has no effect"
|
|
* warning.
|
|
*/
|
|
# define WARN_ON_SMP(x) ({0;})
|
|
#endif
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif
|