static int llcallchain_bufinfo_show(dyn_llcallchain_t *dyn, track_proc_t *proc, track_lwp_t *lwp) { char content[WIN_LINECHAR_MAX]; lat_line_t *lat_buf, *line; win_reg_t *reg; int lwpid = 0, nlines, lat; /* * Display the caption of data table: * "ADDR SIZE ACCESS% LAT(ns) DESC" */ reg = &dyn->buf_caption; reg_erase(reg); (void) snprintf(content, sizeof (content), "%16s%8s%11s%11s%34s", CAPTION_ADDR, CAPTION_SIZE, CAPTION_BUFHIT, CAPTION_AVGLAT, CAPTION_DESC); reg_line_write(&dyn->buf_caption, 1, ALIGN_LEFT, content); dump_write("%s\n", content); reg_refresh_nout(reg); /* * Get the stat of buffer. */ reg = &dyn->buf_data; reg_erase(reg); if (lwp != NULL) { lwpid = lwp->id; } if ((lat_buf = win_lat_buf_create(proc, lwpid, &nlines)) == NULL) { return (-1); } /* * Fill in the memory access information. */ win_lat_buf_fill(lat_buf, nlines, proc, lwp, &lat); /* * Check if the linear address is located in a buffer in * process address space. */ if ((line = bsearch((void *)(dyn->addr), lat_buf, nlines, sizeof (lat_line_t), bufaddr_cmp)) != NULL) { win_lat_str_build(content, WIN_LINECHAR_MAX, 0, line); reg_line_write(reg, 0, ALIGN_LEFT, content); dump_write("%s\n", content); } reg_refresh_nout(reg); free(lat_buf); return (0); }
static boolean_t latnode_data_show(track_proc_t *proc, dyn_latnode_t *dyn, map_entry_t *entry, boolean_t *note_out) { win_reg_t *reg; track_lwp_t *lwp = NULL; char content[WIN_LINECHAR_MAX], intval_buf[16], size_str[32]; *note_out = B_FALSE; if ((dyn->lwpid != 0) && (lwp = proc_lwp_find(proc, dyn->lwpid)) == NULL) { win_warn_msg(WARN_INVALID_LWPID); win_note_show(NOTE_INVALID_LWPID); *note_out = B_TRUE; return (B_FALSE); } reg = &dyn->msg; reg_erase(reg); disp_intval(intval_buf, 16); (void) snprintf(content, sizeof (content), "Break down of memory area for physical memory on node (interval: %s)", intval_buf); reg_line_write(reg, 1, ALIGN_LEFT, content); dump_write("\n*** %s\n", content); reg_refresh_nout(reg); reg = &dyn->note; reg_erase(reg); win_size2str(dyn->size, size_str, sizeof (size_str)); if (lwp != NULL) { (void) snprintf(content, sizeof (content), "Memory area(%"PRIX64", %s), thread(%d)", dyn->addr, size_str, lwp->id); } else { (void) snprintf(content, sizeof (content), "Memory area(%"PRIX64", %s), process(%d)", dyn->addr, size_str, proc->pid); } reg_line_write(reg, 1, ALIGN_LEFT, content); dump_write("\n*** %s\n", content); reg_refresh_nout(reg); latnode_data_get(proc, lwp, dyn); if (lwp != NULL) { lwp_refcount_dec(lwp); } return (B_TRUE); }
static int chainlist_show(sym_chainlist_t *chainlist, win_reg_t *reg) { sym_callchain_t *chain; int nentry, nchain; int i, j = 0, k, nlines; char content[WIN_LINECHAR_MAX]; callchain_line_t *buf, *line; sym_callchain_resort(chainlist); nentry = sym_chainlist_nentry(chainlist, &nchain); reg_erase(reg); if (nentry == 0) { snprintf(content, WIN_LINECHAR_MAX, "<- Detecting call-chain ... -> "); reg_line_write(reg, 0, ALIGN_LEFT, content); dump_write("%s\n", content); reg_refresh_nout(reg); return (0); } nlines = nentry + 2 * nchain; if ((buf = zalloc(nlines * sizeof (callchain_line_t))) == NULL) { return (-1); } for (i = 0; i < nchain; i++) { if ((chain = sym_callchain_detach(chainlist)) == NULL) { break; } line = &buf[j++]; snprintf(line->content, WIN_LINECHAR_MAX, "<- call-chain %d: ->", i + 1); for (k = 0; k < chain->nentry; k++) { line = &buf[j++]; strncpy(line->content, chain->entry_arr[k].name, WIN_LINECHAR_MAX); line->content[WIN_LINECHAR_MAX - 1] = 0; } line = &buf[j++]; strcpy(line->content, ""); sym_callchain_free(chain); } if (reg->buf != NULL) { free(reg->buf); } reg->buf = (void *)buf; reg->nlines_total = nlines - 1; reg_scroll_show(reg, (void *)(reg->buf), nlines - 1, callchain_str_build); reg_refresh_nout(reg); sym_chainlist_free(chainlist); return (0); }
static void nodedetail_line_show(win_reg_t *reg, char *title, char *value, int line) { char s1[256]; snprintf(s1, sizeof (s1), "%-20s%15s", title, value); reg_line_write(reg, line, ALIGN_LEFT, s1); dump_write("%s\n", s1); }
/* * Lowlight the selected line. */ static void reg_idx_lowlight(win_reg_t *r, int idx) { scroll_line_t *scroll = &r->scroll; char line[WIN_LINECHAR_MAX]; if (r->hdl != NULL) { r->line_get(r, idx, line, WIN_LINECHAR_MAX); reg_line_write(r, idx - scroll->page_start, ALIGN_LEFT, line); } }
static int llcallchain_list_show(dyn_llcallchain_t *dyn, track_proc_t *proc, track_lwp_t *lwp) { perf_llrecgrp_t *llrec_grp; char content[WIN_LINECHAR_MAX]; os_perf_llrec_t *rec_arr; sym_chainlist_t chainlist; win_reg_t *reg; int i; reg = &dyn->chain_caption; reg_erase(reg); snprintf(content, WIN_LINECHAR_MAX, "Call-chain list:"); reg_line_write(reg, 1, ALIGN_LEFT, content); dump_write("%s\n", content); reg_refresh_nout(reg); reg = &dyn->pad; reg_erase(reg); dump_write("\n"); reg_refresh_nout(reg); if (lwp != NULL) { llrec_grp = &lwp->llrec_grp; } else { llrec_grp = &proc->llrec_grp; } if (sym_load(proc, SYM_TYPE_FUNC) != 0) { debug_print(NULL, 2, "Failed to load the process symbol " "(pid = %d)\n", proc->pid); return (-1); } memset(&chainlist, 0, sizeof (sym_chainlist_t)); rec_arr = llrec_grp->rec_arr; for (i = 0; i < llrec_grp->nrec_cur; i++) { if ((rec_arr[i].addr < dyn->addr) || (rec_arr[i].addr >= dyn->addr + dyn->size)) { continue; } sym_callchain_add(&proc->sym, rec_arr[i].callchain.ips, rec_arr[i].callchain.ip_num, &chainlist); } chainlist_show(&chainlist, &dyn->chain_data); return (0); }
/* * Show the 'scrolling reg'. */ void reg_scroll_show(win_reg_t *r, void *lines, int nreqs, void (*str_build_func)(char *, int, int, void *)) { int highlight, i, start, end; char content[WIN_LINECHAR_MAX]; highlight = r->scroll.highlight; if (highlight != -1) { if (highlight >= r->nlines_total) { highlight = r->nlines_total - 1; } if (highlight >= r->scroll.page_start) { if ((i = ((highlight - r->scroll.page_start) / r->nlines_scr)) != 0) { r->scroll.page_start += r->nlines_scr * i; } } else { r->scroll.page_start = (highlight / r->nlines_scr) * r->nlines_scr; } start = r->scroll.page_start; i = MIN(nreqs, r->nlines_scr); if ((end = start + i) > r->nlines_total) { end = r->nlines_total; } } else { highlight = 0; start = 0; end = MIN(nreqs, r->nlines_scr); } for (i = start; i < end; i++) { str_build_func(content, sizeof (content), i, lines); dump_write("%s\n", content); if (i != highlight) { reg_line_write(r, i - r->scroll.page_start, ALIGN_LEFT, content); } } if ((highlight >= start) && (highlight < end)) { str_build_func(content, sizeof (content), highlight, lines); reg_highlight_write(r, highlight - r->scroll.page_start, ALIGN_LEFT, content); r->scroll.highlight = highlight; } }
/* * Display the hidden lines on screen. */ static void reg_hidden_show(win_reg_t *r, int idx_start) { int i, idx_end; char line[WIN_LINECHAR_MAX]; if (r->hdl == NULL) { return; } if ((idx_end = idx_start + r->nlines_scr) > r->nlines_total) { idx_end = r->nlines_total; } reg_erase(r); for (i = idx_start; i < idx_end; i++) { r->line_get(r, i, line, WIN_LINECHAR_MAX); reg_line_write(r, i - idx_start, ALIGN_LEFT, line); } }
static int latnode_data_get(track_proc_t *proc, track_lwp_t *lwp, dyn_latnode_t *dyn) { lat_line_t *buf; char content[WIN_LINECHAR_MAX]; int nlines, lwpid = 0, lat = 0; reg_erase(&dyn->caption); reg_refresh_nout(&dyn->caption); reg_erase(&dyn->data); reg_refresh_nout(&dyn->data); if (lwp != NULL) { lwpid = lwp->id; } if ((buf = latnode_buf_create(proc, lwpid, dyn->addr, dyn->size, &nlines)) == NULL) { reg_line_write(&dyn->caption, 1, ALIGN_LEFT, "Failed to get the process NUMA mapping!"); reg_refresh_nout(&dyn->caption); return (-1); } win_lat_buf_fill(buf, nlines, proc, lwp, &lat); /* * Sort by the number of buffer accessing. */ qsort(buf, nlines, sizeof (lat_line_t), win_lat_cmp); /* * Display the caption of data table: * "ADDR SIZE NODE ACCESS% LAT(ns) DESC" */ (void) snprintf(content, sizeof (content), "%16s%8s%8s%11s%11s", CAPTION_ADDR, CAPTION_SIZE, CAPTION_NID, CAPTION_BUFHIT, CAPTION_AVGLAT); reg_line_write(&dyn->caption, 1, ALIGN_LEFT, content); reg_refresh_nout(&dyn->caption); /* * Save data of buffer statistics in scrolling buffer. */ dyn->data.nlines_total = nlines; if (dyn->data.buf != NULL) { free(dyn->data.buf); } /* * Display the buffer with statistics in scrolling buffer */ dyn->data.buf = (void *)buf; reg_scroll_show(&dyn->data, (void *)(dyn->data.buf), nlines, win_lat_str_build); reg_refresh_nout(&dyn->data); return (0); }
static void llcallchain_data_show(dyn_win_t *win, boolean_t *note_out) { dyn_llcallchain_t *dyn; pid_t pid; int lwpid; uint64_t size; track_proc_t *proc; track_lwp_t *lwp = NULL; win_reg_t *reg; char content[WIN_LINECHAR_MAX], intval_buf[16]; char size_str[32]; dyn = (dyn_llcallchain_t *)(win->dyn); pid = dyn->pid; lwpid = dyn->lwpid; size = dyn->size; *note_out = B_FALSE; if ((proc = proc_find(pid)) == NULL) { win_warn_msg(WARN_INVALID_PID); win_note_show(NOTE_INVALID_PID); *note_out = B_TRUE; return; } if ((lwpid > 0) && ((lwp = proc_lwp_find(proc, lwpid)) == NULL)) { proc_refcount_dec(proc); win_warn_msg(WARN_INVALID_LWPID); win_note_show(NOTE_INVALID_LWPID); *note_out = B_TRUE; return; } reg = &dyn->msg; reg_erase(reg); disp_intval(intval_buf, 16); win_size2str(size, size_str, sizeof (size_str)); if (lwp == NULL) { (void) snprintf(content, WIN_LINECHAR_MAX, "Call-chain when process accesses the memory area (pid: %d)" " (interval: %s)", pid, intval_buf); } else { (void) snprintf(content, WIN_LINECHAR_MAX, "Call-chain when thread accesses the memory area (lwpid: %d)" " (interval: %s)", lwpid, intval_buf); } dump_write("\n*** %s\n", content); reg_line_write(reg, 1, ALIGN_LEFT, content); reg_refresh_nout(reg); llcallchain_bufinfo_show(dyn, proc, lwp); llcallchain_list_show(dyn, proc, lwp); if (lwp != NULL) { lwp_refcount_dec(lwp); } proc_refcount_dec(proc); }