From: Felix Lu Date: Fri, 18 Mar 2016 18:11:05 +0000 (-0400) Subject: Add some monitor mode improvements. X-Git-Tag: release-3.0~40 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=32bcf988a7db89220f2472d40d33b07b5c2e6adc;p=systemtap.git Add some monitor mode improvements. Added an option to pause and resume the script while running to allow the user to review the output. Previously, a synthetic probe was being displayed in the probe list, this is now removed. * elaborate.cxx: - monitor_mode_write: skip generating probe point condition for synthetic probes. Add command to resume and pause all probes. - semantic_pass: call monitor_mode_{read, write} in init * staprun/monitor.c: Bind keys for pause and resume. --- diff --git a/elaborate.cxx b/elaborate.cxx index f72d937f8..df45f2264 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2017,84 +2017,6 @@ void add_global_var_display (systemtap_session& s) } } -static void create_monitor_function(systemtap_session& s) -{ - functiondecl* fd = new functiondecl; - fd->synthetic = true; - fd->unmangled_name = fd->name = "__private___monitor_data_function_probes"; - fd->type = pe_string; - - vardecl* v = new vardecl; - v->type = pe_long; - v->unmangled_name = v->name = "index"; - fd->formal_args.push_back(v); - - embeddedcode* ec = new embeddedcode; - string code; - code = "/* unprivileged */ /* pure */" - "const struct stap_probe *const p = &stap_probes[STAP_ARG_index];\n" - "if (likely (probe_timing(STAP_ARG_index))) {\n" - "struct stat_data *stats = _stp_stat_get (probe_timing(STAP_ARG_index), 0);\n" - "if (stats->count) {\n" - "int64_t avg = _stp_div64 (NULL, stats->sum, stats->count);\n" - "snprintf(_monitor_buf, STAP_MONITOR_READ,\n" - "\"\\\"index\\\": %zu, \\\"state\\\": \\\"%s\\\", \\\"hits\\\": %lld, " - "\\\"min\\\": %lld, \\\"avg\\\": %lld, \\\"max\\\": %lld, \",\n" - "p->index, p->cond_enabled ? \"on\" : \"off\", (long long) stats->count,\n" - "(long long) stats->min, (long long) avg, (long long) stats->max);\n" - "} else {\n" - "snprintf(_monitor_buf, STAP_MONITOR_READ,\n" - "\"\\\"index\\\": %zu, \\\"state\\\": \\\"%s\\\", \\\"hits\\\": %d, " - "\\\"min\\\": %d, \\\"avg\\\": %d, \\\"max\\\": %d, \",\n" - "p->index, p->cond_enabled ? \"on\" : \"off\", 0, 0, 0, 0);}}\n" - "STAP_RETURN(_monitor_buf);\n"; - ec->code = code; - fd->body = ec; - - s.functions[fd->name] = fd; -} - -static void monitor_mode_init(systemtap_session& s) -{ - if (!s.monitor) return; - - vardecl* v = new vardecl; - v->unmangled_name = v->name = "__global___monitor_module_start"; - v->set_arity(0, 0); - v->type = pe_long; - v->synthetic = true; - s.globals.push_back(v); - - stringstream code; - code << "probe begin {" << endl; - code << "__monitor_module_start = jiffies()" << endl; - code << "}" << endl; - - probe* p = parse_synthetic_probe(s, code, 0); - if (!p) - throw SEMANTIC_ERROR (_("can't create begin probe"), 0); - - vector dps; - derive_probes (s, p, dps); - - derived_probe* dp = dps[0]; - s.probes.insert (s.probes.begin(), dp); - dp->join_group (s); - - // Repopulate symbol info - symresolution_info sym (s); - sym.current_function = 0; - sym.current_probe = dp; - dp->body->visit (&sym); - - embeddedcode* ec = new embeddedcode; - ec->code = "#define STAP_MONITOR_READ 8192\n" - "static char _monitor_buf[STAP_MONITOR_READ];"; - s.embeds.push_back(ec); - - create_monitor_function(s); -} - static void monitor_mode_read(systemtap_session& s) { if (!s.monitor) return; @@ -2161,7 +2083,7 @@ static void monitor_mode_read(systemtap_session& s) s.probes.push_back (dp); dp->join_group (s); - // Repopulate symbol and type info + // Repopulate symbol info symresolution_info sym (s); sym.current_function = 0; sym.current_probe = dp; @@ -2173,7 +2095,7 @@ static void monitor_mode_write(systemtap_session& s) if (!s.monitor) return; for (vector::const_iterator it = s.probes.begin(); - it != s.probes.end(); ++it) + it != s.probes.end()-1; ++it) // Skip monitor read probe { vardecl* v = new vardecl; v->unmangled_name = v->name = "__global___monitor_" + lex_cast(it-s.probes.begin()) + "_enabled"; @@ -2212,7 +2134,7 @@ static void monitor_mode_write(systemtap_session& s) code << " if ($value == \"exit\") { exit()"; - code << " } else if ($value == \"reset\") {"; + code << " } else if ($value == \"clear\") {"; for (vector::const_iterator it = s.globals.begin(); it != s.globals.end(); ++it) { @@ -2240,10 +2162,24 @@ static void monitor_mode_write(systemtap_session& s) code << "delete " << v->name << endl; } } - code << "}" << endl; + code << "} else if ($value == \"resume\") {" << endl; for (vector::const_iterator it = s.probes.begin(); - it != s.probes.end(); ++it) + it != s.probes.end()-1; ++it) + { + code << " __monitor_" << it-s.probes.begin() << "_enabled" << " = 1" << endl; + } + + code << "} else if ($value == \"pause\") {" << endl; + for (vector::const_iterator it = s.probes.begin(); + it != s.probes.end()-1; ++it) + { + code << " __monitor_" << it-s.probes.begin() << "_enabled" << " = 0" << endl; + } + code << "}"; + + for (vector::const_iterator it = s.probes.begin(); + it != s.probes.end()-1; ++it) { code << " if ($value == \"" << it-s.probes.begin() << "\")" << " __monitor_" << it-s.probes.begin() << "_enabled" << " ^= 1" << endl; @@ -2262,7 +2198,87 @@ static void monitor_mode_write(systemtap_session& s) s.probes.push_back (dp); dp->join_group (s); - // Repopulate symbol and type info + // Repopulate symbol info + symresolution_info sym (s); + sym.current_function = 0; + sym.current_probe = dp; + dp->body->visit (&sym); +} + +static void create_monitor_function(systemtap_session& s) +{ + functiondecl* fd = new functiondecl; + fd->synthetic = true; + fd->unmangled_name = fd->name = "__private___monitor_data_function_probes"; + fd->type = pe_string; + + vardecl* v = new vardecl; + v->type = pe_long; + v->unmangled_name = v->name = "index"; + fd->formal_args.push_back(v); + + embeddedcode* ec = new embeddedcode; + string code; + code = "/* unprivileged */ /* pure */" + "const struct stap_probe *const p = &stap_probes[STAP_ARG_index];\n" + "if (likely (probe_timing(STAP_ARG_index))) {\n" + "struct stat_data *stats = _stp_stat_get (probe_timing(STAP_ARG_index), 0);\n" + "if (stats->count) {\n" + "int64_t avg = _stp_div64 (NULL, stats->sum, stats->count);\n" + "snprintf(_monitor_buf, STAP_MONITOR_READ,\n" + "\"\\\"index\\\": %zu, \\\"state\\\": \\\"%s\\\", \\\"hits\\\": %lld, " + "\\\"min\\\": %lld, \\\"avg\\\": %lld, \\\"max\\\": %lld, \",\n" + "p->index, p->cond_enabled ? \"on\" : \"off\", (long long) stats->count,\n" + "(long long) stats->min, (long long) avg, (long long) stats->max);\n" + "} else {\n" + "snprintf(_monitor_buf, STAP_MONITOR_READ,\n" + "\"\\\"index\\\": %zu, \\\"state\\\": \\\"%s\\\", \\\"hits\\\": %d, " + "\\\"min\\\": %d, \\\"avg\\\": %d, \\\"max\\\": %d, \",\n" + "p->index, p->cond_enabled ? \"on\" : \"off\", 0, 0, 0, 0);}}\n" + "STAP_RETURN(_monitor_buf);\n"; + ec->code = code; + fd->body = ec; + + s.functions[fd->name] = fd; +} + +static void monitor_mode_init(systemtap_session& s) +{ + if (!s.monitor) return; + + vardecl* v = new vardecl; + v->unmangled_name = v->name = "__global___monitor_module_start"; + v->set_arity(0, 0); + v->type = pe_long; + v->synthetic = true; + s.globals.push_back(v); + + embeddedcode* ec = new embeddedcode; + ec->code = "#define STAP_MONITOR_READ 8192\n" + "static char _monitor_buf[STAP_MONITOR_READ];"; + s.embeds.push_back(ec); + + create_monitor_function(s); + monitor_mode_read(s); + monitor_mode_write(s); + + stringstream code; + code << "probe begin {" << endl; + code << "__monitor_module_start = jiffies()" << endl; + code << "}" << endl; + + probe* p = parse_synthetic_probe(s, code, 0); + if (!p) + throw SEMANTIC_ERROR (_("can't create begin probe"), 0); + + vector dps; + derive_probes (s, p, dps); + + derived_probe* dp = dps[0]; + s.probes.push_back (dp); + dp->join_group (s); + + // Repopulate symbol info symresolution_info sym (s); sym.current_function = 0; sym.current_probe = dp; @@ -2285,8 +2301,6 @@ semantic_pass (systemtap_session& s) if (rc == 0) rc = semantic_pass_symbols (s); if (rc == 0) monitor_mode_init (s); - if (rc == 0) monitor_mode_read (s); - if (rc == 0) monitor_mode_write (s); if (rc == 0) rc = semantic_pass_conditions (s); if (rc == 0) rc = semantic_pass_optimize1 (s); if (rc == 0) rc = semantic_pass_types (s); diff --git a/man/stap.1.in b/man/stap.1.in index 2fb326196..4b7f8d881 100644 --- a/man/stap.1.in +++ b/man/stap.1.in @@ -791,7 +791,7 @@ refresh rate in seconds of the status window. The module can also be controlled of commands using the following keys: .RS .TP -.BI r +.BI c resets all global variables to their initial values or zeroes them if they did not have an initial value. .TP @@ -799,7 +799,14 @@ did not have an initial value. rotates the attribute used to sort the list of probes. .TP .BI t -brings up a prompt to allow toggling(on/off) of probes by index. +brings up a prompt to allow toggling(on/off) of probes by index. Probe points +are still affected by their conditions. +.TP +.BI r +resumes the script by toggling on all probes. +.TP +.BI p +pauses the script by toggling off all probes. .TP .BI navigation-keys the j/k/ArrowDown/ArrowUp keys can be used to scroll through the probe diff --git a/staprun/monitor.c b/staprun/monitor.c index 9612797c7..e9d94d6d7 100644 --- a/staprun/monitor.c +++ b/staprun/monitor.c @@ -255,13 +255,32 @@ void monitor_render(void) max_rows = monitor_y; max_cols = MIN(MAX_COLS, monitor_x); - if (monitor_state != help) + if (monitor_state == help) { + /* Render help page */ + rendered = 0; + wclear(monitor_status); + wprintw(monitor_status, "MONITOR MODE COMMANDS\n"); + wprintw(monitor_status, "h - Display help page.\n"); + wprintw(monitor_status, "c - Reset all global variables to initial state, zeroes if unset.\n"); + wprintw(monitor_status, "s - Rotate sort columns for probes.\n"); + wprintw(monitor_status, "t - Open a prompt to enter the index of a probe to toggle.\n"); + wprintw(monitor_status, "r - Resume script by toggling on all probes.\n"); + wprintw(monitor_status, "p - Pause script by toggling off all probes.\n"); + wprintw(monitor_status, "j/DownArrow - Scroll down the probe list.\n"); + wprintw(monitor_status, "k/UpArrow - Scroll up the probe list.\n"); + wprintw(monitor_status, "d/PageDown - Scroll down the output by one page.\n"); + wprintw(monitor_status, "u/PageUp - Scroll up the probe list by one page.\n"); + mvwprintw(monitor_status, max_rows-1, 0, "press q to go back\n"); + wrefresh(monitor_status); + } + else + { + /* Render monitor mode statistics */ if (sprintf_chk(path, "/proc/systemtap/%s/monitor_status", modname)) return; monitor_fp = fopen(path, "r"); - /* Render monitor mode statistics */ if (monitor_fp) { char json[MAX_DATA]; @@ -401,21 +420,6 @@ void monitor_render(void) /* Free allocated memory */ json_object_put(jso); } - } else { - /* Render help page */ - rendered = 0; - wclear(monitor_status); - wprintw(monitor_status, "MONITOR MODE COMMANDS\n"); - wprintw(monitor_status, "h - Display help page.\n"); - wprintw(monitor_status, "r - Reset global variables to initial state, zeroes if unset.\n"); - wprintw(monitor_status, "s - Rotate sort columns for probes.\n"); - wprintw(monitor_status, "t - Open prompt to enter a probe index to toggle.\n"); - wprintw(monitor_status, "j/DownArrow - Scroll down the probe list.\n"); - wprintw(monitor_status, "k/UpArrow - Scroll up the probe list.\n"); - wprintw(monitor_status, "d/PageDown - Scroll down the output by one page.\n"); - wprintw(monitor_status, "u/PageUp - Scroll up the probe list by one page.\n"); - mvwprintw(monitor_status, max_rows-1, 0, "press q to go back\n"); - wrefresh(monitor_status); } } @@ -459,8 +463,14 @@ void monitor_input(void) if (comp_fn_index == COMP_FNS) comp_fn_index = 0; break; + case 'c': + write_command("clear", 5); + break; case 'r': - write_command("reset", 5); + write_command("resume", 6); + break; + case 'p': + write_command("pause", 5); break; case 't': monitor_state = insert;