commit 0bd97a8061c2ebbe792da8b662c5d19b2f1af02c Author: William Cohen Date: Mon Sep 13 21:32:38 2021 -0400 Use task_state tapset function to avoid task_struct changes The Linux 5.14 kernel's task_struct changed the state field to __state. The task_state tapset function selects the appropriate version. Make the scheduler.stp tapset and schedtimes.stp example use the task_state function rather than directly trying to access the task_struct state field (and get it wrong for newer kernels). diff --git a/tapset/linux/scheduler.stp b/tapset/linux/scheduler.stp index 7338e9008..4667ab53a 100644 --- a/tapset/linux/scheduler.stp +++ b/tapset/linux/scheduler.stp @@ -138,7 +138,7 @@ probe scheduler.ctxswitch = kernel.trace("sched_switch") !, prev_tid = $prev_p->pid prev_task = $prev_p prev_task_name = task_execname($prev_p) - prevtsk_state = $prev_p->state + prevtsk_state = task_state($prev_p) } else { prev_priority = $prev->prio @@ -146,7 +146,7 @@ probe scheduler.ctxswitch = kernel.trace("sched_switch") !, prev_tid = $prev->pid prev_task = $prev prev_task_name = task_execname($prev) - prevtsk_state = $prev->state + prevtsk_state = task_state($prev) } if (@defined($next)) { @@ -155,7 +155,7 @@ probe scheduler.ctxswitch = kernel.trace("sched_switch") !, next_tid = $next->pid next_task = $next next_task_name = task_execname($next) - nexttsk_state = $next->state + nexttsk_state = task_state($next) } else if (@defined($next_p)) { next_priority = $next_p->prio @@ -163,7 +163,7 @@ probe scheduler.ctxswitch = kernel.trace("sched_switch") !, next_tid = $next_p->pid next_task = $next_p next_task_name = task_execname($next_p) - nexttsk_state = $next_p->state + nexttsk_state = task_state($next_p) } else { next_priority = $new->prio @@ -171,7 +171,7 @@ probe scheduler.ctxswitch = kernel.trace("sched_switch") !, next_tid = $new->pid next_task = $new next_task_name = task_execname($new) - nexttsk_state = $new->state + nexttsk_state = task_state($new) } } diff --git a/testsuite/systemtap.examples/process/schedtimes.stp b/testsuite/systemtap.examples/process/schedtimes.stp index 4e422c893..ee1053045 100755 --- a/testsuite/systemtap.examples/process/schedtimes.stp +++ b/testsuite/systemtap.examples/process/schedtimes.stp @@ -99,7 +99,7 @@ probe kernel.trace("sched_switch") // Task $prev is scheduled off this cpu if (task_targeted($prev)) { pid = $prev->pid - state = $prev->state + state = task_state($prev) update_times(pid, timestamp()) if (state > 0) { commit a29f65d5750f6379afeca99c5d641598ff638517 Author: Stan Cox Date: Sun Jul 18 21:32:51 2021 -0400 PR28079: Adapt to kernel 5.14 task_struct.__state change Use signal_wake_up_state for the 5.14 kernel which changed volatile long state to unsigned int __state. diff --git a/buildrun.cxx b/buildrun.cxx index a1332a687..ae27ddea4 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -523,3 +523,4 @@ compile_pass (systemtap_session& s) output_autoconf(s, o, cs, "autoconf-lockdown-kernel.c", "STAPCONF_LOCKDOWN_KERNEL", NULL); + output_autoconf(s, o, cs, "autoconf-task-state.c", "STAPCONF_TASK_STATE", NULL); // used by runtime/linux/netfilter.c output_exportconf(s, o2, "nf_register_hook", "STAPCONF_NF_REGISTER_HOOK"); diff --git a/runtime/linux/autoconf-task-state.c b/runtime/linux/autoconf-task-state.c new file mode 100644 index 000000000..27a1d7c13 --- /dev/null +++ b/runtime/linux/autoconf-task-state.c @@ -0,0 +1,18 @@ +/* + * Is this a kernel prior to the following kernel commit: + * + * commit 2f064a59a11ff9bc22e52e9678bc601404c7cb34 + * Author: Peter Zijlstra + * Date: 2021-06-11 10:28:17 +0200 + * + * sched: Change task_struct::state + * Change the type and name of task_struct::state. Drop the volatile and + * shrink it to an 'unsigned int'. Rename it in order to find all uses + * such that we can use READ_ONCE/WRITE_ONCE as appropriate. + */ + +#include + +unsigned int bar (struct task_struct *foo) { + return (foo->state = 0); +} diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c index ff8c5549d..d63e6366c 100644 --- a/runtime/stp_utrace.c +++ b/runtime/stp_utrace.c @@ -33,9 +33,12 @@ #if defined(__set_task_state) #define __stp_set_task_state(tsk, state_value) \ __set_task_state((tsk), (state_value)) -#else +#elif defined(STAPCONF_TASK_STATE) #define __stp_set_task_state(tsk, state_value) \ do { (tsk)->state = (state_value); } while (0) +#else +#define __stp_set_task_state(tsk, state_value) \ + signal_wake_up_state((tsk), (state_value)) #endif // For now, disable the task_work_queue on non-RT kernels. @@ -1263,7 +1266,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) spin_lock_irq(&target->sighand->siglock); if (target->signal->flags & SIGNAL_STOP_STOPPED || target->signal->group_stop_count) - target->state = TASK_STOPPED; + __stp_set_task_state(target, TASK_STOPPED); else stp_wake_up_state(target, __TASK_TRACED); spin_unlock_irq(&target->sighand->siglock);