Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.19 173 lines 3.1 kB view raw
1#include <signal.h> 2#include <stdbool.h> 3#ifdef HAVE_BACKTRACE_SUPPORT 4#include <execinfo.h> 5#endif 6 7#include "../../util/cache.h" 8#include "../../util/debug.h" 9#include "../browser.h" 10#include "../helpline.h" 11#include "../ui.h" 12#include "../util.h" 13#include "../libslang.h" 14#include "../keysyms.h" 15#include "tui.h" 16 17static volatile int ui__need_resize; 18 19extern struct perf_error_ops perf_tui_eops; 20 21extern void hist_browser__init_hpp(void); 22 23void ui__refresh_dimensions(bool force) 24{ 25 if (force || ui__need_resize) { 26 ui__need_resize = 0; 27 pthread_mutex_lock(&ui__lock); 28 SLtt_get_screen_size(); 29 SLsmg_reinit_smg(); 30 pthread_mutex_unlock(&ui__lock); 31 } 32} 33 34static void ui__sigwinch(int sig __maybe_unused) 35{ 36 ui__need_resize = 1; 37} 38 39static void ui__setup_sigwinch(void) 40{ 41 static bool done; 42 43 if (done) 44 return; 45 46 done = true; 47 pthread__unblock_sigwinch(); 48 signal(SIGWINCH, ui__sigwinch); 49} 50 51int ui__getch(int delay_secs) 52{ 53 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; 54 fd_set read_set; 55 int err, key; 56 57 ui__setup_sigwinch(); 58 59 FD_ZERO(&read_set); 60 FD_SET(0, &read_set); 61 62 if (delay_secs) { 63 timeout.tv_sec = delay_secs; 64 timeout.tv_usec = 0; 65 } 66 67 err = select(1, &read_set, NULL, NULL, ptimeout); 68 69 if (err == 0) 70 return K_TIMER; 71 72 if (err == -1) { 73 if (errno == EINTR) 74 return K_RESIZE; 75 return K_ERROR; 76 } 77 78 key = SLang_getkey(); 79 if (key != K_ESC) 80 return key; 81 82 FD_ZERO(&read_set); 83 FD_SET(0, &read_set); 84 timeout.tv_sec = 0; 85 timeout.tv_usec = 20; 86 err = select(1, &read_set, NULL, NULL, &timeout); 87 if (err == 0) 88 return K_ESC; 89 90 SLang_ungetkey(key); 91 return SLkp_getkey(); 92} 93 94#ifdef HAVE_BACKTRACE_SUPPORT 95static void ui__signal_backtrace(int sig) 96{ 97 void *stackdump[32]; 98 size_t size; 99 100 ui__exit(false); 101 psignal(sig, "perf"); 102 103 printf("-------- backtrace --------\n"); 104 size = backtrace(stackdump, ARRAY_SIZE(stackdump)); 105 backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); 106 107 exit(0); 108} 109#else 110# define ui__signal_backtrace ui__signal 111#endif 112 113static void ui__signal(int sig) 114{ 115 ui__exit(false); 116 psignal(sig, "perf"); 117 exit(0); 118} 119 120int ui__init(void) 121{ 122 int err; 123 124 SLutf8_enable(-1); 125 SLtt_get_terminfo(); 126 SLtt_get_screen_size(); 127 128 err = SLsmg_init_smg(); 129 if (err < 0) 130 goto out; 131 err = SLang_init_tty(0, 0, 0); 132 if (err < 0) 133 goto out; 134 135 err = SLkp_init(); 136 if (err < 0) { 137 pr_err("TUI initialization failed.\n"); 138 goto out; 139 } 140 141 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); 142 143 ui_helpline__init(); 144 ui_browser__init(); 145 tui_progress__init(); 146 147 signal(SIGSEGV, ui__signal_backtrace); 148 signal(SIGFPE, ui__signal_backtrace); 149 signal(SIGINT, ui__signal); 150 signal(SIGQUIT, ui__signal); 151 signal(SIGTERM, ui__signal); 152 153 perf_error__register(&perf_tui_eops); 154 155 hist_browser__init_hpp(); 156out: 157 return err; 158} 159 160void ui__exit(bool wait_for_ok) 161{ 162 if (wait_for_ok) 163 ui__question_window("Fatal Error", 164 ui_helpline__last_msg, 165 "Press any key...", 0); 166 167 SLtt_set_cursor_visibility(1); 168 SLsmg_refresh(); 169 SLsmg_reset_smg(); 170 SLang_reset_tty(); 171 172 perf_error__unregister(&perf_tui_eops); 173}