2 * Copyright (C) 2011-2012 Julien Desfossez
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <semaphore.h>
27 #include <state/StateSystem.hpp>
28 #include <state/statevalue/StateValue.hpp>
29 #include <state/statevalue/IntegerStateValue.hpp>
30 #include <state/statevalue/StringStateValue.hpp>
31 #include <state/statevalue/NullStateValue.hpp>
32 #include <state/statevalue/QuarkStateValue.hpp>
34 #define __STDC_FORMAT_MACROS
37 #include "cursesdisplay.h"
38 #include "lttngtoptypes.h"
39 #include "iostreamtop.h"
42 #define DEFAULT_DELAY 15
43 #define MAX_LINE_LENGTH 50
44 #define MAX_LOG_LINES 4
46 using namespace State
;
48 enum view_list current_view
;
49 enum view_list previous_view
;
51 /* to prevent concurrent updates of the different windows */
52 sem_t update_display_sem
;
55 WINDOW
*footer
, *header
, *center
, *status
;
56 WINDOW
*pref_panel_window
= NULL
;
57 PANEL
*pref_panel
, *main_panel
;
59 int pref_panel_visible
= 0;
60 int pref_line_selected
= 0;
61 int pref_current_sort
= 0;
63 Quark selected_process
;
66 int selected_line
= 0; /* select bar position */
67 int selected_in_list
= 0; /* selection relative to the whole list */
68 int list_offset
= 0; /* first index in the list to display (scroll) */
70 char log_lines
[MAX_LINE_LENGTH
* MAX_LOG_LINES
+ MAX_LOG_LINES
];
72 int max_elements
= 80;
74 int toggle_threads
= 1;
75 int toggle_pause
= -1;
78 GPtrArray
*selected_processes
;
80 pthread_t keyboard_thread
;
82 struct header_view cputopview
[4];
83 struct header_view iostreamtopview
[3];
84 struct header_view fileview
[3];
86 unsigned long i_start
= 0;
87 unsigned long i_end
= 0;
89 std::string sort_perf_key
;
99 static void handle_sigterm(int signal
)
108 halfdelay(DEFAULT_DELAY
);
110 intrflush(stdscr
, false);
111 keypad(stdscr
, true);
116 init_pair(1, COLOR_RED
, COLOR_BLACK
); /* - */
117 init_pair(2, COLOR_GREEN
, COLOR_BLACK
); /* + */
118 init_pair(3, COLOR_BLACK
, COLOR_WHITE
); /* keys */
119 init_pair(4, COLOR_WHITE
, COLOR_GREEN
); /* keys activated */
120 init_pair(5, COLOR_WHITE
, COLOR_BLUE
); /* select line */
121 init_pair(6, COLOR_WHITE
, COLOR_GREEN
); /* selected process */
123 termtype
= getenv("TERM");
124 if (!strcmp(termtype
, "xterm") || !strcmp(termtype
, "xterm-color") ||
125 !strcmp(termtype
, "vt220")) {
126 define_key("\033[H", KEY_HOME
);
127 define_key("\033[F", KEY_END
);
128 define_key("\033OP", KEY_F(1));
129 define_key("\033OQ", KEY_F(2));
130 define_key("\033OR", KEY_F(3));
131 define_key("\033OS", KEY_F(4));
132 define_key("\0330U", KEY_F(6));
133 define_key("\033[11~", KEY_F(1));
134 define_key("\033[12~", KEY_F(2));
135 define_key("\033[13~", KEY_F(3));
136 define_key("\033[14~", KEY_F(4));
137 define_key("\033[16~", KEY_F(6));
138 define_key("\033[17;2~", KEY_F(18));
140 signal(SIGTERM
, handle_sigterm
);
141 mousemask(BUTTON1_CLICKED
, NULL
);
145 WINDOW
*create_window(int height
, int width
, int startx
, int starty
)
148 win
= newwin(height
, width
, startx
, starty
);
154 WINDOW
*create_window_no_border(int height
, int width
, int startx
, int starty
)
157 win
= newwin(height
, width
, startx
, starty
);
162 void print_digit(WINDOW
*win
, int digit
)
165 wattron(win
, COLOR_PAIR(1));
166 wprintw(win
, "%d", digit
);
167 wattroff(win
, COLOR_PAIR(1));
168 } else if (digit
> 0) {
169 wattron(win
, COLOR_PAIR(2));
170 wprintw(win
, "+%d", digit
);
171 wattroff(win
, COLOR_PAIR(2));
177 void print_digits(WINDOW
*win
, int first
, int second
)
180 print_digit(win
, first
);
182 print_digit(win
, second
);
186 void print_headers(int line
, const char desc
[], int value
, int first
, int second
)
188 wattron(header
, A_BOLD
);
189 mvwprintw(header
, line
, 4, "%s", desc
);
190 wattroff(header
, A_BOLD
);
191 mvwprintw(header
, line
, 16, "%d", value
);
192 wmove(header
, line
, 24);
193 print_digits(header
, first
, second
);
194 wmove(header
, line
, 40);
197 void set_window_title(WINDOW
*win
, const char title
[])
199 wattron(win
, A_BOLD
);
200 mvwprintw(win
, 0, 1, title
);
201 wattroff(win
, A_BOLD
);
204 void print_log(const char str
[])
207 int current_line
= 1;
208 int current_char
= 1;
210 /* rotate the line buffer */
211 if (nb_log_lines
>= MAX_LOG_LINES
) {
212 tmp
= strndup(log_lines
, MAX_LINE_LENGTH
* MAX_LOG_LINES
+ MAX_LOG_LINES
);
213 tmp2
= strchr(tmp
, '\n');
214 memset(log_lines
, '\0', strlen(log_lines
));
215 strncat(log_lines
, tmp2
+ 1, strlen(tmp2
) - 1);
216 log_lines
[strlen(log_lines
)] = '\n';
217 log_lines
[strlen(log_lines
)] = '\0';
222 strncat(log_lines
, str
, MAX_LINE_LENGTH
- 1);
224 if (nb_log_lines
< MAX_LOG_LINES
)
225 log_lines
[strlen(log_lines
)] = '\n';
226 log_lines
[strlen(log_lines
)] = '\0';
230 set_window_title(status
, "Status");
231 for (i
= 0; i
< strlen(log_lines
); i
++) {
232 if (log_lines
[i
] == '\n') {
233 wmove(status
, ++current_line
, 1);
236 mvwprintw(status
, current_line
, current_char
++, "%c",
243 int process_selected(Quark proc
)
246 get_current_attribute_value_int(&proc
, "selected", selected
);
250 void update_selected_processes()
252 Quark selected
= state_system
->getQuark(selected_process
, "selected");
253 if (process_selected(selected_process
)) {
254 state_system
->updateCurrentState(selected
, 0);
255 print_log("Process removed");
257 state_system
->updateCurrentState(selected
, 1);
258 print_log("Process added");
262 void print_key(WINDOW
*win
, const char key
[], const char desc
[], int toggle
)
269 wattron(win
, COLOR_PAIR(pair
));
270 wprintw(footer
, "%s", key
);
271 wattroff(win
, COLOR_PAIR(pair
));
272 wprintw(footer
, ":%s", desc
);
277 sem_wait(&update_display_sem
);
280 print_key(footer
, "F2", "CPUtop ", current_view
== cpu
);
281 print_key(footer
, "F3", "PerfTop ", current_view
== perf
);
282 print_key(footer
, "F4", "IOTop ", current_view
== iostream
);
283 print_key(footer
, "Enter", "Details ", current_view
== process_details
);
284 print_key(footer
, "Space", "Highlight ", 0);
285 print_key(footer
, "q", "Quit ", 0);
286 print_key(footer
, "r", "Pref ", 0);
287 print_key(footer
, "t", "Threads ", toggle_threads
);
288 print_key(footer
, "p", "Pause ", toggle_pause
);
291 sem_post(&update_display_sem
);
298 set_window_title(header
, "Statistics for interval [gathering data...[");
299 wattron(header
, A_BOLD
);
300 mvwprintw(header
, 1, 4, "CPUs");
301 mvwprintw(header
, 2, 4, "Threads");
302 mvwprintw(header
, 3, 4, "FDs");
303 wattroff(header
, A_BOLD
);
307 struct tm
format_timestamp(uint64_t timestamp
)
310 uint64_t ts_sec
= 0, ts_nsec
;
314 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
315 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
317 time_s
= (time_t) ts_sec
;
319 localtime_r(&time_s
, &tm
);
324 static void scale_unit(uint64_t bytes
, char *ret
)
326 if (bytes
>= 1000000000)
327 sprintf(ret
, "%" PRIu64
"G", bytes
/1000000000);
328 if (bytes
>= 1000000)
329 sprintf(ret
, "%" PRIu64
"M", bytes
/1000000);
330 else if (bytes
>= 1000)
331 sprintf(ret
, "%" PRIu64
"K", bytes
/1000);
333 sprintf(ret
, "%" PRIu64
, bytes
);
341 unsigned long real_start
;
344 if (get_attribute_value_at_quark(i_end
, NULL
, "proc", proc
)) {
346 get_attribute_value_at_ulong(
347 i_end
, &proc
, "birth", birth
);
351 real_start
= i_start
;
352 get_interval_value_int(real_start
, i_end
, &proc
,
354 get_interval_value_int(real_start
, i_end
, &proc
,
356 total
+= read
+ write
;
358 } while (get_attribute_value_at_quark(
359 i_end
, &proc
, "next", proc
));
367 struct tm start
, end
;
368 uint64_t ts_nsec_start
, ts_nsec_end
;
371 int nbthreads
, nbnewthreads
, nbdeadthreads
;
372 int nbfiles
, nbnewfiles
, nbdeadfiles
;
374 ts_nsec_start
= i_start
% NSEC_PER_SEC
;
375 start
= format_timestamp(i_start
);
377 ts_nsec_end
= i_end
% NSEC_PER_SEC
;
378 end
= format_timestamp(i_end
);
382 set_window_title(header
, "Statistics for interval ");
383 wattron(header
, A_BOLD
);
386 "[%02d:%02d:%02d.%09" PRIu64
", %02d:%02d:%02d.%09" PRIu64
"[",
387 start
.tm_hour
, start
.tm_min
, start
.tm_sec
, ts_nsec_start
,
388 end
.tm_hour
, end
.tm_min
, end
.tm_sec
, ts_nsec_end
);
389 mvwprintw(header
, 1, 4, "CPUs");
390 wattroff(header
, A_BOLD
);
392 cpu_nb
= get_sequence_length(i_end
, state_system
->getQuark("cpu"));
393 get_attribute_value_at_int(i_end
, NULL
, "nbthreads", nbthreads
);
394 get_interval_value_int(i_start
, i_end
, NULL
, "nbnewthreads",
396 get_interval_value_int(i_start
, i_end
, NULL
, "nbdeadthreads",
398 get_attribute_value_at_int(i_end
, NULL
, "nbfiles", nbfiles
);
399 get_interval_value_int(i_start
, i_end
, NULL
, "nbnewfiles", nbnewfiles
);
400 get_interval_value_int(i_start
, i_end
, NULL
, "nbdeadfiles",
403 wprintw(header
, "\t%d\t(max/cpu : %0.2f%)", cpu_nb
,
405 print_headers(2, "Threads", nbthreads
, nbnewthreads
,-1*nbdeadthreads
);
406 print_headers(3, "FDs", nbfiles
, nbnewfiles
,-1*nbdeadfiles
);
407 scale_unit(total_io(), io
);
408 mvwprintw(header
, 3, 43, "%sB/sec", io
);
412 int sort_by_cpu_desc(const void *pp1
, const void *pp2
)
414 Quark p1
= *(Quark
*)pp1
;
415 Quark p2
= *(Quark
*)pp2
;
416 unsigned long total1
, total2
;
417 unsigned long birth1
, birth2
;
418 unsigned long start1
= i_start
;
419 unsigned long start2
= i_start
;
421 get_attribute_value_at_ulong(i_end
, &p1
, "birth", birth1
);
422 get_attribute_value_at_ulong(i_end
, &p2
, "birth", birth2
);
423 if (birth1
> i_start
)
425 if (birth2
> i_start
)
428 get_interval_value_ulong(start1
, i_end
, &p1
, "totalcpunsec", total1
);
429 get_interval_value_ulong(start2
, i_end
, &p2
, "totalcpunsec", total2
);
433 if (total1
== total2
)
438 int sort_by_tid_desc(const void *pp1
, const void *pp2
)
440 Quark p1
= *(Quark
*)pp1
;
441 Quark p2
= *(Quark
*)pp2
;
444 get_attribute_value_at_int(i_end
, &p1
, "tid", tid1
);
445 get_attribute_value_at_int(i_end
, &p2
, "tid", tid2
);
454 int sort_by_pid_desc(const void *pp1
, const void *pp2
)
456 Quark p1
= *(Quark
*)pp1
;
457 Quark p2
= *(Quark
*)pp2
;
460 get_attribute_value_at_int(i_end
, &p1
, "pid", pid1
);
461 get_attribute_value_at_int(i_end
, &p2
, "pid", pid2
);
471 int sort_by_process_read_desc(const void *pp1
, const void *pp2
)
473 Quark p1
= *(Quark
*)pp1
;
474 Quark p2
= *(Quark
*)pp2
;
476 unsigned long birth1
, birth2
;
477 unsigned long start1
= i_start
;
478 unsigned long start2
= i_start
;
480 get_attribute_value_at_ulong(i_end
, &p1
, "birth", birth1
);
481 get_attribute_value_at_ulong(i_end
, &p2
, "birth", birth2
);
482 if (birth1
> i_start
)
484 if (birth2
> i_start
)
487 get_interval_value_int(start1
, i_end
, &p1
, "fileread", total1
);
488 get_interval_value_int(start2
, i_end
, &p2
, "fileread", total2
);
492 if (total1
== total2
)
497 int sort_by_process_write_desc(const void *pp1
, const void *pp2
)
499 Quark p1
= *(Quark
*)pp1
;
500 Quark p2
= *(Quark
*)pp2
;
502 unsigned long birth1
, birth2
;
503 unsigned long start1
= i_start
;
504 unsigned long start2
= i_start
;
506 get_attribute_value_at_ulong(i_end
, &p1
, "birth", birth1
);
507 get_attribute_value_at_ulong(i_end
, &p2
, "birth", birth2
);
508 if (birth1
> i_start
)
510 if (birth2
> i_start
)
513 get_interval_value_int(start1
, i_end
, &p1
, "filewrite", total1
);
514 get_interval_value_int(start2
, i_end
, &p2
, "filewrite", total2
);
518 if (total1
== total2
)
523 int sort_by_process_total_desc(const void *pp1
, const void *pp2
)
525 Quark p1
= *(Quark
*)pp1
;
526 Quark p2
= *(Quark
*)pp2
;
528 int p1Write
, p2Write
;
530 unsigned long birth1
, birth2
;
531 unsigned long start1
= i_start
;
532 unsigned long start2
= i_start
;
534 get_attribute_value_at_ulong(i_end
, &p1
, "birth", birth1
);
535 get_attribute_value_at_ulong(i_end
, &p2
, "birth", birth2
);
536 if (birth1
> i_start
)
538 if (birth2
> i_start
)
541 get_interval_value_int(start1
, i_end
, &p1
, "fileread", p1Read
);
542 get_interval_value_int(start2
, i_end
, &p2
, "fileread", p2Read
);
543 get_interval_value_int(start1
, i_end
, &p1
, "filewrite", p1Write
);
544 get_interval_value_int(start2
, i_end
, &p2
, "filewrite", p2Write
);
546 total1
= p1Read
+ p1Write
;
547 total2
= p2Read
+ p2Write
;
551 if (total1
== total2
)
556 int sort_by_file_read_desc(const void *pf1
, const void *pf2
)
558 Quark f1
= *(Quark
*)pf1
;
559 Quark f2
= *(Quark
*)pf2
;
561 unsigned long birth1
, birth2
;
562 unsigned long start1
= i_start
;
563 unsigned long start2
= i_start
;
565 get_attribute_value_at_ulong(i_end
, &f1
, "file/birth", birth1
);
566 get_attribute_value_at_ulong(i_end
, &f2
, "file/birth", birth2
);
567 if (birth1
> i_start
)
569 if (birth2
> i_start
)
572 get_interval_value_int(start1
, i_end
, &f1
, "file/read", total1
);
573 get_interval_value_int(start2
, i_end
, &f2
, "file/read", total2
);
577 if (total1
== total2
)
582 int sort_by_file_write_desc(const void *pf1
, const void *pf2
)
584 Quark f1
= *(Quark
*)pf1
;
585 Quark f2
= *(Quark
*)pf2
;
587 unsigned long birth1
, birth2
;
588 unsigned long start1
= i_start
;
589 unsigned long start2
= i_start
;
591 get_attribute_value_at_ulong(i_end
, &f1
, "file/birth", birth1
);
592 get_attribute_value_at_ulong(i_end
, &f2
, "file/birth", birth2
);
593 if (birth1
> i_start
)
595 if (birth2
> i_start
)
598 get_interval_value_int(start1
, i_end
, &f1
, "file/write", total1
);
599 get_interval_value_int(start2
, i_end
, &f2
, "file/write", total2
);
603 if (total1
== total2
)
608 int sort_by_file_fd_desc(const void *pf1
, const void *pf2
)
610 Quark f1
= *(Quark
*)pf1
;
611 Quark f2
= *(Quark
*)pf2
;
614 get_attribute_value_at_int(i_end
, &f1
, "file/fd", fd1
);
615 get_attribute_value_at_int(i_end
, &f2
, "file/fd", fd2
);
624 int sort_by_cpu_group_by_threads_desc(const void *pp1
, const void *pp2
)
626 Quark p1
= *(Quark
*)pp1
;
627 Quark p2
= *(Quark
*)pp2
;
628 unsigned long total1
, total2
;
629 unsigned long birth1
, birth2
;
630 unsigned long start1
= i_start
;
631 unsigned long start2
= i_start
;
633 get_attribute_value_at_ulong(i_end
, &p1
, "birth", birth1
);
634 get_attribute_value_at_ulong(i_end
, &p2
, "birth", birth2
);
635 if (birth1
> i_start
)
637 if (birth2
> i_start
)
640 get_interval_value_ulong(start1
, i_end
, &p1
, "threadstotalcpunsec",
642 get_interval_value_ulong(start2
, i_end
, &p2
, "threadstotalcpunsec",
647 if (total1
== total2
)
652 void update_cputop_display()
655 int header_offset
= 2;
656 unsigned long elapsed
;
658 int nblinedisplayed
= 0;
659 int current_line
= 0;
663 unsigned long totalcpunsec
;
666 Quark cpu_root
= state_system
->getQuark("cpu");
667 Quark proc_root
= state_system
->getQuark("proc");
668 unsigned int cpu_nb
= get_sequence_length(i_end
, cpu_root
);
669 unsigned int proc_nb
= get_sequence_length(i_end
, proc_root
);
671 elapsed
= i_end
- i_start
;
672 maxcputime
= elapsed
* cpu_nb
/ 100.0;
674 processes
= g_new(Quark
, proc_nb
);
675 sequence_to_array(i_end
, proc_root
, processes
, proc_nb
);
677 if (cputopview
[0].sort
== 1)
678 qsort(processes
, proc_nb
, sizeof(Quark
), sort_by_cpu_desc
);
679 else if (cputopview
[1].sort
== 1)
680 qsort(processes
, proc_nb
, sizeof(Quark
), sort_by_pid_desc
);
681 else if (cputopview
[2].sort
== 1)
682 qsort(processes
, proc_nb
, sizeof(Quark
), sort_by_tid_desc
);
683 else if (cputopview
[3].sort
== 1)
684 qsort(processes
, proc_nb
, sizeof(Quark
), sort_by_cpu_desc
);
686 qsort(processes
, proc_nb
, sizeof(Quark
), sort_by_cpu_desc
);
688 set_window_title(center
, "CPU Top");
689 wattron(center
, A_BOLD
);
691 for (i
= 0; i
< 4; i
++) {
692 if (cputopview
[i
].sort
) {
693 wattron(center
, A_UNDERLINE
);
694 pref_current_sort
= i
;
696 mvwprintw(center
, 1, column
, cputopview
[i
].title
);
697 wattroff(center
, A_UNDERLINE
);
700 wattroff(center
, A_BOLD
);
702 max_center_lines
= LINES
- 5 - 7 - 1 - header_offset
;
704 /* iterate the process (thread) list */
705 for (i
= list_offset
; i
< proc_nb
&& nblinedisplayed
< max_center_lines
;
707 get_attribute_value_at_int(i_end
, processes
+ i
, "tid", tid
);
708 get_attribute_value_at_int(i_end
, processes
+ i
, "pid", pid
);
711 if (toggle_threads
== -1)
714 if (process_selected(processes
[i
])) {
715 wattron(center
, COLOR_PAIR(6));
716 mvwhline(center
, current_line
+ header_offset
, 1, ' ',
719 if (current_line
== selected_line
) {
720 selected_process
= processes
[i
];
721 wattron(center
, COLOR_PAIR(5));
722 mvwhline(center
, current_line
+ header_offset
, 1, ' ',
726 get_interval_value_ulong(i_start
, i_end
, processes
+ i
,
727 "totalcpunsec", totalcpunsec
);
728 mvwprintw(center
, current_line
+ header_offset
, 1, "%1.2f",
729 totalcpunsec
/ maxcputime
);
731 mvwprintw(center
, current_line
+ header_offset
, 11, "%d", pid
);
733 mvwprintw(center
, current_line
+ header_offset
, 21, "%d", tid
);
735 get_attribute_value_at_string(i_end
, processes
+ i
, "comm",
737 mvwprintw(center
, current_line
+ header_offset
, 31, "%s",
739 wattroff(center
, COLOR_PAIR(6));
740 wattroff(center
, COLOR_PAIR(5));
748 int sort_perf(const void *pp1
, const void *pp2
)
750 Quark p1
= *(Quark
*)pp1
;
751 Quark p2
= *(Quark
*)pp2
;
752 std::string key
= sort_perf_key
;
758 if (!get_attribute_value_at_int(i_end
, &p1
, "perf/" + key
+ "/count",
762 if (!get_attribute_value_at_int(i_end
, &p2
, "perf/" + key
+ "/count",
769 if (total1
== total2
) {
770 get_attribute_value_at_int(i_end
, &p1
, "tid", tid1
);
771 get_attribute_value_at_int(i_end
, &p2
, "tid", tid2
);
779 void print_key_title(const char key
[], int line
)
781 wattron(center
, A_BOLD
);
782 mvwprintw(center
, line
, 1, "%s", key
);
783 mvwprintw(center
, line
, 30, " ");
784 wattroff(center
, A_BOLD
);
787 void update_process_details()
789 unsigned long elapsed
;
791 unsigned int i
, j
= 0;
793 char filename_buf
[COLS
];
798 int tid
= -1, pid
, ppid
, fileread
, filewrite
;
799 unsigned long totalcpunsec
;
801 unsigned int global_perf_nb
;
805 unsigned int file_nb
;
809 set_window_title(center
, "Process details");
811 elapsed
= i_end
- i_start
;
812 cpu_nb
= get_sequence_length(i_end
, state_system
->getQuark("cpu"));
813 maxcputime
= elapsed
* cpu_nb
/ 100.0;
815 get_attribute_value_at_int(i_end
, &selected_process
, "tid", tid
);
817 print_key_title("Does not exit at this time", 3);
821 print_key_title("Name", line
++);
822 get_attribute_value_at_string(i_end
, &selected_process
, "comm", comm
);
823 wprintw(center
, "%s", comm
.c_str());
824 print_key_title("TID", line
++);
825 wprintw(center
, "%d", tid
);
827 print_key_title("PID", line
++);
828 get_attribute_value_at_int(i_end
, &selected_process
, "pid", pid
);
829 wprintw(center
, "%d", pid
);
830 print_key_title("PPID", line
++);
831 get_attribute_value_at_int(i_end
, &selected_process
, "ppid", ppid
);
832 wprintw(center
, "%d", ppid
);
833 print_key_title("CPU", line
++);
834 get_attribute_value_at_ulong(i_end
, &selected_process
, "totalcpunsec",
836 wprintw(center
, "%1.2f %%", totalcpunsec
/maxcputime
);
838 print_key_title("READ B/s", line
++);
839 get_attribute_value_at_int(i_end
, &selected_process
, "fileread",
841 scale_unit(fileread
, unit
);
842 wprintw(center
, "%s", unit
);
844 print_key_title("WRITE B/s", line
++);
845 get_attribute_value_at_int(i_end
, &selected_process
, "filewrite",
847 scale_unit(filewrite
, unit
);
848 wprintw(center
, "%s", unit
);
851 global_perf_nb
= get_global_perf_list_size(i_end
);
852 global_perf
= g_new(Quark
, global_perf_nb
);
853 get_global_perf_list(i_end
, global_perf
, global_perf_nb
);
854 for (i
= 0; i
< global_perf_nb
; i
++) {
855 get_attribute_value_at_string(i_end
, global_perf
+ i
, "key",
857 print_key_title(key
.c_str(), line
++);
858 if (!get_attribute_value_at_int(i_end
, global_perf
+ i
, "count",
861 wprintw(center
, "%d", count
);
865 wattron(center
, A_BOLD
);
867 for (i
= 0; i
< 3; i
++) {
868 if (fileview
[i
].sort
) {
869 pref_current_sort
= i
;
870 wattron(center
, A_UNDERLINE
);
872 mvwprintw(center
, line
, column
, fileview
[i
].title
);
873 wattroff(center
, A_UNDERLINE
);
876 mvwprintw(center
, line
++, column
, "FILENAME");
877 wattroff(center
, A_BOLD
);
879 file_nb
= get_number_of_opened_files(i_end
, selected_process
);
880 files
= g_new(Quark
, file_nb
);
881 get_opened_files(i_end
, selected_process
, files
, file_nb
);
883 if (fileview
[0].sort
== 1)
884 qsort(files
, file_nb
, sizeof(Quark
), sort_by_file_fd_desc
);
885 else if (fileview
[1].sort
== 1)
886 qsort(files
, file_nb
, sizeof(Quark
), sort_by_file_read_desc
);
887 else if (fileview
[2].sort
== 1)
888 qsort(files
, file_nb
, sizeof(Quark
), sort_by_file_write_desc
);
890 qsort(files
, file_nb
, sizeof(Quark
), sort_by_file_fd_desc
);
892 for (i
= selected_line
;
893 i
< file_nb
&& i
< (selected_line
+ max_center_lines
- line
+ 2);
895 get_attribute_value_at_int(i_end
, files
+ i
, "fd", fd
);
896 mvwprintw(center
, line
+ j
, 1, "%d", fd
);
897 get_attribute_value_at_int(i_end
, files
+ i
, "read", read
);
898 scale_unit(read
, unit
);
899 mvwprintw(center
, line
+ j
, 11, "%s", unit
);
900 get_attribute_value_at_int(i_end
, files
+ i
, "write", write
);
901 scale_unit(write
, unit
);
902 mvwprintw(center
, line
+ j
, 21, "%s", unit
);
903 get_attribute_value_at_string(i_end
, files
+ i
, "name", name
);
904 snprintf(filename_buf
, COLS
- 25, "%s", name
.c_str());
905 mvwprintw(center
, line
+ j
, 31, "%s", filename_buf
);
915 int nblinedisplayed
= 0;
916 int current_line
= 0;
917 int header_offset
= 2;
920 unsigned int global_perf_nb
;
926 unsigned int proc_nb
;
932 set_window_title(center
, "Perf Top");
933 wattron(center
, A_BOLD
);
934 mvwprintw(center
, 1, 1, "PID");
935 mvwprintw(center
, 1, 11, "TID");
936 mvwprintw(center
, 1, 22, "NAME");
939 global_perf_nb
= get_global_perf_list_size(i_end
);
940 global_perf
= g_new(Quark
, global_perf_nb
);
941 get_global_perf_list(i_end
, global_perf
, global_perf_nb
);
942 for (i
= 0; i
< global_perf_nb
; i
++) {
943 get_attribute_value_at_int(i_end
, global_perf
+ i
, "visible",
945 get_attribute_value_at_string(i_end
, global_perf
+ i
, "key",
947 sort_exists
= get_attribute_value_at_int(i_end
, global_perf
+ i
,
950 if (sort_exists
&& sort
) {
951 wattron(center
, A_UNDERLINE
);
953 /* + 5 to strip the "perf_" prefix */
954 mvwprintw(center
, 1, perf_row
, "%s",
956 wattroff(center
, A_UNDERLINE
);
959 if (sort_exists
&& sort
) {
963 wattroff(center
, A_BOLD
);
965 proc_beg
= state_system
->getQuark("proc");
966 proc_nb
= get_sequence_length(i_end
, proc_beg
);
967 procs
= g_new(Quark
, proc_nb
);
968 sequence_to_array(i_end
, proc_beg
, procs
, proc_nb
);
969 for (i
= 0; i
< proc_nb
&& nblinedisplayed
< max_center_lines
; i
++) {
970 get_attribute_value_at_int(i_end
, procs
+ i
, "tid", tid
);
971 get_attribute_value_at_int(i_end
, procs
+ i
, "pid", pid
);
972 get_attribute_value_at_string(i_end
, procs
+ 1, "comm", comm
);
975 if (toggle_threads
== -1)
978 if (process_selected(procs
[i
])) {
979 wattron(center
, COLOR_PAIR(6));
980 mvwhline(center
, current_line
+ header_offset
, 1, ' ',
983 if (current_line
== selected_line
) {
984 selected_process
= procs
[i
];
985 wattron(center
, COLOR_PAIR(5));
986 mvwhline(center
, current_line
+ header_offset
, 1, ' ',
990 mvwprintw(center
, current_line
+ header_offset
, 1, "%d", pid
);
991 mvwprintw(center
, current_line
+ header_offset
, 11, "%d", tid
);
992 mvwprintw(center
, current_line
+ header_offset
, 22, "%s",
996 for (j
= 0; j
< global_perf_nb
; j
++) {
997 get_attribute_value_at_int(i_end
, global_perf
+ j
,
999 get_attribute_value_at_string(i_end
, global_perf
+ j
,
1003 if (!get_interval_value_int(i_start
, i_end
,
1004 procs
+ i
, "perf/" +
1009 mvwprintw(center
, current_line
+ header_offset
,
1010 perf_row
, "%d", value
);
1015 wattroff(center
, COLOR_PAIR(6));
1016 wattroff(center
, COLOR_PAIR(5));
1020 g_free(global_perf
);
1024 void update_iostream()
1027 int header_offset
= 2;
1028 int nblinedisplayed
= 0;
1029 int current_line
= 0;
1032 unsigned int proc_nb
;
1035 int pid
, tid
, read
, write
, totalread
, totalwrite
;
1038 set_window_title(center
, "IO Top");
1039 wattron(center
, A_BOLD
);
1040 mvwprintw(center
, 1, 1, "PID");
1041 mvwprintw(center
, 1, 11, "TID");
1042 mvwprintw(center
, 1, 22, "NAME");
1044 for (i
= 0; i
< 3; i
++) {
1045 if (iostreamtopview
[i
].sort
) {
1046 pref_current_sort
= i
;
1047 wattron(center
, A_UNDERLINE
);
1049 mvwprintw(center
, 1, column
, iostreamtopview
[i
].title
);
1050 wattroff(center
, A_UNDERLINE
);
1053 wattroff(center
, A_BOLD
);
1054 wattroff(center
, A_UNDERLINE
);
1056 proc_root
= state_system
->getQuark("proc");
1057 proc_nb
= get_sequence_length(i_end
, proc_root
);
1058 procs
= g_new(Quark
, proc_nb
);
1059 sequence_to_array(i_end
, proc_root
, procs
, proc_nb
);
1061 if (iostreamtopview
[0].sort
== 1)
1062 qsort(procs
, proc_nb
, sizeof(Quark
), sort_by_process_read_desc
);
1063 else if (iostreamtopview
[1].sort
== 1)
1064 qsort(procs
, proc_nb
, sizeof(Quark
),
1065 sort_by_process_write_desc
);
1066 else if (iostreamtopview
[2].sort
== 1)
1067 qsort(procs
, proc_nb
, sizeof(Quark
),
1068 sort_by_process_total_desc
);
1070 qsort(procs
, proc_nb
, sizeof(Quark
),
1071 sort_by_process_total_desc
);
1073 for (i
= list_offset
; i
< proc_nb
&& nblinedisplayed
< max_center_lines
;
1075 get_attribute_value_at_int(i_end
, procs
+ i
, "tid", tid
);
1076 get_attribute_value_at_int(i_end
, procs
+ i
, "pid", pid
);
1077 get_attribute_value_at_string(i_end
, procs
+ i
, "comm", comm
);
1078 get_attribute_value_at_int(i_end
, procs
+ i
, "fileread",
1080 get_attribute_value_at_int(i_end
, procs
+ i
, "filewrite",
1082 get_attribute_value_at_int(i_end
, procs
+ i
, "totalfileread",
1084 get_attribute_value_at_int(i_end
, procs
+ i
, "totalfilewrite",
1089 if (toggle_threads
== -1)
1092 if (process_selected(procs
[i
])) {
1093 wattron(center
, COLOR_PAIR(6));
1094 mvwhline(center
, current_line
+ header_offset
, 1, ' ',
1097 if (current_line
== selected_line
) {
1098 selected_process
= procs
[i
];
1099 wattron(center
, COLOR_PAIR(5));
1100 mvwhline(center
, current_line
+ header_offset
, 1, ' ',
1104 mvwprintw(center
, current_line
+ header_offset
, 1, "%d", pid
);
1106 mvwprintw(center
, current_line
+ header_offset
, 11, "%d", tid
);
1108 mvwprintw(center
, current_line
+ header_offset
, 22, "%s",
1111 /* READ (bytes/sec) */
1112 scale_unit(read
, unit
);
1113 mvwprintw(center
, current_line
+ header_offset
, 40, "%s", unit
);
1115 /* WRITE (bytes/sec) */
1116 scale_unit(write
, unit
);
1117 mvwprintw(center
, current_line
+ header_offset
, 52, "%s", unit
);
1120 scale_unit(totalread
+ totalwrite
, unit
);
1121 mvwprintw(center
, current_line
+ header_offset
, 64, "%s", unit
);
1123 wattroff(center
, COLOR_PAIR(6));
1124 wattroff(center
, COLOR_PAIR(5));
1131 void update_current_view()
1133 sem_wait(&update_display_sem
);
1138 switch (current_view
) {
1140 update_cputop_display();
1145 case process_details
:
1146 update_process_details();
1152 update_cputop_display();
1159 sem_post(&update_display_sem
);
1162 void update_process_detail_sort(int *line_selected
)
1169 if (*line_selected
> (size
- 1))
1170 *line_selected
= size
- 1;
1171 else if (*line_selected
< 0)
1174 if (fileview
[*line_selected
].sort
== 1)
1175 fileview
[*line_selected
].reverse
= 1;
1176 for (i
= 0; i
< size
; i
++)
1177 fileview
[i
].sort
= 0;
1178 fileview
[*line_selected
].sort
= 1;
1181 void update_process_detail_pref(int *line_selected
, int toggle_view
, int toggle_sort
)
1186 if (pref_panel_window
) {
1187 del_panel(pref_panel
);
1188 delwin(pref_panel_window
);
1192 pref_panel_window
= create_window(size
+ 2, 30, 10, 10);
1193 pref_panel
= new_panel(pref_panel_window
);
1195 werase(pref_panel_window
);
1196 box(pref_panel_window
, 0 , 0);
1197 set_window_title(pref_panel_window
, "Process Detail Preferences ");
1198 wattron(pref_panel_window
, A_BOLD
);
1199 mvwprintw(pref_panel_window
, size
+ 1, 1,
1200 " 's' : sort, space : toggle");
1201 wattroff(pref_panel_window
, A_BOLD
);
1203 if (*line_selected
> (size
- 1))
1204 *line_selected
= size
- 1;
1205 else if (*line_selected
< 0)
1207 if (toggle_sort
== 1) {
1208 update_process_detail_sort(line_selected
);
1209 update_current_view();
1212 for (i
= 0; i
< size
; i
++) {
1213 if (i
== *line_selected
) {
1214 wattron(pref_panel_window
, COLOR_PAIR(5));
1215 mvwhline(pref_panel_window
, i
+ 1, 1, ' ', 30 - 2);
1217 if (fileview
[i
].sort
== 1)
1218 wattron(pref_panel_window
, A_BOLD
);
1219 mvwprintw(pref_panel_window
, i
+ 1, 1, "[-] %s",
1221 wattroff(pref_panel_window
, A_BOLD
);
1222 wattroff(pref_panel_window
, COLOR_PAIR(5));
1229 void update_iostream_sort(int *line_selected
)
1235 if (*line_selected
> (size
- 1))
1236 *line_selected
= size
- 1;
1237 else if (*line_selected
< 0)
1239 if (iostreamtopview
[*line_selected
].sort
== 1)
1240 iostreamtopview
[*line_selected
].reverse
= 1;
1241 for (i
= 0; i
< size
; i
++)
1242 iostreamtopview
[i
].sort
= 0;
1243 iostreamtopview
[*line_selected
].sort
= 1;
1247 void update_iostream_pref(int *line_selected
, int toggle_view
, int toggle_sort
)
1252 if (pref_panel_window
) {
1253 del_panel(pref_panel
);
1254 delwin(pref_panel_window
);
1258 pref_panel_window
= create_window(size
+ 2, 30, 10, 10);
1259 pref_panel
= new_panel(pref_panel_window
);
1261 werase(pref_panel_window
);
1262 box(pref_panel_window
, 0 , 0);
1263 set_window_title(pref_panel_window
, "IOTop Preferences ");
1264 wattron(pref_panel_window
, A_BOLD
);
1265 mvwprintw(pref_panel_window
, size
+ 1, 1,
1266 " 's' : sort, space : toggle");
1267 wattroff(pref_panel_window
, A_BOLD
);
1269 if (*line_selected
> (size
- 1))
1270 *line_selected
= size
- 1;
1271 else if (*line_selected
< 0)
1273 if (toggle_sort
== 1) {
1274 update_iostream_sort(line_selected
);
1275 update_current_view();
1278 for (i
= 0; i
< size
; i
++) {
1279 if (i
== *line_selected
) {
1280 wattron(pref_panel_window
, COLOR_PAIR(5));
1281 mvwhline(pref_panel_window
, i
+ 1, 1, ' ', 30 - 2);
1283 if (iostreamtopview
[i
].sort
== 1)
1284 wattron(pref_panel_window
, A_BOLD
);
1285 mvwprintw(pref_panel_window
, i
+ 1, 1, "[-] %s",
1286 iostreamtopview
[i
].title
);
1287 wattroff(pref_panel_window
, A_BOLD
);
1288 wattroff(pref_panel_window
, COLOR_PAIR(5));
1295 void update_cpu_sort(int *line_selected
)
1300 if (*line_selected
> (size
- 1))
1301 *line_selected
= size
- 1;
1302 else if (*line_selected
< 0)
1305 /* special case, we don't support sorting by procname for now */
1306 if (*line_selected
!= 3) {
1307 if (cputopview
[*line_selected
].sort
== 1)
1308 cputopview
[*line_selected
].reverse
= 1;
1309 for (i
= 0; i
< size
; i
++)
1310 cputopview
[i
].sort
= 0;
1311 cputopview
[*line_selected
].sort
= 1;
1315 void update_cpu_pref(int *line_selected
, int toggle_view
, int toggle_sort
)
1320 if (pref_panel_window
) {
1321 del_panel(pref_panel
);
1322 delwin(pref_panel_window
);
1326 pref_panel_window
= create_window(size
+ 2, 30, 10, 10);
1327 pref_panel
= new_panel(pref_panel_window
);
1329 werase(pref_panel_window
);
1330 box(pref_panel_window
, 0 , 0);
1331 set_window_title(pref_panel_window
, "CPUTop Preferences ");
1332 wattron(pref_panel_window
, A_BOLD
);
1333 mvwprintw(pref_panel_window
, size
+ 1, 1,
1334 " 's' : sort, space : toggle");
1335 wattroff(pref_panel_window
, A_BOLD
);
1337 if (*line_selected
> (size
- 1))
1338 *line_selected
= size
- 1;
1339 else if (*line_selected
< 0)
1341 if (toggle_sort
== 1) {
1342 update_cpu_sort(line_selected
);
1343 update_current_view();
1346 for (i
= 0; i
< size
; i
++) {
1347 if (i
== *line_selected
) {
1348 wattron(pref_panel_window
, COLOR_PAIR(5));
1349 mvwhline(pref_panel_window
, i
+ 1, 1, ' ', 30 - 2);
1351 if (cputopview
[i
].sort
== 1)
1352 wattron(pref_panel_window
, A_BOLD
);
1353 mvwprintw(pref_panel_window
, i
+ 1, 1, "[-] %s",
1354 cputopview
[i
].title
);
1355 wattroff(pref_panel_window
, A_BOLD
);
1356 wattroff(pref_panel_window
, COLOR_PAIR(5));
1363 void update_perf_sort(int *line_selected
)
1369 size
= get_global_perf_list_size(i_end
);
1370 global_perf
= g_new(Quark
, size
);
1371 get_global_perf_list(i_end
, global_perf
, size
);
1373 if (*line_selected
> (size
- 1))
1374 *line_selected
= size
- 1;
1375 else if (*line_selected
< 0)
1378 for (i
= 0; i
< size
; i
++) {
1379 if (i
!= *line_selected
)
1380 modify_attribute(i_end
, global_perf
+ i
, "sort", 0);
1382 modify_attribute(i_end
, global_perf
+ i
, "sort", 1);
1385 g_free(global_perf
);
1388 void update_perf_pref(int *line_selected
, int toggle_view
, int toggle_sort
)
1397 if (pref_panel_window
) {
1398 del_panel(pref_panel
);
1399 delwin(pref_panel_window
);
1402 size
= get_global_perf_list_size(i_end
);
1403 global_perf
= g_new(Quark
, size
);
1404 get_global_perf_list(i_end
, global_perf
, size
);
1406 pref_panel_window
= create_window(size
+ 2, 30, 10, 10);
1407 pref_panel
= new_panel(pref_panel_window
);
1409 werase(pref_panel_window
);
1410 box(pref_panel_window
, 0 , 0);
1411 set_window_title(pref_panel_window
, "Perf Preferences ");
1412 wattron(pref_panel_window
, A_BOLD
);
1413 mvwprintw(pref_panel_window
, size
+ 1, 1,
1414 " 's' : sort, space : toggle");
1415 wattroff(pref_panel_window
, A_BOLD
);
1417 if (*line_selected
> (size
- 1))
1418 *line_selected
= size
- 1;
1419 else if (*line_selected
< 0)
1422 if (toggle_sort
== 1) {
1423 update_perf_sort(line_selected
);
1424 update_current_view();
1427 for (i
= 0; i
< size
; i
++) {
1428 get_attribute_value_at_int(i_end
, global_perf
+ i
,
1429 "visible", visible
);
1430 get_attribute_value_at_string(i_end
, global_perf
+ i
, "key",
1432 if (i
== *line_selected
&& toggle_view
== 1) {
1433 visible
= visible
== 1 ? 0 : 1;
1434 modify_attribute(i_end
, global_perf
+ i
, "visible",
1436 update_current_view();
1438 if (i
== *line_selected
) {
1439 wattron(pref_panel_window
, COLOR_PAIR(5));
1440 mvwhline(pref_panel_window
, i
+ 1, 1, ' ', 30 - 2);
1443 if (get_attribute_value_at_int(i_end
, global_perf
+ 1, "sort",
1445 wattron(pref_panel_window
, A_BOLD
);
1447 mvwprintw(pref_panel_window
, i
+ 1, 1, "[%c] %s",
1448 visible
== 1 ? 'x' : ' ', key
.c_str() + 5);
1449 wattroff(pref_panel_window
, A_BOLD
);
1450 wattroff(pref_panel_window
, COLOR_PAIR(5));
1455 g_free(global_perf
);
1458 int update_preference_panel(int *line_selected
, int toggle_view
, int toggle_sort
)
1462 switch(current_view
) {
1464 update_perf_pref(line_selected
, toggle_view
, toggle_sort
);
1467 update_cpu_pref(line_selected
, toggle_view
, toggle_sort
);
1470 update_iostream_pref(line_selected
, toggle_view
, toggle_sort
);
1472 case process_details
:
1473 update_process_detail_pref(line_selected
, toggle_view
, toggle_sort
);
1483 int update_sort(int *line_selected
)
1487 switch(current_view
) {
1489 update_perf_sort(line_selected
);
1492 update_cpu_sort(line_selected
);
1495 update_iostream_sort(line_selected
);
1497 case process_details
:
1498 update_process_detail_sort(line_selected
);
1509 void toggle_pref_panel(void)
1513 if (pref_panel_visible
) {
1514 hide_panel(pref_panel
);
1515 pref_panel_visible
= 0;
1517 ret
= update_preference_panel(&pref_line_selected
, 0, 0);
1520 show_panel(pref_panel
);
1521 pref_panel_visible
= 1;
1530 i_start
= first_display_update
;
1532 i_start
+= refresh_display
;
1533 i_end
= i_start
+ refresh_display
;
1535 max_elements
= get_sequence_length(
1536 i_end
, state_system
->getQuark("proc"));
1537 update_current_view();
1543 void pause_display()
1547 sem_wait(&pause_sem
);
1550 void resume_display()
1553 print_log("Resume");
1554 sem_post(&pause_sem
);
1557 void *handle_keyboard(void *p
)
1560 while((ch
= getch())) {
1562 /* Move the cursor and scroll */
1565 if (pref_panel_visible
) {
1566 pref_line_selected
++;
1567 update_preference_panel(&pref_line_selected
, 0, 0);
1569 if (selected_line
< (max_center_lines
- 1) &&
1570 selected_line
< max_elements
- 1) {
1573 } else if (selected_in_list
< (max_elements
- 1)
1574 && (list_offset
< (max_elements
- max_center_lines
))) {
1578 update_current_view();
1585 if (pref_panel_visible
) {
1586 if (pref_line_selected
> 0)
1587 pref_line_selected
--;
1588 update_preference_panel(&pref_line_selected
, 0, 0);
1590 if (selected_line
> 0) {
1593 } else if (selected_in_list
> 0 && list_offset
> 0) {
1597 update_current_view();
1603 /* Navigate the history with arrows */
1605 if ((i_start
- refresh_display
) >=
1606 first_display_update
) {
1607 i_start
-= refresh_display
;
1608 i_end
= i_start
+ refresh_display
;
1609 print_log("Going back in time");
1611 print_log("Cannot rewind, last data is already displayed");
1613 max_elements
= get_sequence_length(
1614 i_end
, state_system
->getQuark("proc"));
1616 /* we force to pause the display when moving in time */
1617 if (toggle_pause
< 0)
1620 update_current_view();
1624 if ((i_end
+ refresh_display
) <=
1625 last_display_update
) {
1626 i_end
+= refresh_display
;
1627 i_start
= i_end
- refresh_display
;
1628 print_log("Going forward in time");
1629 max_elements
= get_sequence_length(
1630 i_end
, state_system
->getQuark(
1632 update_current_view();
1635 print_log("Manually moving forward");
1637 if (toggle_pause
> 0) {
1638 sem_post(&pause_sem
);
1639 update_current_view();
1640 sem_wait(&pause_sem
);
1646 if (pref_panel_visible
) {
1647 update_preference_panel(&pref_line_selected
, 1, 0);
1649 update_selected_processes();
1650 update_current_view();
1654 if (pref_panel_visible
)
1655 update_preference_panel(&pref_line_selected
, 0, 1);
1658 /* perf uses a hashtable, it is ordered backward */
1659 if (current_view
== perf
) {
1660 pref_current_sort
--;
1661 } else if (!pref_panel_visible
) {
1662 pref_current_sort
++;
1664 update_sort(&pref_current_sort
);
1665 update_current_view();
1668 /* perf uses a hashtable, it is ordered backward */
1669 if (current_view
== perf
) {
1670 pref_current_sort
++;
1671 } else if (!pref_panel_visible
) {
1672 pref_current_sort
--;
1674 update_sort(&pref_current_sort
);
1675 update_current_view();
1678 case 13: /* FIXME : KEY_ENTER ?? */
1679 if (pref_panel_visible
)
1681 if (current_view
!= process_details
) {
1682 previous_view
= current_view
;
1683 current_view
= process_details
;
1685 current_view
= previous_view
;
1686 previous_view
= process_details
;
1688 update_current_view();
1692 if (pref_panel_visible
)
1693 toggle_pref_panel();
1696 update_current_view();
1699 if (pref_panel_visible
)
1700 toggle_pref_panel();
1703 update_current_view();
1706 if (pref_panel_visible
)
1707 toggle_pref_panel();
1708 current_view
= perf
;
1710 update_current_view();
1713 if (pref_panel_visible
)
1714 toggle_pref_panel();
1715 current_view
= iostream
;
1717 update_current_view();
1724 toggle_threads
*= -1;
1725 update_current_view();
1728 if (toggle_pause
< 0) {
1735 toggle_pref_panel();
1737 /* ESCAPE, but slow to process, don't know why */
1739 if (pref_panel_visible
)
1740 toggle_pref_panel();
1741 else if (current_view
== process_details
) {
1742 current_view
= previous_view
;
1743 previous_view
= process_details
;
1745 update_current_view();
1748 update_current_view();
1756 void init_view_headers()
1758 cputopview
[0].title
= strdup("CPU(%)");
1759 cputopview
[0].sort
= 1;
1760 cputopview
[1].title
= strdup("PID");
1761 cputopview
[2].title
= strdup("TID");
1762 cputopview
[3].title
= strdup("NAME");
1764 iostreamtopview
[0].title
= strdup("R (B/sec)");
1765 iostreamtopview
[1].title
= strdup("W (B/sec)");
1766 iostreamtopview
[2].title
= strdup("Total (B)");
1767 iostreamtopview
[2].sort
= 1;
1769 fileview
[0].title
= strdup("FD");
1770 fileview
[1].title
= strdup("READ");
1771 fileview
[1].sort
= 1;
1772 fileview
[2].title
= strdup("WRITE");
1777 selected_processes
= g_ptr_array_new();
1778 sem_init(&update_display_sem
, 0, 1);
1779 init_view_headers();
1782 header
= create_window(5, COLS
- 1, 0, 0);
1783 center
= create_window(LINES
- 5 - 7, COLS
- 1, 5, 0);
1784 status
= create_window(MAX_LOG_LINES
+ 2, COLS
- 1, LINES
- 7, 0);
1785 footer
= create_window(1, COLS
- 1, LINES
- 1, 0);
1787 print_log("Starting display");
1789 main_panel
= new_panel(center
);
1796 pthread_create(&keyboard_thread
, NULL
, handle_keyboard
, (void *)NULL
);