Skip to content
  • Steven Rostedt's avatar
    tracing/context-tracking: Add preempt_schedule_context() for tracing · 29bb9e5a
    Steven Rostedt authored
    
    
    Dave Jones hit the following bug report:
    
     ===============================
     [ INFO: suspicious RCU usage. ]
     3.10.0-rc2+ #1 Not tainted
     -------------------------------
     include/linux/rcupdate.h:771 rcu_read_lock() used illegally while idle!
     other info that might help us debug this:
     RCU used illegally from idle CPU! rcu_scheduler_active = 1, debug_locks = 0
     RCU used illegally from extended quiescent state!
     2 locks held by cc1/63645:
      #0:  (&rq->lock){-.-.-.}, at: [<ffffffff816b39fd>] __schedule+0xed/0x9b0
      #1:  (rcu_read_lock){.+.+..}, at: [<ffffffff8109d645>] cpuacct_charge+0x5/0x1f0
    
     CPU: 1 PID: 63645 Comm: cc1 Not tainted 3.10.0-rc2+ #1 [loadavg: 40.57 27.55 13.39 25/277 64369]
     Hardware name: Gigabyte Technology Co., Ltd. GA-MA78GM-S2H/GA-MA78GM-S2H, BIOS F12a 04/23/2010
      0000000000000000 ffff88010f78fcf8 ffffffff816ae383 ffff88010f78fd28
      ffffffff810b698d ffff88011c092548 000000000023d073 ffff88011c092500
      0000000000000001 ffff88010f78fd60 ffffffff8109d7c5 ffffffff8109d645
     Call Trace:
      [<ffffffff816ae383>] dump_stack+0x19/0x1b
      [<ffffffff810b698d>] lockdep_rcu_suspicious+0xfd/0x130
      [<ffffffff8109d7c5>] cpuacct_charge+0x185/0x1f0
      [<ffffffff8109d645>] ? cpuacct_charge+0x5/0x1f0
      [<ffffffff8108dffc>] update_curr+0xec/0x240
      [<ffffffff8108f528>] put_prev_task_fair+0x228/0x480
      [<ffffffff816b3a71>] __schedule+0x161/0x9b0
      [<ffffffff816b4721>] preempt_schedule+0x51/0x80
      [<ffffffff816b4800>] ? __cond_resched_softirq+0x60/0x60
      [<ffffffff816b6824>] ? retint_careful+0x12/0x2e
      [<ffffffff810ff3cc>] ftrace_ops_control_func+0x1dc/0x210
      [<ffffffff816be280>] ftrace_call+0x5/0x2f
      [<ffffffff816b681d>] ? retint_careful+0xb/0x2e
      [<ffffffff816b4805>] ? schedule_user+0x5/0x70
      [<ffffffff816b4805>] ? schedule_user+0x5/0x70
      [<ffffffff816b6824>] ? retint_careful+0x12/0x2e
     ------------[ cut here ]------------
    
    What happened was that the function tracer traced the schedule_user() code
    that tells RCU that the system is coming back from userspace, and to
    add the CPU back to the RCU monitoring.
    
    Because the function tracer does a preempt_disable/enable_notrace() calls
    the preempt_enable_notrace() checks the NEED_RESCHED flag. If it is set,
    then preempt_schedule() is called. But this is called before the user_exit()
    function can inform the kernel that the CPU is no longer in user mode and
    needs to be accounted for by RCU.
    
    The fix is to create a new preempt_schedule_context() that checks if
    the kernel is still in user mode and if so to switch it to kernel mode
    before calling schedule. It also switches back to user mode coming back
    from schedule in need be.
    
    The only user of this currently is the preempt_enable_notrace(), which is
    only used by the tracing subsystem.
    
    Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    Signed-off-by: default avatarPeter Zijlstra <peterz@infradead.org>
    Link: http://lkml.kernel.org/r/1369423420.6828.226.camel@gandalf.local.home
    
    
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    29bb9e5a