diff options
Diffstat (limited to 'tapset')
-rw-r--r-- | tapset/indent.stp | 6 | ||||
-rw-r--r-- | tapset/proc_mem.stp | 194 | ||||
-rw-r--r-- | tapset/scheduler.stp | 353 |
3 files changed, 497 insertions, 56 deletions
diff --git a/tapset/indent.stp b/tapset/indent.stp index 1dbbebd4..2f850bfd 100644 --- a/tapset/indent.stp +++ b/tapset/indent.stp @@ -9,11 +9,7 @@ function _generic_indent (idx, desc, delta) x = _indent_counters[idx] + (delta > 0 ? delta : 0) _indent_counters[idx] += delta - r = sprintf("%6d %s:", (ts - _indent_timestamps[idx]), desc) - - for (i=1; i<x; i++) r .= " " - - return r + return sprintf("%6d %s:%-*s", (ts - _indent_timestamps[idx]), desc, (x>0 ? x-1 : 0), "") } /** diff --git a/tapset/proc_mem.stp b/tapset/proc_mem.stp new file mode 100644 index 00000000..1493bd92 --- /dev/null +++ b/tapset/proc_mem.stp @@ -0,0 +1,194 @@ +// Process memory query and utility functions. +// Copyright (C) 2009 Red Hat Inc. +// +// This file is part of systemtap, and is free software. You can +// redistribute it and/or modify it under the terms of the GNU General +// Public License (GPL); either version 2, or (at your option) any +// later version. + +// <tapsetdescription> +// Process memory query and utility functions provide information about +// the memory usage of the current application. These functions provide +// information about the full size, resident, shared, code and data used +// by the current process. And provide utility functions to query the +// page size of the current architecture and create human readable string +// representations of bytes and pages used. +// </tapsetdescription> + +%{ +/* PF_BORROWED_MM got renamed to PF_KTHREAD with same semantics somewhere. */ +#ifdef PF_BORROWED_MM +#define _STP_PF_KTHREAD PF_BORROWED_MM +#else +#define _STP_PF_KTHREAD PF_KTHREAD +#endif + /* Returns the mm for the current proc. Slightly paranoid. Only returns + if the task isn't starting, exiting or (coopted by) a kernel thread. */ + static struct mm_struct *_stp_proc_mm(void) + { + if (current->flags & (_STP_PF_KTHREAD | PF_EXITING | PF_STARTING)) + return NULL; + return current->mm; + } +%} + +/** + * sfunction proc_mem_size - Total program virtual memory size in pages. + * + * Description: Returns the total virtual memory size in pages of the + * current process, or zero when there is no current process or the + * number of pages couldn't be retrieved. + */ +function proc_mem_size:long () +%{ /* pure */ /* unprivileged */ + struct mm_struct *mm = _stp_proc_mm (); + if (mm) + THIS->__retvalue = mm->total_vm; + else + THIS->__retvalue = 0; +%} + +/** + * sfunction proc_mem_rss - Program resident set size in pages. + * + * Description: Returns the resident set size in pages of the current + * process, or zero when there is no current process or the number of + * pages couldn't be retrieved. + */ +function proc_mem_rss:long () +%{ /* pure */ /* unprivileged */ + struct mm_struct *mm = _stp_proc_mm (); + if (mm) + THIS->__retvalue = (get_mm_counter(mm, file_rss) + + get_mm_counter(mm, anon_rss)); + else + THIS->__retvalue = 0; +%} + +/** + * sfunction proc_mem_shr - Program shared pages (from shared mappings). + * + * Description: Returns the shared pages (from shared mappings) of the + * current process, or zero when there is no current process or the + * number of pages couldn't be retrieved. + */ +function proc_mem_shr:long () +%{ /* pure */ /* unprivileged */ + struct mm_struct *mm = _stp_proc_mm (); + if (mm) + THIS->__retvalue = get_mm_counter(mm, file_rss); + else + THIS->__retvalue = 0; +%} + +/** + * sfunction proc_mem_txt - Program text (code) size in pages. + * + * Description: Returns the current process text (code) size in pages, + * or zero when there is no current process or the number of pages + * couldn't be retrieved. + */ +function proc_mem_txt:long () +%{ /* pure */ /* unprivileged */ + struct mm_struct *mm = _stp_proc_mm (); + if (mm) + THIS->__retvalue = (PAGE_ALIGN(mm->end_code) + - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT; + else + THIS->__retvalue = 0; +%} + +/** + * sfunction proc_mem_data - Program data size (data + stack) in pages. + * + * Description: Returns the current process data size (data + stack) + * in pages, or zero when there is no current process or the number of + * pages couldn't be retrieved. + */ +function proc_mem_data:long () +%{ /* pure */ /* unprivileged */ + struct mm_struct *mm = _stp_proc_mm (); + if (mm) + THIS->__retvalue = mm->total_vm - mm->shared_vm; + else + THIS->__retvalue = 0; +%} + +/** + * sfunction mem_page_size - Number of bytes in a page for this architecture. + */ +function mem_page_size:long () +%{ /* pure */ /* unprivileged */ + THIS->__retvalue = PAGE_SIZE; +%} + +// Return a 5 character wide string " x.yyp", " xx.yp", " xxxp", "xxxxp". +function _stp_number_to_string_postfix:string (x:long, y:long, p:string) +{ + if (x < 10) + return sprintf("%d.%.2d%s", x, y * 100 / 1024, p); + if (x < 100) + return sprintf("%2d.%d%s", x, y * 10 / 1024, p); + return sprintf("%4d%s", x, p); +} + +/** + * sfunction bytes_to_string - Human readable string for given bytes. + * + * Description: Returns a string representing the number of bytes (up + * to 1024 bytes), the number of kilobytes (when less than 1024K) + * postfixed by 'K', the number of megabytes (when less than 1024M) + * postfixed by 'M' or the number of gigabytes postfixed by 'G'. If + * representing K, M or G, and the number is amount is less than 100, + * it includes a '.' plus the remainer. The returned string will be 5 + * characters wide (padding with whitespace at the front) unless + * negative or representing more than 9999G bytes. + */ +function bytes_to_string:string (bytes:long) +{ + if (bytes < 1024) + return sprintf("%5d", bytes); + + remain = bytes % 1024; + bytes = bytes / 1024; + if (bytes < 1024) + return _stp_number_to_string_postfix(bytes, remain, "K"); + + remain = bytes % 1024; + bytes = bytes / 1024; + if (bytes < 1024) + return _stp_number_to_string_postfix(bytes, remain, "M"); + + remain = bytes % 1024; + bytes = bytes / 1024; + return _stp_number_to_string_postfix(bytes, remain, "G"); +} + +/** + * sfunction pages_to_string - Turns pages into a human readable string. + * + * Description: Multiplies pages by page_size() to get the number of + * bytes and returns the result of bytes_to_string(). + */ +function pages_to_string:string (pages:long) +{ + bytes = pages * mem_page_size(); + return bytes_to_string (bytes); +} + +/** + * sfunction proc_mem_string - Human readable string of current proc memory usage. + * + * Description: Returns a human readable string showing the size, rss, + * shr, txt and data of the memory used by the current process. + * For example "size: 301m, rss: 11m, shr: 8m, txt: 52k, data: 2248k". + */ +function proc_mem_string:string () +{ + return sprintf ("size: %s, rss: %s, shr: %s, txt: %s, data: %s", + pages_to_string(proc_mem_size()), + pages_to_string(proc_mem_rss()), + pages_to_string(proc_mem_shr()), + pages_to_string(proc_mem_txt()), + pages_to_string(proc_mem_data())); +} diff --git a/tapset/scheduler.stp b/tapset/scheduler.stp index 3c3d504e..b1911ac2 100644 --- a/tapset/scheduler.stp +++ b/tapset/scheduler.stp @@ -20,7 +20,7 @@ function __is_idle:long() %} -/* probe scheduler.cpu_off +/** probe scheduler.cpu_off * * Fires when a process is about to stop running on a cpu. * @@ -41,7 +41,7 @@ probe scheduler.cpu_off } -/* probe scheduler.cpu_on +/** probe scheduler.cpu_on * * Fires when a process is beginning execution on a cpu. * @@ -76,26 +76,6 @@ probe scheduler.tick = kernel.function("scheduler_tick") idle = __is_idle() } - -/* probe scheduler.migrate - * - * Fires whenever a task is moved to a different cpu's runqueue. - * - * Context: - * Unknown (sometimes migration thread, sometimes cpu_to) - * - * Arguments: - * task - the process that is being migrated - * cpu_from - the cpu that is losing the task - * cpu_to - the cpu that is claiming the task - */ -probe scheduler.migrate = kernel.function("pull_task")? { - task = $p - cpu_from = task_cpu($p) /*thread_info renamed to stack since 2.6.22*/ - cpu_to = $this_cpu -} - - /* probe scheduler.balance * * Fires when a cpu attempts to find more work. @@ -107,43 +87,314 @@ probe scheduler.migrate = kernel.function("pull_task")? { probe scheduler.balance = kernel.function("idle_balance")? {} -/* probe scheduler.ctxswitch - * - * Fires when there is a context switch +/** + * probe scheduler.ctxswitch - Fires when there is a context switch. Currently + * systemTap can't access arguments of inline + * functions. So we choose to probe __switch_to instead + * of context_switch() + * @prev_pid: The pid of the process to be switched out + * @next_pid: The pid of the process to be switched in + * @prev_tid: The tid of the process to be switched out + * @next_tid: The tid of the process to be switched in + * @prev_task_name: The name of the process to be switched out + * @next_task_name: The name of the process to be switched in + * @prev_priority: The priority of the process to be switched out + * @next_priority: The priority of the process to be switched in + * @prevtsk_state: the state of the process to be switched out + * @nexttsk_state: the state of the process to be switched in + */ - * Currently systemTap can't access arguments of inline - * functions. So we choose to probe __switch_to instead - * of context_switch() +probe __scheduler.ctxswitch.tp = kernel.trace("sched_switch") +{ + next_pid = $next->tgid + next_tid = $next->pid + next_task = $next + next_task_name = task_execname($next) + nexttsk_state = $next->state + next_priority = $next->prio + prev_priority = $prev->prio + prev_pid = $prev->tgid + prev_tid = $prev->pid + prev_task = $prev + prev_task_name = task_execname($prev) + prevtsk_state = $prev->state +} - * Arguments: - * prev_pid: The pid of the process to be switched out - * next_pid: The pid of the process to be switched in - * prevtsk_state: the state of the process to be switched out - */ -probe scheduler.ctxswitch = +probe __scheduler.ctxswitch.kp = %( arch != "x86_64" && arch != "ia64" %? - kernel.trace("sched_switch") !, kernel.function("__switch_to") + kernel.function("__switch_to") %: - kernel.trace("sched_switch") !, kernel.function("context_switch") + kernel.function("context_switch") %) { %( arch == "powerpc" %? - prev_pid = $prev->pid - next_pid = $new->pid - prev_task = $prev - next_task = $new - prevtsk_state = $prev->state + prev_pid = $prev->tgid + next_pid = $new->tgid + prev_tid = $prev->pid + next_tid = $new->pid + prev_task = $prev + next_task = $new + next_priority = $new->prio + prev_priority = $prev->prio + prev_task_name = task_execname($prev) + next_task_name = task_execname($new) + prevtsk_state = $prev->state + nexttsk_state = $new->state + %: %( arch == "x86_64" || arch == "ia64" %? - prev_pid = $prev->pid - next_pid = $next->pid - prev_task = $prev - next_task = $next - prevtsk_state = $prev->state + prev_pid = $prev->tgid + next_pid = $next->tgid + prev_tid = $prev->pid + next_tid = $next->pid + prev_task = $prev + next_task = $next + next_priority = $next->prio + prev_priority = $prev->prio + prev_task_name = task_execname($prev) + next_task_name = task_execname($next) + prevtsk_state = $prev->state + nexttsk_state = $next->state %: - prev_pid = $prev_p->pid - next_pid = $next_p->pid - prev_task = $prev_p - next_task = $next_p - prevtsk_state = $prev_p->state + prev_pid = $prev_p->tgid + next_pid = $next_p->tgid + prev_tid = $prev_p->pid + next_tid = $next_p->pid + prev_task = $prev_p + next_task = $next_p + next_priority = $next_p->prio + prev_priority = $prev_p->prio + prev_task_name = task_execname($prev_p) + next_task_name = task_execname($next_p) + prevtsk_state = $prev_p->state + nexttsk_state = $next_p->state %) %) } + +probe scheduler.ctxswitch + = __scheduler.ctxswitch.tp !, __scheduler.ctxswitch.kp +{} + + +/** + * probe scheduler.kthread_stop - Fires when a thread created by kthread_create is stopped. + * @thread_pid: pid of the thread being stopped. + * @thread_priority: priority of the thread. + */ +probe __scheduler.kthread_stop.kp = kernel.function("kthread_stop") +{ + thread_pid = $k->tgid + thread_priority = $k->priority +} +probe __scheduler.kthread_stop.tp = kernel.trace("sched_kthread_stop") +{ + thread_pid = $t->tgid + thread_priority = $t->prio +} +probe scheduler.kthread_stop + = __scheduler.kthread_stop.tp !, + __scheduler.kthread_stop.kp +{} + + +/** + * probe scheduler.kthread_stop.return - Fires once the kthread is stopped and gets the return value + * @return_value: return value after stopping the thread. + */ + +probe __scheduler.kthread_stop.return.kp = kernel.function("kthread_stop").return +{ + return_value = $k->exit_code +} +probe __scheduler.kthread_stop.return.tp = kernel.trace("sched_kthread_stop_ret") +{ + return_value = $ret +} + +probe scheduler.kthread_stop.return + = __scheduler.kthread_stop.return.tp !, + __scheduler.kthread_stop.return.kp +{} + +/** + * probe scheduler.wait_task - Fires when waiting on a task to unschedule. + * It waits till the task becomes inactive. + * @task_pid: pid of the task the scheduler is waiting on. + * @task_priority: priority of the task + */ + +probe scheduler.wait_task + = kernel.trace("sched_wait_task") !, + kernel.function("wait_task_inactive") +{ + task_pid = $p->tgid + task_priority = $p->prio +} + +/** + * probe scheduler.wakeup - Fires when a task is woken up + * @task_pid: pid of the task being woken up + * @task_priority: priority of the task being woken up + * @task_cpu: cpu of the task being woken up + * @task_state: state of the task being woken up + * @task_tid: tid of the task being woken up + */ + +probe scheduler.wakeup + = kernel.trace("sched_wakeup") !, + kernel.function("try_to_wake_up") +{ + task = $p + task_pid = $p->tgid + task_tid = $p->pid + task_priority = $p->prio + task_cpu = task_cpu($p) + task_state = task_state($p) +} + +/** + * probe scheduler.wakeup_new - Fires when a newly created task is woken up for the first time + * @task_pid: pid of the new task woken up + * @task_priority: priority of the new task + * @task_tid: tid of the new task woken up + * @task_state: state of the task woken up + * @task_cpu: cpu of the task woken up + */ +probe scheduler.wakeup_new + = kernel.trace("sched_wakeup_new") !, + kernel.function("wake_up_new_task") +{ + task_pid = $p->tgid + task_priority = $p->prio + task_cpu = task_cpu($p) + task_state = task_state($p) + task = $p + task_tid = $p->pid +} + +/** + * probe scheduler.migrate - Traces the migration of the tasks across cpus by the scheduler. + * @task: the process that is being migrated. + * @pid: pid of the task being migrated. + * @priority: priority of the task being migrated. + * @cpu_from: the original cpu + * @cpu_to: the destination cpu + */ +probe __scheduler.migrate.kp1 = kernel.function("pull_task") +{ + cpu_to = $this_cpu +} +probe __scheduler.migrate.kp = kernel.function("set_task_cpu") +{ + cpu_to = $new_cpu +} +probe __scheduler.migrate.tp = kernel.trace("sched_migrate_task") +{ + cpu_to = $dest_cpu +} +probe scheduler.migrate + = __scheduler.migrate.tp !, + __scheduler.migrate.kp !, + __scheduler.migrate.kp1 +{ + task = $p + pid = $p->tgid + priority = $p->prio + cpu_from = task_cpu($p) +} +/** + * probe scheduler.process_free - Traces the process of freeing up of a process + * @pid: PID of the process getting freed + * @priority: priority of the process getting freed + */ +probe __scheduler.process_free.kp = kernel.function("delayed_put_task_struct") +{ + pid = $tsk->tgid + priority = $tsk->prio +} +probe __scheduler.process_free.tp = kernel.trace("sched_process_free") +{ + pid = $p->tgid + priority = $p->prio +} +probe scheduler.process_free + = __scheduler.process_free.tp !, + __scheduler.process_free.kp +{} + +/** + * probe scheduler.process_exit - Fires when a process exits + * @pid: pid of the process exiting + * @priority: priority of the process exiting + */ +probe __scheduler.process_exit.kp = kernel.function("do_exit") +{ + pid = $tsk->tgid + priority = $tsk->priority +} +probe __scheduler.process_exit.tp = kernel.trace("sched_process_exit") +{ + pid = $p->tgid + priority = $p->prio +} + +probe scheduler.process_exit + = __scheduler.process_exit.tp !, + __scheduler.process_exit.kp +{} + +/** + * probe scheduler.process_wait - Fires when scheduler waits on a process + * @pid: PID of the process scheduler is waiting on + */ +probe __scheduler.process_wait.kp = kernel.function("do_wait") +{ + pid = $wo->wo_pid +} +probe __scheduler.process_wait.tp = kernel.trace("sched_process_wait") +{ + pid = $pid +} +probe scheduler.process_wait + = __scheduler.process_wait.tp !, + __scheduler.process_wait.kp +{} + +/** + * probe scheduler.process_fork - Probes the tracepoint for forking a process + * @parent_pid: PID of the parent process + * @child_pid: PID of the child process + */ +probe __scheduler.process_fork.kp = kernel.function("do_fork") +{ + parent_pid = $current->tgid + child_pid = $p->tgid +} +probe __scheduler.process_fork.tp = kernel.trace("sched_process_fork") +{ + parent_pid = $parent->tgid + child_pid = $child->tgid +} + +probe scheduler.process_fork + = __scheduler.process_fork.tp !, + __scheduler.process_fork.kp +{} +/** + * probe scheduler.signal_send - Probes the tracepoint for sending a signal + * @pid: pid of the process sending signal + * @signal_number: signal number + */ +probe __scheduler.signal_send.kp = kernel.function("__send_signal") +{ + pid = $t->tgid +} +probe __scheduler.signal_send.tp = kernel.trace("sched_signal_send") +{ + pid = $p->tgid +} +probe scheduler.signal_send + = __scheduler.signal_send.tp !, + __scheduler.signal_send.kp +{ + signal_number = $sig +} |