For CONFIG_PREEMPT=y kernels the sched_switch(.prev_state) argument isn't useful because we can get preempted with current->state != TASK_RUNNING without actually getting removed from the runqueue. Cure this by treating all preempted tasks as runnable from the tracer's point of view.
Showing the changes to include/trace (1 of 1 file). Show all
Unified · Split
| @@ -115,6 +115,23 @@ DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new, · 114 unmodified lines | ||
| 115 | 115 | TP_PROTO(struct task_struct *p, int success), |
| 116 | 116 | TP_ARGS(p, success)); |
| 117 | 117 | |
| 118 | +#ifdef CREATE_TRACE_POINTS | |
| 119 | +static inline long __trace_sched_switch_state(struct task_struct *p) | |
| 120 | +{ | |
| 121 | + long state = p->state; | |
| 122 | + | |
| 123 | +#ifdef CONFIG_PREEMPT | |
| 124 | + /* | |
| 125 | + * For all intents and purposes a preempted task is a running task. | |
| 126 | + */ | |
| 127 | + if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE) | |
| 128 | + state = TASK_RUNNING; | |
| 129 | +#endif | |
| 130 | + | |
| 131 | + return state; | |
| 132 | +} | |
| 133 | +#endif | |
| 134 | + | |
| 118 | 135 | /* |
| 119 | 136 | * Tracepoint for task switches, performed by the scheduler: |
| 120 | 137 | */ |
| @@ -139,7 +156,7 @@ TRACE_EVENT(sched_switch, · 18 unmodified lines | ||
| 139 | 156 | memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN); |
| 140 | 157 | __entry->prev_pid = prev->pid; |
| 141 | 158 | __entry->prev_prio = prev->prio; |
| 142 | − __entry->prev_state = prev->state; | |
| 159 | + __entry->prev_state = __trace_sched_switch_state(prev); | |
| 143 | 160 | memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); |
| 144 | 161 | __entry->next_pid = next->pid; |
| 145 | 162 | __entry->next_prio = next->prio; |