Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

printk/sched: Introduce special printk_sched() for those awkward moments

There's a few awkward printk()s inside of scheduler guts that people
prefer to keep but really are rather deadlock prone. Fudge around it
by storing the text in a per-cpu buffer and poll it using the existing
printk_tick() handler.

This will drop output when its more frequent than once a tick, however
only the affinity thing could possible go that fast and for that just
one should suffice to notify the admin he's done something silly..

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Link: http://lkml.kernel.org/n/tip-wua3lmkt3dg8nfts66o6brne@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Peter Zijlstra and committed by
Ingo Molnar
3ccf3e83 554cecaf

+55 -5
+10
include/linux/printk.h
··· 101 101 int printk(const char *fmt, ...); 102 102 103 103 /* 104 + * Special printk facility for scheduler use only, _DO_NOT_USE_ ! 105 + */ 106 + __printf(1, 2) __cold int printk_sched(const char *fmt, ...); 107 + 108 + /* 104 109 * Please don't use printk_ratelimit(), because it shares ratelimiting state 105 110 * with all other unrelated printk_ratelimit() callsites. Instead use 106 111 * printk_ratelimited() or plain old __ratelimit(). ··· 129 124 } 130 125 static inline __printf(1, 2) __cold 131 126 int printk(const char *s, ...) 127 + { 128 + return 0; 129 + } 130 + static inline __printf(1, 2) __cold 131 + int printk_sched(const char *s, ...) 132 132 { 133 133 return 0; 134 134 }
+37 -3
kernel/printk.c
··· 1208 1208 return console_locked; 1209 1209 } 1210 1210 1211 + /* 1212 + * Delayed printk facility, for scheduler-internal messages: 1213 + */ 1214 + #define PRINTK_BUF_SIZE 512 1215 + 1216 + #define PRINTK_PENDING_WAKEUP 0x01 1217 + #define PRINTK_PENDING_SCHED 0x02 1218 + 1211 1219 static DEFINE_PER_CPU(int, printk_pending); 1220 + static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); 1221 + 1222 + int printk_sched(const char *fmt, ...) 1223 + { 1224 + unsigned long flags; 1225 + va_list args; 1226 + char *buf; 1227 + int r; 1228 + 1229 + local_irq_save(flags); 1230 + buf = __get_cpu_var(printk_sched_buf); 1231 + 1232 + va_start(args, fmt); 1233 + r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args); 1234 + va_end(args); 1235 + 1236 + __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); 1237 + local_irq_restore(flags); 1238 + 1239 + return r; 1240 + } 1212 1241 1213 1242 void printk_tick(void) 1214 1243 { 1215 1244 if (__this_cpu_read(printk_pending)) { 1216 - __this_cpu_write(printk_pending, 0); 1217 - wake_up_interruptible(&log_wait); 1245 + int pending = __this_cpu_xchg(printk_pending, 0); 1246 + if (pending & PRINTK_PENDING_SCHED) { 1247 + char *buf = __get_cpu_var(printk_sched_buf); 1248 + printk(KERN_WARNING "[sched_delayed] %s", buf); 1249 + } 1250 + if (pending & PRINTK_PENDING_WAKEUP) 1251 + wake_up_interruptible(&log_wait); 1218 1252 } 1219 1253 } 1220 1254 ··· 1262 1228 void wake_up_klogd(void) 1263 1229 { 1264 1230 if (waitqueue_active(&log_wait)) 1265 - this_cpu_write(printk_pending, 1); 1231 + this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); 1266 1232 } 1267 1233 1268 1234 /**
+1 -1
kernel/sched/core.c
··· 1284 1284 * leave kernel. 1285 1285 */ 1286 1286 if (p->mm && printk_ratelimit()) { 1287 - printk(KERN_INFO "process %d (%s) no longer affine to cpu%d\n", 1287 + printk_sched("process %d (%s) no longer affine to cpu%d\n", 1288 1288 task_pid_nr(p), p->comm, cpu); 1289 1289 } 1290 1290
+7 -1
kernel/sched/rt.c
··· 864 864 * but accrue some time due to boosting. 865 865 */ 866 866 if (likely(rt_b->rt_runtime)) { 867 + static bool once = false; 868 + 867 869 rt_rq->rt_throttled = 1; 868 - printk_once(KERN_WARNING "sched: RT throttling activated\n"); 870 + 871 + if (!once) { 872 + once = true; 873 + printk_sched("sched: RT throttling activated\n"); 874 + } 869 875 } else { 870 876 /* 871 877 * In case we did anyway, make it go away,