public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: kfree(NULL)
@ 2006-04-22 12:05 linux
  0 siblings, 0 replies; 42+ messages in thread
From: linux @ 2006-04-22 12:05 UTC (permalink / raw)
  To: linux-kernel, paulus

> Well, we'd have to start by fixing up the janitors that run around
> taking out the if statements in the callers.  :)

You just need to document those two as special.  Probably the
simplest is to tell the programmer and the compiler in one
fell swoop:

	if (unlikely(p))
		kfree(p);

Or that could be wrapped up in a macro:

#define kfree_likely_null(p) if (unlikely(p)) kfree(p)

Or just mention it to the programmer.  A few possible one-line comments:

	/* Testing before calling is faster if often NULL, as here. */
	/* It's worth the (redundant) test for NULL if it often succeeds */
	/* This test saves the call often enough to be worth it. */
	/* Test for NULL not necessary, but worth it here */
	/* Don't delete NULL test; speed trumps code size here */
	/* Very often NULL, so avoid call overhead if possible */
	/* kfree(NULL) is legal, but probabilities favor testing here */

^ permalink raw reply	[flat|nested] 42+ messages in thread
* Re: kfree(NULL)
@ 2006-04-21 21:02 Hua Zhong
  2006-04-21 21:11 ` kfree(NULL) Daniel Walker
  2006-04-21 21:42 ` kfree(NULL) Andrew Morton
  0 siblings, 2 replies; 42+ messages in thread
From: Hua Zhong @ 2006-04-21 21:02 UTC (permalink / raw)
  To: akpm, jmorris, dwalker; +Cc: linux-kernel

Maybe something like this might be a useful debug option to detect unwise likely()/unlikely() usage?

This is a quick hack (not submitted for inclusion), but it works on my box and detected certain points after boot. Anyone likes this idea?

The reason I had to add printk_debug_likely() is that using printk directly gives compile error. It seems not to like asmlinkage for some reason..I guess likely/unlikely are too fundamental macros and the dependency gets too messy. Or maybe it could be fixed in a way I've not found.

It increases kernel size by about 10%, but hey, it's a debugg option. :-)

Sample print:

possible (un)likely misuse at include/asm/mmu_context.h:32/switch_mm()
 <c011b644> printk_debug_likely+0x25/0x31   <c02b3092> schedule+0xb04/0xefa
 <c02b457b> __mutex_lock_slowpath+0x35a/0x89e   <c016c0fd> real_lookup+0x1f/0xb3
 <c016c0fd> real_lookup+0x1f/0xb3   <c016c512> do_lookup+0x50/0xe8
 <c016d14b> __link_path_walk+0xba1/0x125f   <c016d8a6> link_path_walk+0x9d/0x166
 <c014b911> __handle_mm_fault+0x2fd/0x35b   <c01ca29e> _atomic_dec_and_lock+0x22/0x2c
 <c016d5c2> __link_path_walk+0x1018/0x125f   <c016d8a6> link_path_walk+0x9d/0x166
 <c014b911> __handle_mm_fault+0x2fd/0x35b   <c01ce9fe> strncpy_from_user+0x94/0xb3
 <c016dee7> do_path_lookup+0x35c/0x4d2   <c016e385> __user_walk_fd+0x84/0x9b
 <c0167ae1> vfs_stat_fd+0x15/0x3c   <c014b911> __handle_mm_fault+0x2fd/0x35b
 <c0168091> sys_stat64+0xf/0x23   <c0113fea> do_page_fault+0x30d/0x753
 <c01ceefd> copy_to_user+0x113/0x11c   <c0126ee6> sys_rt_sigprocmask+0xae/0xc1
 <c01035cb> sysenter_past_esp+0x54/0x75  
possible (un)likely misuse at kernel/sched.c:1638/context_switch()
 <c011b644> printk_debug_likely+0x25/0x31   <c02b3025> schedule+0xa97/0xefa
 <c011ddcd> do_exit+0x75b/0x765   <c011dec4> sys_exit_group+0x0/0xd
 <c01035cb> sysenter_past_esp+0x54/0x75  
possible (un)likely misuse at kernel/softlockup.c:59/softlockup_tick()
 <c011b644> printk_debug_likely+0x25/0x31   <c0138f78> softlockup_tick+0x88/0xf5
 <c0123dcd> update_process_times+0x35/0x57   <c0106133> timer_interrupt+0x3d/0x60
 <c013919c> handle_IRQ_event+0x21/0x4a   <c01392f7> __do_IRQ+0x132/0x1e7
 <c0104d86> do_IRQ+0x9c/0xab   <c01037fe> common_interrupt+0x1a/0x20
possible (un)likely misuse at kernel/sched.c:1645/context_switch()
 <c011b644> printk_debug_likely+0x25/0x31   <c02b3236> schedule+0xca8/0xefa
 <c0130d33> enqueue_hrtimer+0x5b/0x80   <c02b57f5> do_nanosleep+0x3b/0xc0
 <c0131092> hrtimer_nanosleep+0x45/0xe6   <c01680b4> sys_lstat64+0xf/0x23
 <c013102a> hrtimer_wakeup+0x0/0x18   <c01cf021> copy_from_user+0x11b/0x142
 <c0131179> sys_nanosleep+0x46/0x4e   <c01035cb> sysenter_past_esp+0x54/0x75

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index f23d3c6..a6df5f7 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -58,9 +58,32 @@ #endif
  * build go below this comment. Actual compiler/compiler version
  * specific implementations come from the above header files
  */
+#define CONFIG_DEBUG_LIKELY
+#ifdef CONFIG_DEBUG_LIKELY
+extern int printk_debug_likely(const char *fmt, ...);
+extern int debug_likely_count_min_thresh;
+extern int debug_likely_print_max_thresh;
+#define __check_likely(x, v, uv)                                \
+  ({ static int _ckl_print_nr = 0;                              \
+     static unsigned int _ckl_s[2];                             \
+     int _ckl_r = !!(x);                                        \
+     _ckl_s[_ckl_r]++;                                          \
+     if ((_ckl_s[v] == _ckl_s[uv]) && (_ckl_s[v] > debug_likely_count_min_thresh) \
+          && (_ckl_print_nr < debug_likely_print_max_thresh)) { \
+         _ckl_print_nr++;                                       \
+         printk_debug_likely("possible (un)likely misuse at %s:%d/%s()\n",        \
+                             __FILE__, __LINE__, __FUNCTION__); \
+     }                                                          \
+     _ckl_r; })
+#else
+#define __check_likely(x, v, uv)       __builtin_expect(!!(x), v)
+#endif
+
+#define likely(x)      __check_likely(x, 1, 0)
+#define unlikely(x)    __check_likely(x, 0, 1)
 
-#define likely(x)      __builtin_expect(!!(x), 1)
-#define unlikely(x)    __builtin_expect(!!(x), 0)
+//#define likely(x)    __builtin_expect(!!(x), 1)
+//#define unlikely(x)  __builtin_expect(!!(x), 0)
 
 /* Optimization barrier */
 #ifndef barrier
diff --git a/kernel/printk.c b/kernel/printk.c
index c056f33..cc09dca 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -602,6 +602,30 @@ out:
 EXPORT_SYMBOL(printk);
 EXPORT_SYMBOL(vprintk);
 
+#ifdef CONFIG_DEBUG_LIKELY
+int debug_likely_count_min_thresh = 100;
+int debug_likely_print_max_thresh = 1;
+int printk_debug_likely(const char *fmt, ...)
+{
+       int r = 0;
+       static atomic_t recurse = ATOMIC_INIT(1); /* as a mutex */
+       if (atomic_dec_and_test(&recurse)) {
+               va_list args;
+
+               va_start(args, fmt);
+               r = vprintk(fmt, args);
+               va_end(args);
+               dump_stack();
+       }
+       atomic_inc(&recurse);
+
+       return r;
+}
+EXPORT_SYMBOL(debug_likely_count_min_thresh);
+EXPORT_SYMBOL(debug_likely_print_max_thresh);
+EXPORT_SYMBOL(printk_debug_likely);
+#endif
+
 #else
 
 asmlinkage long sys_syslog(int type, char __user *buf, int len)



^ permalink raw reply related	[flat|nested] 42+ messages in thread
* kfree(NULL)
@ 2006-04-21  7:03 Daniel Walker
  2006-04-21  7:22 ` kfree(NULL) James Morris
  0 siblings, 1 reply; 42+ messages in thread
From: Daniel Walker @ 2006-04-21  7:03 UTC (permalink / raw)
  To: linux-kernel

	I included a patch , not like it's needed . Recently I've been
evaluating likely/unlikely branch prediction .. One thing that I found 
is that the kfree function is often called with a NULL "objp" . In fact
it's so frequent that the "unlikely" branch predictor should be inverted!
Or at least on my configuration. 

Here are some examples of the warnings that I observed ..

printk: 66 messages suppressed.
BUG: warning at mm/slab.c:3384/kfree()
 <c01043d3> show_trace+0x13/0x20   <c01043fe> dump_stack+0x1e/0x20
 <c015e334> kfree+0xa4/0xc0   <c032584b> make_request+0x36b/0x670
 <c0210305> generic_make_request+0x175/0x240   <c02107d7> submit_bio+0x57/0x100
 <c01648f6> submit_bh+0x106/0x160   <c0165a62> __block_write_full_page+0x222/0x3f0
 <c0165d28> block_write_full_page+0xf8/0x100   <c016a4b1> blkdev_writepage+0x21/0x30
 <c0188c1e> mpage_writepages+0x1ae/0x3d0   <c016a46e> generic_writepages+0x1e/0x20
 <c0148f9d> do_writepages+0x2d/0x50   <c0186b70> __writeback_single_inode+0xa0/0x400
 <c018716b> sync_sb_inodes+0x1bb/0x2a0   <c01877bf> writeback_inodes+0xaf/0xe5
 <c0148d53> wb_kupdate+0x83/0x100   <c0149ab2> pdflush+0x102/0x1c0
 <c0131fa4> kthread+0xc4/0xf0   <c0100ed5> kernel_thread_helper+0x5/0x10
printk: 157 messages suppressed.
BUG: warning at mm/slab.c:3384/kfree()
 <c01043d3> show_trace+0x13/0x20   <c01043fe> dump_stack+0x1e/0x20
 <c015e334> kfree+0xa4/0xc0   <c0140405> audit_syscall_exit+0x405/0x430
 <c0106a56> do_syscall_trace+0x1d6/0x245   <c010320a> syscall_exit_work+0x16/0x1c


Daniel

Index: linux-2.6.16/mm/slab.c
===================================================================
--- linux-2.6.16.orig/mm/slab.c
+++ linux-2.6.16/mm/slab.c
@@ -3380,8 +3380,10 @@ void kfree(const void *objp)
 	struct kmem_cache *c;
 	unsigned long flags;
 
-	if (unlikely(!objp))
+	if (unlikely(!objp)){
+		WARN_ON(printk_ratelimit());
 		return;
+	}
 	local_irq_save(flags);
 	kfree_debugcheck(objp);
 	c = virt_to_cache(objp);

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2006-04-23 16:50 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <63XWg-1IL-5@gated-at.bofh.it>
     [not found] ` <63YfP-26I-11@gated-at.bofh.it>
     [not found]   ` <63ZEY-45n-27@gated-at.bofh.it>
2006-04-21 15:25     ` kfree(NULL) Tilman Schmidt
2006-04-21 16:03       ` kfree(NULL) Daniel Walker
2006-04-21 17:48         ` kfree(NULL) Jörn Engel
2006-04-21 18:00         ` kfree(NULL) Steven Rostedt
2006-04-21 18:42           ` kfree(NULL) Daniel Walker
2006-04-21 18:56             ` kfree(NULL) Steven Rostedt
2006-04-21 19:26           ` kfree(NULL) Andrew Morton
2006-04-22 12:05 kfree(NULL) linux
  -- strict thread matches above, loose matches on Subject: below --
2006-04-21 21:02 kfree(NULL) Hua Zhong
2006-04-21 21:11 ` kfree(NULL) Daniel Walker
2006-04-21 21:36   ` kfree(NULL) Michael Buesch
2006-04-21 21:42 ` kfree(NULL) Andrew Morton
2006-04-21 21:48   ` kfree(NULL) Andrew Morton
2006-04-21 22:53   ` kfree(NULL) Hua Zhong
2006-04-21 22:58     ` kfree(NULL) Daniel Walker
2006-04-21 23:03       ` kfree(NULL) Hua Zhong
2006-04-21 23:25     ` kfree(NULL) Andrew Morton
2006-04-21 23:27     ` kfree(NULL) Andrew Morton
2006-04-22 11:18   ` kfree(NULL) Jan Engelhardt
2006-04-21  7:03 kfree(NULL) Daniel Walker
2006-04-21  7:22 ` kfree(NULL) James Morris
2006-04-21  8:54   ` kfree(NULL) Andrew Morton
2006-04-21 13:56     ` kfree(NULL) Vernon Mauery
2006-04-21 14:07       ` kfree(NULL) Dmitry Fedorov
2006-04-21 15:07         ` kfree(NULL) Jan Engelhardt
2006-04-21 19:22           ` kfree(NULL) Adrian Bunk
2006-04-21 20:30             ` kfree(NULL) Vernon Mauery
2006-04-21 20:54               ` kfree(NULL) Steven Rostedt
2006-04-21 21:38               ` kfree(NULL) Adrian Bunk
2006-04-22 11:56               ` kfree(NULL) Jörn Engel
2006-04-21 23:55     ` kfree(NULL) Paul Mackerras
2006-04-22  7:43       ` kfree(NULL) Pekka Enberg
2006-04-22  8:48         ` kfree(NULL) Paul Mackerras
2006-04-22 15:02           ` kfree(NULL) Pekka Enberg
2006-04-22 18:57           ` kfree(NULL) Hua Zhong
2006-04-22 19:05             ` kfree(NULL) Nick Piggin
2006-04-22 19:22               ` kfree(NULL) Hua Zhong
2006-04-22 19:25                 ` kfree(NULL) Nick Piggin
2006-04-22 20:18                   ` kfree(NULL) Jan Engelhardt
2006-04-23 16:50               ` kfree(NULL) Steven Rostedt
2006-04-22 11:34       ` kfree(NULL) Jesper Juhl
2006-04-21 14:06   ` kfree(NULL) Daniel Walker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox