Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 377261
b: refs/heads/master
c: 29bb9e5
h: refs/heads/master
i:
  377259: e4d6912
v: v3
  • Loading branch information
Steven Rostedt authored and Ingo Molnar committed Jun 19, 2013
1 parent a44e22d commit 6a59876
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 873b4c65b519fd769940eb281f77848227d4e5c1
refs/heads/master: 29bb9e5a75684106a37593ad75ec75ff8312731b
18 changes: 17 additions & 1 deletion trunk/include/linux/preempt.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,25 @@ do { \
preempt_schedule(); \
} while (0)

#ifdef CONFIG_CONTEXT_TRACKING

void preempt_schedule_context(void);

#define preempt_check_resched_context() \
do { \
if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
preempt_schedule_context(); \
} while (0)
#else

#define preempt_check_resched_context() preempt_check_resched()

#endif /* CONFIG_CONTEXT_TRACKING */

#else /* !CONFIG_PREEMPT */

#define preempt_check_resched() do { } while (0)
#define preempt_check_resched_context() do { } while (0)

#endif /* CONFIG_PREEMPT */

Expand Down Expand Up @@ -88,7 +104,7 @@ do { \
do { \
preempt_enable_no_resched_notrace(); \
barrier(); \
preempt_check_resched(); \
preempt_check_resched_context(); \
} while (0)

#else /* !CONFIG_PREEMPT_COUNT */
Expand Down
40 changes: 40 additions & 0 deletions trunk/kernel/context_tracking.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,46 @@ void user_enter(void)
local_irq_restore(flags);
}

#ifdef CONFIG_PREEMPT
/**
* preempt_schedule_context - preempt_schedule called by tracing
*
* The tracing infrastructure uses preempt_enable_notrace to prevent
* recursion and tracing preempt enabling caused by the tracing
* infrastructure itself. But as tracing can happen in areas coming
* from userspace or just about to enter userspace, a preempt enable
* can occur before user_exit() is called. This will cause the scheduler
* to be called when the system is still in usermode.
*
* To prevent this, the preempt_enable_notrace will use this function
* instead of preempt_schedule() to exit user context if needed before
* calling the scheduler.
*/
void __sched notrace preempt_schedule_context(void)
{
struct thread_info *ti = current_thread_info();
enum ctx_state prev_ctx;

if (likely(ti->preempt_count || irqs_disabled()))
return;

/*
* Need to disable preemption in case user_exit() is traced
* and the tracer calls preempt_enable_notrace() causing
* an infinite recursion.
*/
preempt_disable_notrace();
prev_ctx = exception_enter();
preempt_enable_no_resched_notrace();

preempt_schedule();

preempt_disable_notrace();
exception_exit(prev_ctx);
preempt_enable_notrace();
}
EXPORT_SYMBOL_GPL(preempt_schedule_context);
#endif /* CONFIG_PREEMPT */

/**
* user_exit - Inform the context tracking that the CPU is
Expand Down

0 comments on commit 6a59876

Please sign in to comment.