[ltt-dev] [patch] add tracepoints to trace activate/deactivate task

Jason Baron jbaron at redhat.com
Mon Dec 8 14:49:48 EST 2008


hi,

I thought it would be useful to track when a task is
'activated/deactivated'. This case is different from wakeup/wait, in that
task can be activated and deactivated, when the scheduler re-balances
tasks, the allowable cpuset changes, or cpu hotplug occurs. Using these
patches I can more precisely figure out when a task becomes runnable and
why. 

Patch to add these tracepoints to the lttng tree is below. I'm also including a 
systemtap script, originally written by Oracle, but which I've modified to work
with these new tracepoints.

thanks,

-Jason

Signed-off-by: Jason Baron <jbaron at redhat.com>


diff --git a/include/trace/sched.h b/include/trace/sched.h
index fe4767d..d1fd8a3 100644
--- a/include/trace/sched.h
+++ b/include/trace/sched.h
@@ -4,6 +4,8 @@
 #include <linux/sched.h>
 #include <linux/tracepoint.h>
 
+struct rq;
+
 DECLARE_TRACE(sched_kthread_stop,
 	TPPROTO(struct task_struct *t),
 	TPARGS(t));
@@ -44,5 +46,13 @@ DECLARE_TRACE(sched_signal_send,
 DECLARE_TRACE(sched_kthread_create,
 	TPPROTO(void *fn, int pid),
 	TPARGS(fn, pid));
+DECLARE_TRACE(sched_activate_task,
+	TPPROTO(struct task_struct *p, struct rq *rq),
+	TPARGS(p, rq));
+DECLARE_TRACE(sched_deactivate_task,
+	TPPROTO(struct task_struct *p, struct rq *rq),
+	TPARGS(p, rq));
+
+
 
 #endif
diff --git a/kernel/sched.c b/kernel/sched.c
index cc7f048..7b707cf 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -122,6 +122,8 @@ DEFINE_TRACE(sched_wakeup);
 DEFINE_TRACE(sched_wakeup_new);
 DEFINE_TRACE(sched_switch);
 DEFINE_TRACE(sched_migrate_task);
+DEFINE_TRACE(sched_activate_task);
+DEFINE_TRACE(sched_deactivate_task);
 
 #ifdef CONFIG_SMP
 /*
@@ -1716,6 +1718,7 @@ static int effective_prio(struct task_struct *p)
  */
 static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
 {
+	trace_sched_activate_task(p, rq);
 	if (task_contributes_to_load(p))
 		rq->nr_uninterruptible--;
 
@@ -1728,6 +1731,7 @@ static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
  */
 static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
 {
+	trace_sched_deactivate_task(p, rq);
 	if (task_contributes_to_load(p))
 		rq->nr_uninterruptible++;
 
@@ -2420,6 +2424,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
 		 * Let the scheduling class do new task startup
 		 * management (if any):
 		 */
+		trace_sched_activate_task(p, rq);
 		p->sched_class->task_new(rq, p);
 		inc_nr_running(rq);
 	}
diff --git a/ltt/probes/kernel-trace.c b/ltt/probes/kernel-trace.c
index e241499..c27e671 100644
--- a/ltt/probes/kernel-trace.c
+++ b/ltt/probes/kernel-trace.c
@@ -372,6 +372,19 @@ void probe_kernel_vprintk(unsigned long retaddr, char *buf, int len)
 	}
 }
 
+void probe_activate_task(struct task_struct *p, struct rq *rq)
+{
+	trace_mark_tp(kernel_activate_task, sched_activate_task, probe_activate_task,
+		"pid %d state %ld cpu_id %u", p->pid, p->state, task_cpu(p));
+}
+
+void probe_deactivate_task(struct task_struct *p, struct rq *rq)
+{
+	trace_mark_tp(kernel_deactivate_task, sched_deactivate_task,
+		probe_deactivate_task, "pid %d state %ld cpu_id %u",
+		p->pid, p->state, task_cpu(p));
+}
+
 #ifdef CONFIG_MODULES
 void probe_kernel_module_free(struct module *mod)
 {



#!/usr/bin/env stap  
#
# Copyright (C) 2007 Oracle Corp.
#
# Trace state transition of one specified process
#
# GNU General Public License (GPL); either version 2, or (at your option) any
# later version.
#
# Parameter 1: specified process id
#
# Usage:
#  ./proc_transition_by_pid.stp -gx 1234
#
# Output:
#  Process 1234: TASK_RUNNING -> TASK_INTERRUPTIBLE
#  Process 1234: TASK_RUNNING -> TASK_STOP
#    ...
#
# Note:  timestamp may be not exactly point to transition moment. Fix me!

global id_state
global traced_pid
global task_name


/*return task name according to process id*/
function __get_task_name: string (pid:long) %{
        struct task_struct *p;
        pid_t pid;

        pid = (pid_t)(long)THIS->pid;

        rcu_read_lock();
        p = find_task_by_vpid(pid);
        rcu_read_unlock();

        if (p==NULL)
                strlcpy(THIS->__retvalue,"Unknown",MAXSTRINGLEN);
        else  {
                strlcpy(THIS->__retvalue,p->comm,MAXSTRINGLEN);
              }
        CATCH_DEREF_FAULT();
%}

function __get_task_struct: long (pid:long) %{
        struct task_struct *p;
        pid_t pid;

        pid = (pid_t)(long)THIS->pid;

        rcu_read_lock();
        p = find_task_by_vpid(pid);
        rcu_read_unlock();

        if (p==NULL)
                THIS->__retvalue=(long)NULL;
        else  {
                THIS->__retvalue=(long)p;
              }
        CATCH_DEREF_FAULT();
%}

/* process added into runqueue : really running or well prepared */
probe kernel.mark("kernel_activate_task"){
	if ($arg1==traced_pid)
		printf("[%d] %s(%d): %s --> TASK_RUNNING\n",get_cycles(),task_name,traced_pid,id_state[$arg2]);
}

/* process removed from runqueue : in wait queue or other state */
probe kernel.mark("kernel_deactivate_task") {
	if ($arg1==traced_pid)
		printf("[%d] %s(%d): TASK_RUNNING --> %s\n", get_cycles(),task_name,traced_pid, id_state[$arg2]);
}

/* process clean up */
probe kernel.mark("kernel_process_exit") {
        if ($arg1==traced_pid){
          printf("[%d] %s(%d): %s --> Cleaned \n", get_cycles(),task_execname(__get_task_struct($arg1)),traced_pid,id_state[task_state(__get_task_struct($arg1))]);
          exit()
        }
}

/* accept one parameter as process id
*  if not in correct format, step1 parse reports error*/
probe begin {
	/*from sched.h*/
	id_state[0] = "TASK_RUNNING"
	id_state[1] = "TASK_INTERRUPTIBLE"
	id_state[2] = "TASK_UNINTERRUPTIBLE"
	id_state[4] = "TASK_STOPPED"
	id_state[8] = "TASK_TRACED"
	/* exit_state
	id_state[16] = "EXIT_ZOMBIE"
	id_state[32] = "EXIT_DEAD"
	*/
	id_state[64] = "TASK_NONINTERACTIVE"
	id_state[128] = "TASK_DEAD"

        traced_pid = target();
	task_name = __get_task_name(traced_pid);
	if (task_name!="Unknown") {
		   printf("Now scanning the process...%s %d\n\n", task_name, traced_pid);
 	    }
        else  {	
	   printf("No such process!\n");
	   exit();
	   }
}
	
probe end{
	delete id_state;
	delete traced_pid;
	delete task_name;
}




More information about the lttng-dev mailing list