]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_timeout.cpp
update
[l4.git] / kernel / fiasco / src / jdb / jdb_timeout.cpp
1 IMPLEMENTATION:
2
3 #include <cstdio>
4 #include <cstring>
5
6 #include "config.h"
7 #include "globals.h"
8 #include "ipc_timeout.h"
9 #include "jdb.h"
10 #include "jdb_kobject.h"
11 #include "jdb_kobject_names.h"
12 #include "jdb_module.h"
13 #include "jdb_screen.h"
14 #include "kernel_console.h"
15 #include "keycodes.h"
16 #include "kmem.h"
17 #include "simpleio.h"
18 #include "static_init.h"
19 #include "timeout.h"
20 #include "timeslice_timeout.h"
21 #include "thread.h"
22
23 class Jdb_list_timeouts : public Jdb_module
24 {
25 public:
26   Jdb_list_timeouts() FIASCO_INIT;
27 private:
28   enum
29   {
30     Timeout_timeslice = 1,
31     Timeout_sc        = 2,
32   };
33 };
34
35
36 namespace {
37
38 class Timeout_iter
39 {
40 private:
41   typedef Timeout::To_list::Const_iterator To_iter;
42
43   int skip_empty(To_iter *c, int i)
44   {
45     while (*c == _q->first(i).end() && i < (int)_q->queues())
46       {
47         ++i;
48         *c = _q->first(i).begin();
49       }
50     return i;
51   }
52
53 public:
54   explicit Timeout_iter(Timeout_q *t)
55   : _q(t), _i(0)
56   { rewind(); }
57
58   explicit Timeout_iter(Timeout_q *t, bool)
59   : _q(t), _c(t->first(0).end()), _i(0)
60   {}
61
62   void rewind()
63   {
64     _i = 0;
65     _c = _q->first(0).begin();
66     _i = skip_empty(&_c, _i);
67   }
68
69   Timeout_iter const &operator ++ ()
70   {
71     if (_c == _q->first(_i).end())
72       return *this;
73
74     ++_c;
75     _i = skip_empty(&_c, _i);
76
77     return *this;
78   }
79
80   Timeout *operator * () const { return *_c; }
81
82   bool operator == (Timeout_iter const &o) const
83   { return _c == o._c; }
84
85   bool operator != (Timeout_iter const &o) const
86   { return _c != o._c; }
87
88 private:
89   Timeout_q *_q;
90   To_iter _c;
91   int _i;
92 };
93
94 template< typename FWD_ITER >
95 class Rnd_container
96 {
97 public:
98   explicit Rnd_container(FWD_ITER const &b, FWD_ITER const &e)
99   : _b(b), _e(e), _cnt(0)
100   {
101     for (FWD_ITER i = b; i != e; ++i)
102       ++_cnt;
103   }
104
105   class Iterator : public FWD_ITER
106   {
107   public:
108     Iterator() {}
109
110     Iterator const &operator += (int offs)
111     {
112       if (offs < 0)
113         return operator -= (-offs);
114
115       if (offs == 0)
116         return *this;
117
118       for (; *this != _c->_e && offs > 0; --offs, ++_p)
119         this->operator ++ ();
120
121       return *this;
122     }
123
124     Iterator const &operator -= (int offs)
125     {
126       if (offs < 0)
127         return this->operator += (-offs);
128
129       if (offs == 0)
130         return *this;
131
132       int p = 0;
133
134       if (_p > (unsigned)offs)
135         p = _p - offs;
136
137       FWD_ITER i = _c->_b;
138
139       for (int z = 0; z < p && i != _c->_e; ++i, ++z)
140         ;
141
142       *this = Iterator(_c, p, i);
143       return *this;
144     }
145
146     Iterator const &operator -- ()
147     { return this->operator -= (1); }
148
149     int pos() const { return _p; }
150
151   private:
152     friend class Rnd_container;
153
154     Iterator(Rnd_container *c, unsigned long pos, FWD_ITER const &i)
155     : FWD_ITER(i), _c(c), _p(pos)
156     {}
157
158     Rnd_container *_c;
159     unsigned long _p;
160   };
161
162 public:
163   Iterator begin() { return Iterator(this, 0, _b); }
164   Iterator end() { return Iterator(this, _cnt, _e); }
165   unsigned long size() const { return _cnt; }
166   Iterator at(unsigned long pos)
167   {
168     if (pos >= _cnt)
169       return _e;
170
171     Iterator i = _b;
172     i += pos;
173     return i;
174   }
175
176 private:
177   FWD_ITER _b, _e;
178   unsigned long _cnt;
179 };
180
181 }
182
183
184 // available from the jdb_tcb module
185 extern int jdb_show_tcb(Thread *thread, int level) __attribute__((weak));
186
187 // use implicit knowledge to determine the type of a timeout because we
188 // cannot use dynamic_cast (we compile with -fno-rtti)
189 static
190 int
191 Jdb_list_timeouts::get_type(Timeout *t)
192 {
193   for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
194     if (t == timeslice_timeout.cpu(i))
195       return Timeout_timeslice;
196
197   // add others
198
199   // unknown
200   return 0;
201 }
202
203 static
204 Thread*
205 Jdb_list_timeouts::get_owner(Timeout *t)
206 {
207   switch (get_type(t))
208     {
209       case Timeout_timeslice:
210         return static_cast<Thread*>(Context::kernel_context(Cpu_number::first()));
211 #if 0
212         // XXX: current_sched does not work from the debugger
213         if (Context::current_sched())
214           return static_cast<Thread*>(Context::current_sched()->context());
215 #endif
216       default:
217         return 0;
218     }
219 }
220
221 static
222 void
223 Jdb_list_timeouts::show_header()
224 {
225   printf("%s  type           timeout    owner       name\033[m\033[K\n",
226          Jdb::esc_emph);
227 }
228
229 static
230 void
231 Jdb_list_timeouts::list_timeouts_show_timeout(Timeout *t)
232 {
233   char const *type;
234   char ownerstr[32] = "";
235   Thread *owner;
236   Signed64 timeout = t->get_timeout(Kip::k()->clock);
237
238   Kconsole::console()->getchar_chance();
239
240   switch (get_type(t))
241     {
242     case Timeout_timeslice:
243       type  = "timeslice";
244       owner = get_owner(t);
245       if (owner)
246         snprintf(ownerstr, sizeof(ownerstr), "  %p", owner);
247       else
248        strcpy(ownerstr, "destruct");
249       break;
250     default:
251       snprintf(ownerstr, sizeof(ownerstr), "  0x%lx", (Address)t);
252       type  = "unkn";
253       owner = 0;
254       break;
255     }
256
257   printf("  %-10s   ", type);
258   if (timeout < 0)
259     putstr("   over     ");
260   else
261     {
262       String_buf<12> time_str;
263       Jdb::write_ll_ns(&time_str, timeout * 1000, false);
264       time_str.terminate();
265       putstr(time_str.begin());
266     }
267
268   Jdb_kobject_name *nx = 0;
269
270   if (owner)
271     nx = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(owner);
272
273   printf(" %s  %s\033[K\n", ownerstr, nx ? nx->name() : "");
274 }
275
276 IMPLEMENT
277 Jdb_list_timeouts::Jdb_list_timeouts()
278   : Jdb_module("INFO")
279 {}
280
281 static
282 void
283 Jdb_list_timeouts::complete_show()
284 {
285   typedef Rnd_container<Timeout_iter> Cont;
286   typedef Cont::Iterator Iter;
287
288   Cont to_cont(Timeout_iter(&Timeout_q::timeout_queue.cpu(Cpu_number::first())),
289                Timeout_iter(&Timeout_q::timeout_queue.cpu(Cpu_number::first()), true));
290
291   show_header();
292   for (Iter i = to_cont.begin(); i != to_cont.end(); ++i)
293     list_timeouts_show_timeout(*i);
294 }
295
296 static
297 void
298 Jdb_list_timeouts::list()
299 {
300   unsigned y, y_max;
301
302   typedef Rnd_container<Timeout_iter> Cont;
303   typedef Cont::Iterator Iter;
304
305   Cont to_cont(Timeout_iter(&Timeout_q::timeout_queue.cpu(Cpu_number::first())),
306                Timeout_iter(&Timeout_q::timeout_queue.cpu(Cpu_number::first()), true));
307   Iter first = to_cont.begin();
308   Iter current = first;
309   Iter end = to_cont.end();
310   --end;
311
312   Jdb::clear_screen();
313   Jdb::cursor();
314   show_header();
315   for (;;)
316     {
317       y = current.pos();
318
319       for (bool resync=false; !resync; )
320         {
321           Jdb::cursor(2, 1);
322           y_max = 0;
323           // need to check for y_max > Jdb_screen::height()-3 here too
324           for (Iter i = current; i != to_cont.end(); ++i, ++y_max)
325             list_timeouts_show_timeout(*i);
326
327           for (unsigned i=y_max; i<Jdb_screen::height()-3; ++i)
328             putstr("\033[K\n");
329
330           Jdb::printf_statline("timouts", "<CR>=select owner", "_");
331
332           for (bool redraw=false; !redraw; )
333             {
334               Jdb::cursor(y+2, 1);
335               switch (int c=Jdb_core::getchar())
336                 {
337                 case KEY_CURSOR_UP:
338                   if (y > 0)
339                     y--;
340                   else
341                     {
342                       Iter i = current;
343                       --current;
344                       redraw = i != current;
345                     }
346                   break;
347                 case KEY_CURSOR_DOWN:
348                   if (y < y_max)
349                     y++;
350                   else
351                     {
352                       Iter i = current;
353                       ++current;
354
355                       if (current == to_cont.end())
356                         current = i;
357                       redraw = i != current;
358                     }
359                   break;
360                 case KEY_PAGE_UP:
361                     {
362                       Iter i = current;
363                       current -= Jdb_screen::height()-3;
364                       redraw =  i != current;
365                       if (!redraw)
366                         y = 0;
367                     }
368                   break;
369                 case KEY_PAGE_DOWN:
370                     {
371                       Iter i = current;
372                       current += Jdb_screen::height()-3;
373                       if (current == to_cont.end())
374                         current = end;
375                       redraw =  i != current;
376                       if (!redraw)
377                         y = y_max;
378                     }
379                   break;
380                 case KEY_CURSOR_HOME:
381                   redraw = current != first;
382                   current = first;
383                   y = 0;
384                   break;
385                 case KEY_CURSOR_END:
386                   redraw = current != end;
387                   current = end;
388                   y = y_max;
389                   break;
390                 case KEY_RETURN:
391                   if (jdb_show_tcb != 0)
392                     {
393                       Thread *owner;
394                       Iter i = current;
395                       i += y;
396                       if (i != to_cont.end() && (owner = get_owner(*i)))
397                         {
398                           if (!jdb_show_tcb(owner, 1))
399                             return;
400                           Jdb::cursor();
401                           show_header();
402                           redraw = 1;
403                         }
404                     }
405                   break;
406                 case KEY_ESC:
407                   Jdb::abort_command();
408                   return;
409                 default:
410                   if (Jdb::is_toplevel_cmd(c))
411                     return;
412                 }
413             }
414         }
415     }
416 }
417
418 PUBLIC
419 Jdb_module::Action_code
420 Jdb_list_timeouts::action(int cmd, void *&, char const *&, int &)
421 {
422   if (cmd == 0)
423     list();
424   else if (cmd == 1)
425     complete_show();
426
427   return NOTHING;
428 }
429
430 PUBLIC
431 Jdb_module::Cmd const *
432 Jdb_list_timeouts::cmds() const
433 {
434   static Cmd cs[] =
435     {
436         { 0, "lt", "timeouts", "", "lt\tshow enqueued timeouts", 0 },
437         { 1, "", "timeoutsdump", "", 0, 0 },
438     };
439
440   return cs;
441 }
442
443 PUBLIC
444 int
445 Jdb_list_timeouts::num_cmds() const
446 {
447   return 2;
448 }
449
450 static Jdb_list_timeouts jdb_list_timeouts INIT_PRIORITY(JDB_MODULE_INIT_PRIO);