]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_tbuf_output.cpp
Update
[l4.git] / kernel / fiasco / src / jdb / jdb_tbuf_output.cpp
1 INTERFACE:
2
3 #include "initcalls.h"
4 #include "l4_types.h"
5 #include "thread.h"
6
7 class Tb_entry;
8 class String_buffer;
9
10 class Jdb_tbuf_output
11 {
12 private:
13   typedef void (Format_entry_fn)(String_buffer *, Tb_entry *tb, const char *tidstr,
14                                  int tidlen);
15   static Format_entry_fn *_format_entry_fn[];
16   static bool show_names;
17 };
18
19 IMPLEMENTATION:
20
21 #include <cassert>
22 #include <cstdlib>
23 #include <cstdio>
24 #include <cstring>
25
26 #include "config.h"
27 #include "initcalls.h"
28 #include "jdb.h"
29 #include "jdb_kobject_names.h"
30 #include "jdb_regex.h"
31 #include "jdb_symbol.h"
32 #include "jdb_tbuf.h"
33 #include "kdb_ke.h"
34 #include "kernel_console.h"
35 #include "l4_types.h"
36 #include "processor.h"
37 #include "static_init.h"
38 #include "string_buffer.h"
39 #include "tb_entry.h"
40 #include "terminate.h"
41 #include "watchdog.h"
42
43
44 Jdb_tbuf_output::Format_entry_fn *Jdb_tbuf_output::_format_entry_fn[Tbuf_dynentries];
45 bool Jdb_tbuf_output::show_names;
46
47 static void
48 console_log_entry(Tb_entry *e, const char *)
49 {
50   static String_buf<80> log_message;
51   log_message.reset();
52
53   // disable all interrupts to stop other threads
54   Watchdog::disable();
55   Proc::Status s = Proc::cli_save();
56
57   Jdb_tbuf_output::print_entry(&log_message, e);
58   printf("%s\n", log_message.begin());
59
60   // do not use getchar here because we ran cli'd
61   // and getchar may do halt
62   int c;
63   Jdb::enter_getchar();
64   while ((c=Kconsole::console()->getchar(false)) == -1)
65     Proc::pause();
66   Jdb::leave_getchar();
67   if (c == 'i')
68     kdb_ke("LOG");
69   if (c == '^')
70     terminate(1);
71
72   // enable interrupts we previously disabled
73   Proc::sti_restore(s);
74   Watchdog::enable();
75 }
76
77 PRIVATE static
78 void
79 Jdb_tbuf_output::dummy_format_entry(String_buffer *buf, Tb_entry *tb, const char *, int)
80 {
81   buf->printf(" << no format_entry_fn for type %d registered >>", tb->type());
82 }
83
84 STATIC_INITIALIZE(Jdb_tbuf_output);
85
86 PUBLIC static
87 void FIASCO_INIT
88 Jdb_tbuf_output::init()
89 {
90   unsigned i;
91
92   Jdb_tbuf::direct_log_entry = &console_log_entry;
93   for (i=0; i<sizeof(_format_entry_fn)/sizeof(_format_entry_fn[0]); i++)
94     if (!_format_entry_fn[i])
95       _format_entry_fn[i] = dummy_format_entry;
96 }
97
98 PUBLIC static
99 void
100 Jdb_tbuf_output::register_ff(Unsigned8 type, Format_entry_fn format_entry_fn)
101 {
102   assert(type < Tbuf_dynentries);
103
104   if (   (_format_entry_fn[type] != 0)
105       && (_format_entry_fn[type] != dummy_format_entry))
106     panic("format entry function for type %d already registered", type);
107
108   _format_entry_fn[type] = format_entry_fn;
109 }
110
111 // return thread+ip of entry <e_nr>
112 PUBLIC static
113 int
114 Jdb_tbuf_output::thread_ip(int e_nr, Thread const **th, Mword *ip)
115 {
116   Tb_entry *e = Jdb_tbuf::lookup(e_nr);
117
118   if (!e)
119     return false;
120
121   *th = static_cast<Thread const *>(e->ctx());
122
123   *ip = e->ip();
124
125   return true;
126 }
127
128 PUBLIC static
129 void
130 Jdb_tbuf_output::toggle_names()
131 {
132   show_names = !show_names;
133 }
134
135 static
136 void
137 formatter_default(String_buffer *buf, Tb_entry *tb, const char *tidstr, int tidlen)
138 {
139   if (tb->type() < Tbuf_dynentries)
140     return;
141
142   int idx = tb->type()-Tbuf_dynentries;
143
144   Tb_entry_formatter *fmt = _log_table[idx].fmt;
145   char const *sc = _log_table[idx].name;
146   sc += strlen(sc) + 1;
147
148   buf->printf("%-3s: %-*s ", sc, tidlen, tidstr);
149
150   if (!fmt)
151     {
152       Tb_entry_ke_reg *e = static_cast<Tb_entry_ke_reg*>(tb);
153       buf->printf("\"%s\" " L4_PTR_FMT " " L4_PTR_FMT " " L4_PTR_FMT " @ " L4_PTR_FMT,
154                e->msg.str(), e->v[0], e->v[1], e->v[2], e->ip());
155     }
156
157   fmt->print(buf, tb);
158 }
159
160 PUBLIC static
161 void
162 Jdb_tbuf_output::print_entry(String_buffer *buf, int e_nr)
163 {
164   Tb_entry *tb = Jdb_tbuf::lookup(e_nr);
165
166   if (tb)
167     print_entry(buf, tb);
168 }
169
170 PUBLIC static
171 void
172 Jdb_tbuf_output::print_entry(String_buffer *buf, Tb_entry *tb)
173 {
174   assert(tb->type() < Tbuf_max);
175
176   char tidstr[32];
177   Thread const *t = static_cast<Thread const *>(tb->ctx());
178
179   if (!t || !Kobject_dbg::is_kobj(t))
180     strcpy(tidstr, "????");
181   else
182     {
183       Jdb_kobject_name *ex
184         = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(t);
185       if (show_names && ex)
186         snprintf(tidstr, sizeof(tidstr), "%04lx %-*.*s", t->dbg_info()->dbg_id(), (int)ex->max_len(), (int)ex->max_len(), ex->name());
187       else
188         snprintf(tidstr, sizeof(tidstr), "%04lx", t->dbg_info()->dbg_id());
189     }
190
191   if (Config::Max_num_cpus > 1)
192     buf->printf(Config::Max_num_cpus > 16 ? "%02d " : "%d ", tb->cpu());
193
194   if (tb->type() >= Tbuf_dynentries)
195     formatter_default(buf, tb, tidstr, show_names ? 21 : 4);
196   else
197     _format_entry_fn[tb->type()](buf, tb, tidstr, show_names ? 21 : 4);
198
199   buf->fill(' ');
200   buf->terminate();
201 }
202
203 PUBLIC static
204 bool
205 Jdb_tbuf_output::set_filter(const char *filter_str, Mword *entries)
206 {
207   if (*filter_str && Jdb_regex::avail() && !Jdb_regex::start(filter_str))
208     return false;
209
210   if (!*filter_str)
211     {
212       for (Mword n=0; n<Jdb_tbuf::unfiltered_entries(); n++)
213         Jdb_tbuf::unfiltered_lookup(n)->unhide();
214
215       Jdb_tbuf::disable_filter();
216       if (entries)
217         *entries = Jdb_tbuf::unfiltered_entries();
218       return true;
219     }
220
221   Mword cnt = 0;
222
223   for (Mword n=0; n<Jdb_tbuf::unfiltered_entries(); n++)
224     {
225       Tb_entry *e = Jdb_tbuf::unfiltered_lookup(n);
226       String_buf<200> s;
227
228       print_entry(&s, e);
229       if (Jdb_regex::avail())
230         {
231           if (Jdb_regex::find(s.begin(), 0, 0))
232             {
233               e->unhide();
234               cnt++;
235               continue;
236             }
237         }
238       else
239         {
240           if (strstr(s.begin(), filter_str))
241             {
242               e->unhide();
243               cnt++;
244               continue;
245             }
246         }
247       e->hide();
248     }
249
250   if (entries)
251     *entries = cnt;
252   Jdb_tbuf::enable_filter();
253   return true;
254 }