Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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}