]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/jdb_tcb.cpp
9d4146e21a152365eab12fe0e13cce91a6986137
[l4.git] / kernel / fiasco / src / jdb / jdb_tcb.cpp
1 INTERFACE:
2
3 #include "l4_types.h"
4
5 class Thread;
6
7
8 //-----------------------------------------------------------------
9 IMPLEMENTATION:
10
11 #include <cstdio>
12 #include <cstring>
13
14 #include "entry_frame.h"
15 #include "jdb.h"
16 #include "jdb_disasm.h"
17 #include "jdb_handler_queue.h"
18 #include "jdb_input.h"
19 #include "jdb_kobject.h"
20 #include "jdb_kobject_names.h"
21 #include "jdb_module.h"
22 #include "jdb_screen.h"
23 #include "jdb_thread.h"
24 #include "jdb_util.h"
25 #include "kernel_console.h"
26 #include "kernel_task.h"
27 #include "keycodes.h"
28 #include "l4_types.h"
29 #include "push_console.h"
30 #include "simpleio.h"
31 #include "static_init.h"
32 #include "task.h"
33 #include "thread_object.h"
34 #include "thread_state.h"
35 #include "types.h"
36
37 IMPLEMENTATION [32bit]:
38 #define ADDR_FMT "%08lx"
39
40 IMPLEMENTATION [64bit]:
41 #define ADDR_FMT "%016lx"
42
43
44 IMPLEMENTATION:
45
46 class Jdb_tcb_ptr
47 {
48 public:
49   Jdb_tcb_ptr(Address addr = 0)
50     : _base(addr & ~(Config::thread_block_size-1)),
51       _offs(addr &  (Config::thread_block_size-1))
52   {}
53
54   Jdb_tcb_ptr(Jdb_tcb_ptr const &p)
55     : _base(p.base()), _offs(p.offs())
56   {}
57
58   inline bool valid() const
59   { return _offs <= Config::thread_block_size-sizeof(Mword); }
60
61   bool operator > (int offs) const
62   {
63     return offs < 0 ? _offs > Config::thread_block_size + offs*sizeof(Mword)
64                     : _offs > offs*sizeof(Mword);
65   }
66
67   Jdb_tcb_ptr &operator += (int offs)
68   { _offs += offs*sizeof(Mword); return *this; }
69
70   inline Address addr() const
71   { return _base + _offs; }
72
73   inline Mword value() const
74   { return *(Mword*)(_base + _offs); }
75
76   inline void value(Mword v)
77   { *(Mword*)(_base + _offs) = v; }
78
79   inline bool is_user_value() const;
80
81   inline const char *user_value_desc() const;
82
83   inline Mword top_value(int offs) const
84   { return *((Mword*)(Cpu::stack_align(_base + Config::thread_block_size)) + offs); }
85
86   inline Address base() const
87   { return _base; }
88
89   inline Address offs() const
90   { return _offs; }
91
92   inline void offs(Address offs)
93   { _offs = offs; }
94
95   inline bool is_kern_code() const
96   { return (Address)&Mem_layout::image_start <= value()
97            && value() <= (Address)&Mem_layout::ecode;  };
98
99   inline bool is_kobject() const
100   { return Kobject_dbg::is_kobj(reinterpret_cast<void *>(value())); }
101
102 private:
103   Address  _base;
104   Address  _offs;
105 };
106
107 class Jdb_disasm_view
108 {
109 public:
110   unsigned _x, _y;
111 };
112
113
114 class Jdb_stack_view
115 {
116 public:
117   bool is_current;
118   Jdb_entry_frame *ef;
119   Jdb_tcb_ptr current;
120   unsigned start_y;
121   Address absy;
122   Address addy, addx;
123   bool memdump_is_colored;
124
125   bool edit_registers();
126 };
127
128
129 class Jdb_tcb : public Jdb_module, public Jdb_kobject_handler
130 {
131   static Kobject *threadid;
132   static Address address;
133   static char    first_char;
134   static char    auto_tcb;
135
136 private:
137   static void print_return_frame_regs(Jdb_tcb_ptr const &current, Mword ksp);
138   static void print_entry_frame_regs(Space *task);
139   static void info_thread_state(Thread *t);
140
141   static Jdb_disasm_view _disasm_view;
142   static Jdb_stack_view  _stack_view;
143 };
144
145
146
147 Kobject *Jdb_tcb::threadid;
148 Address Jdb_tcb::address;
149 char    Jdb_tcb::first_char;
150 char    Jdb_tcb::auto_tcb;
151 Jdb_disasm_view Jdb_tcb::_disasm_view(Jdb_tcb::Disasm_x, Jdb_tcb::Disasm_y);
152 Jdb_stack_view  Jdb_tcb::_stack_view (Jdb_tcb::Stack_y);
153
154
155 // available from jdb_dump module
156 extern int jdb_dump_addr_task (Address addr, Space *task, int level)
157   __attribute__((weak));
158
159 PUBLIC
160 Jdb_stack_view::Jdb_stack_view(unsigned y)
161 : start_y(y), absy(0), memdump_is_colored(true)
162 {}
163
164 PUBLIC static inline
165 Mword
166 Jdb_stack_view::cols()
167 {
168   return Jdb_screen::cols() - 1;
169 }
170
171 PUBLIC static inline
172 Mword
173 Jdb_stack_view::bytes_per_line()
174 { return cols() * sizeof(Mword); }
175
176 PUBLIC
177 void
178 Jdb_stack_view::init(Address ksp, Jdb_entry_frame *_ef, bool _is_current)
179 {
180   current = Jdb_tcb_ptr(ksp);
181
182   absy = current.offs() / bytes_per_line();
183   addx = (current.offs() % bytes_per_line()) / sizeof(Mword);
184   addy = 0;
185   ef = _ef;
186   is_current = _is_current;
187 }
188
189 PUBLIC
190 void
191 Jdb_stack_view::print_value(Jdb_tcb_ptr const &p, bool highl = false)
192 {
193   if (!p.valid() || !Jdb_util::is_mapped((void const*)p.addr()))
194     {
195       printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped);
196       return;
197     }
198
199   const char *s1="", *s2="";
200   if (highl)
201     {
202       s1 = Jdb::esc_emph;
203       s2 = JDB_ANSI_END;
204     }
205   else if (p.is_user_value())
206     {
207       s1 = Jdb::esc_iret;
208       s2 = JDB_ANSI_END;
209     }
210   else if (memdump_is_colored)
211     {
212       if (p.is_kern_code())
213         {
214           s1 = JDB_ANSI_COLOR(lightblue);
215           s2 = JDB_ANSI_END;
216         }
217       else if (p.is_kobject())
218         {
219           s1 = JDB_ANSI_COLOR(lightgreen);
220           s2 = JDB_ANSI_END;
221         }
222       /* else if (p.in_backtrace(...
223          {
224          s1 = Jdb::esc_bt;
225          s2 = "\033[m";
226          } */
227     }
228
229   printf(" %s"ADDR_FMT"%s", s1, p.value(), s2);
230 }
231
232
233 PUBLIC
234 void
235 Jdb_stack_view::dump()//Jdb_tcb_ptr const &current)
236 {
237   Jdb_tcb_ptr p = current;
238   p.offs(absy * bytes_per_line());
239
240   Jdb::cursor(start_y, 1);
241
242   for (unsigned y = 0; y < Jdb_screen::height() - start_y; ++y)
243     {
244       Kconsole::console()->getchar_chance();
245
246       if (p.valid())
247         {
248           printf("    %03lx ", p.addr() & 0xfff);
249           for (unsigned x = 0; x < cols(); ++x, p+=1)
250             print_value(p);
251           putchar('\n');
252         }
253       else
254         puts("\033[K");
255     }
256 }
257
258 PRIVATE inline
259 unsigned
260 Jdb_stack_view::posx()
261 { return addx * (Jdb_screen::Mword_size_bmode + 1) + 9; }
262
263 PRIVATE inline
264 unsigned
265 Jdb_stack_view::posy()
266 { return addy + start_y; }
267
268 PUBLIC
269 void
270 Jdb_stack_view::highlight(bool highl)
271 {
272   current.offs(absy*bytes_per_line() + addy*bytes_per_line() + addx * sizeof(Mword));
273   Jdb_tcb_ptr first_col = current;
274   first_col.offs(absy*bytes_per_line() + addy*bytes_per_line());
275
276   if (!current.valid())
277     return;
278
279   Jdb::cursor(posy(), 1);
280   if (highl)
281     printf("%08lx", current.addr() & 0xffffffff);
282   else
283     printf("    %03lx ", first_col.addr() & 0xfff);
284   Jdb::cursor(posy(), posx());
285   print_value(current, highl);
286
287   char kobj_desc[120];
288   kobj_desc[0] = 0;
289
290   if (current.is_kern_code())
291     strcpy(kobj_desc, "Kernel code"); // todo: print kernel function name
292   else if (current.is_user_value())
293     snprintf(kobj_desc, sizeof(kobj_desc), "Return frame: %s",
294              current.user_value_desc());
295   else
296     if (Kobject *o = Kobject::pointer_to_obj(reinterpret_cast<void *>(current.value())))
297       {
298         Jdb_kobject::obj_description(kobj_desc, sizeof(kobj_desc), true, o);
299         kobj_desc[sizeof(kobj_desc) - 1] = 0;
300       }
301
302   Jdb::printf_statline("tcb", "<CR>=dump <Space>=Disas",
303                        "%s", kobj_desc);
304 }
305
306 PUBLIC
307 bool
308 Jdb_stack_view::handle_key(int key, bool *redraw)
309 {
310   Mword   lines    = Jdb_screen::height() - start_y;
311   Mword   max_lines = (Config::thread_block_size + bytes_per_line() - 1)/bytes_per_line();
312   Address max_absy = max_lines - lines;
313
314   if (lines > max_lines)
315     max_absy = 0;
316
317   if (lines > max_lines - absy)
318     lines = max_lines - absy;
319
320   if (key == 'e')
321     edit_stack(redraw);
322   else
323     return Jdb::std_cursor_key(key, this->cols(), lines, max_absy,
324       &absy, &addy, &addx, redraw);
325
326   return true;
327 }
328
329 PUBLIC
330 void
331 Jdb_stack_view::edit_stack(bool *redraw)
332 {
333   if (current.valid())
334     {
335       Mword value;
336       int c;
337
338       Jdb::cursor(posy(), posx());
339       printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_blank);
340       Jdb::printf_statline("tcb",
341           is_current ? "<Space>=edit registers" : 0,
342           "edit <"ADDR_FMT"> = "ADDR_FMT,
343           current.addr(), current.value());
344
345       Jdb::cursor(posy(), posx() + 1);
346       c = Jdb_core::getchar();
347
348       if (c==KEY_ESC)
349         {
350           *redraw = true;
351           return;
352         }
353
354       if (c != ' ' || !is_current)
355         {
356           // edit memory
357           putchar(c);
358           Jdb::printf_statline("tcb", 0, "edit <"ADDR_FMT"> = "ADDR_FMT,
359               current.addr(), current.value());
360           Jdb::cursor(posy(), posx() + 1);
361           if (!Jdb_input::get_mword(&value, c, 16))
362             {
363               Jdb::cursor(posy(), posx());
364               print_value(current);
365               return;
366             }
367           else
368             current.value(value);
369         }
370       else
371         {
372           // edit registers
373           Jdb::cursor(posy(), posx());
374           print_value(current);
375           edit_registers();
376           return;
377         }
378       *redraw = true;
379     }
380 }
381
382 PUBLIC
383 Jdb_disasm_view::Jdb_disasm_view(unsigned x, unsigned y)
384 : _x(x), _y(y)
385 {}
386
387 PUBLIC
388 void
389 Jdb_disasm_view::show(Jdb_tcb_ptr const &p, Space *s)
390 {
391   if (!Jdb_disasm::avail())
392     return;
393
394   Address disass_addr = p.top_value(-5);
395   Jdb::cursor(_y, _x);
396   putstr(Jdb::esc_emph);
397   Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
398   putstr("\033[m");
399   Jdb::cursor(_y + 1, _x);
400   Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s);
401 }
402
403
404 PUBLIC
405 Jdb_tcb::Jdb_tcb()
406   : Jdb_module("INFO"), Jdb_kobject_handler(Thread_object::static_kobj_type)
407 {
408   static Jdb_handler enter(at_jdb_enter);
409
410   Jdb::jdb_enter.add(&enter);
411   Jdb_kobject::module()->register_handler(this);
412 }
413
414 static void
415 Jdb_tcb::at_jdb_enter()
416 {
417   if (auto_tcb)
418     {
419       // clear any keystrokes in queue
420       Jdb::set_next_cmd(0);
421       Jdb::push_cons()->push('t');
422       Jdb::push_cons()->push(' ');
423     }
424 }
425
426
427 PUBLIC virtual
428 Kobject *
429 Jdb_tcb::parent(Kobject *o)
430 {
431   Thread *t = Kobject::dcast<Thread_object*>(o);
432   if (!t)
433     return 0;
434
435   return static_cast<Task*>(t->space());
436 }
437
438 PRIVATE static inline
439 char *
440 Jdb_tcb::vcpu_state_str(Mword state, char *s, int len)
441 {
442   snprintf(s, len, "%c%c%c%c%c%c",
443            (state & Vcpu_state::F_fpu_enabled) ? 'F' : 'f',
444            (state & Vcpu_state::F_user_mode)   ? 'U' : 'u',
445            (state & Vcpu_state::F_debug_exc)   ? 'D' : 'd',
446            (state & Vcpu_state::F_exceptions)  ? 'E' : 'e',
447            (state & Vcpu_state::F_page_faults) ? 'P' : 'p',
448            (state & Vcpu_state::F_irqs)        ? 'I' : 'i');
449   s[len - 1] = 0;
450   return s;
451 }
452
453 PUBLIC static
454 Jdb_module::Action_code
455 Jdb_tcb::show(Thread *t, int level)
456 {
457 new_tcb:
458
459   Thread *t_current      = Jdb::get_current_active();
460   bool is_current_thread;
461   bool redraw_screen     = true;
462   Jdb_entry_frame *ef    = Jdb::get_entry_frame(Jdb::current_cpu);
463 #if 0
464   Address bt_start       = 0;
465 #endif
466
467   if (!t && !t_current)
468     {
469 #if 0
470       const Mword mask
471         = (Config::thread_block_size * Mem_layout::max_threads()) - 1;
472       const Mword tsksz = Config::thread_block_size*L4_uid::threads_per_task();
473       LThread_num task = ((Address)Jdb::get_thread() & mask) / tsksz;
474 #endif
475 #if 0
476       putchar('\n');
477       print_entry_frame_regs(0);
478 #endif
479       return NOTHING;
480     }
481
482   if (!t)
483     t = t_current;
484
485   is_current_thread = t == t_current;
486
487 #if 0
488   if (!t->is_valid())
489     {
490       puts(" Invalid thread");
491       return NOTHING;
492     }
493 #endif
494
495   if (level==0)
496     {
497       Jdb::clear_screen(Jdb::FANCY);
498       redraw_screen = false;
499     }
500
501 whole_screen:
502
503   if (redraw_screen)
504     {
505       Jdb::clear_screen(Jdb::NOFANCY);
506       redraw_screen = false;
507     }
508
509   char time_str[12];
510
511   putstr("thread: ");
512   Jdb_kobject::print_uid(t->kobject(), 3);
513   print_thread_uid_raw(t);
514   printf("CPU %3u ", t->cpu());
515
516   printf("\tprio: %02x  mode: %s\n",
517          t->sched()->prio(),
518          t->mode() & Context::Periodic  ?
519          t->mode() & Context::Nonstrict ? "Per (IRT)" : "Per (SP)" : "Con");
520
521   printf("state: %03lx ", t->state());
522   t->print_state_long();
523
524   putstr("\n\nwait for: ");
525   if (!t->partner())
526     putstr("--- ");
527   else
528     Jdb_thread::print_partner(t, 4);
529
530   putstr("   polling: ");
531   Jdb_thread::print_snd_partner(t, 3);
532
533   putstr("\trcv descr: ");
534
535   if (t->state() & Thread_ipc_receiving_mask)
536     printf("%08lx", t->rcv_regs()->from_spec());
537   else
538     putstr("        ");
539
540   putstr("\n"
541          "lcked by: ");
542   if (t->thread_lock()->lock_owner())
543     Jdb_kobject::print_uid(Thread::lookup(t->thread_lock()->lock_owner())->kobject(), 3);
544
545   putstr("\t\t\ttimeout  : ");
546   if (t->_timeout && t->_timeout->is_set())
547     {
548       Signed64 diff = (t->_timeout->get_timeout(Kip::k()->clock)) * 1000;
549       if (diff < 0)
550         strcpy(time_str, "over");
551       else
552         Jdb::write_ll_ns(diff, time_str,
553                          11 < sizeof(time_str)-1 ? 11 : sizeof(time_str)-1,
554                          false);
555       printf("%-13s", time_str);
556     }
557
558   putstr("\ncpu time: ");
559   Jdb::write_ll_ns(t->consumed_time()*1000, time_str,
560                    11 < sizeof(time_str) ? 11 : sizeof(time_str), false);
561   printf("%-13s", time_str);
562
563   printf("\t\ttimeslice: %llu/%llu %cs\n"
564          "pager\t: ",
565          t->sched()->left(), t->sched()->quantum(), Config::char_micro);
566   print_kobject(t, t->_pager.raw());
567
568   putstr("\ttask: ");
569   if (t->space() == Kernel_task::kernel_task())
570     putstr(" kernel        ");
571   else
572     print_kobject(static_cast<Task*>(t->space()));
573
574   putstr("\tutcb: ");
575   printf("%08lx", (Mword)t->utcb());
576
577   putstr("\nexc-hndl: ");
578   print_kobject(t, t->_exc_handler.raw());
579
580 #if 0
581   putstr("\tready  lnk: ");
582   if (t->state() & Thread_ready)
583     {
584       if (t->_ready_next)
585         Jdb_kobject::print_uid(Thread::lookup(t->_ready_next), 3);
586       else if (is_current_thread)
587         putstr(" ???.??");
588       else
589         putstr("\033[31;1m???.??\033[m");
590       if (t->_ready_prev)
591         Jdb_kobject::print_uid(Thread::lookup(t->_ready_prev), 4);
592       else if (is_current_thread)
593         putstr(" ???.??");
594       else
595         putstr(" \033[31;1m???.??\033[m");
596       putchar('\n');
597     }
598   else
599     puts("--- ---");
600 #endif
601
602   putstr("\tprsent lnk: ");
603   if (t->Present_list_item::next())
604     Jdb_kobject::print_uid(static_cast<Thread*>(t->Present_list_item::next())->kobject(), 3);
605   else
606     putstr("--- ");
607   if (t->Present_list_item::prev())
608     Jdb_kobject::print_uid(static_cast<Thread*>(t->Present_list_item::prev())->kobject(), 4);
609   else
610     putstr("--- ");
611   putchar('\n');
612
613   putstr("vCPU  st: ");
614   if (t->state() & Thread_vcpu_enabled)
615     {
616       char st1[7];
617       char st2[7];
618       printf("c=%s s=%s sf=%c e-ip=%08lx e-sp=%08lx S=",
619              vcpu_state_str(t->vcpu_state()->state, st1, sizeof(st1)),
620              vcpu_state_str(t->vcpu_state()->_saved_state, st2, sizeof(st2)),
621              (t->vcpu_state()->sticky_flags & Vcpu_state::Sf_irq_pending) ? 'P' : '-',
622              t->vcpu_state()->_entry_ip, t->vcpu_state()->_entry_sp);
623       print_kobject(static_cast<Task*>(t->vcpu_user_space()));
624     }
625   else
626     putstr("---");
627   putchar('\n');
628
629   Address ksp  = is_current_thread ? ef->ksp()
630                                    : (Address)t->get_kernel_sp();
631
632 #if 0
633   Address tcb  = (Address)context_of((void*)ksp);
634 #endif
635   _stack_view.init(ksp, ef, is_current_thread);
636
637   if (is_current_thread)
638     print_entry_frame_regs(t->space());
639
640   else if (t->space() != Kernel_task::kernel_task())
641     {
642       Jdb::cursor(11, 1);
643       info_thread_state(t);
644       putchar('\n');
645       print_return_frame_regs(_stack_view.current, ksp);
646
647       _disasm_view.show(_stack_view.current, t->space());
648     }
649   else
650     {
651       // kernel thread
652       Jdb::cursor(15, 1);
653       printf("kernel SP="ADDR_FMT, ksp);
654     }
655
656 dump_stack:
657
658   // dump the stack from ksp bottom right to tcb_top
659   _stack_view.dump();
660
661   for (bool redraw=false; ; )
662     {
663       _stack_view.highlight(true);
664       int c=Jdb_core::getchar();
665       _stack_view.highlight(false);
666       Jdb::cursor(Jdb_screen::height(), 6);
667
668       if (c == KEY_CURSOR_HOME && level > 0)
669         return GO_BACK;
670
671       if (!_stack_view.handle_key(c, &redraw))
672         {
673           switch (c)
674             {
675             case KEY_RETURN:
676               if (jdb_dump_addr_task && _stack_view.current.valid())
677                 {
678                   if (!jdb_dump_addr_task(_stack_view.current.value(),
679                         _stack_view.current.is_user_value() ? t->space() : 0, level+1))
680                     return NOTHING;
681                   redraw_screen = true;
682                 }
683               break;
684             case KEY_TAB:
685               //bt_start = search_bt_start(tcb, (Mword*)ksp, is_current_thread);
686               redraw = true;
687               break;
688             case ' ':
689               if (Jdb_disasm::avail() && _stack_view.current.valid())
690                 {
691                   printf("V %lx\n", _stack_view.current.value());
692                   if (!Jdb_disasm::show(_stack_view.current.value(),
693                         _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
694                     return NOTHING;
695                   redraw_screen = true;
696                 }
697               break;
698             case 'u':
699               if (Jdb_disasm::avail() && _stack_view.current.valid())
700                 {
701                   Jdb::printf_statline("tcb", "<CR>=disassemble here",
702                                         "u[address=%08lx task=%lx] ",
703                                         _stack_view.current.value(),
704                                         Kobject_dbg::pointer_to_id(t->space()));
705                   int c1 = Jdb_core::getchar();
706                   if ((c1 != KEY_RETURN) && (c1 != ' '))
707                     {
708                       Jdb::printf_statline("tcb", 0, "u");
709                       Jdb::execute_command("u", c1);
710                       return NOTHING;
711                     }
712
713                   if (!Jdb_disasm::show(_stack_view.current.value(),
714                         _stack_view.current.is_user_value() ? t->space() : 0, level+1, true))
715                     return NOTHING;
716                   redraw_screen = true;
717                 }
718               break;
719 #if 0
720             case 'r': // ready-list
721               putstr("[n]ext/[p]revious in ready list?");
722               switch (Jdb_core::getchar())
723                 {
724                 case 'n':
725                   if (t->_ready_next)
726                     {
727                       t = static_cast<Thread*>(t->_ready_next);
728                       goto new_tcb;
729                     }
730                   break;
731                 case 'p':
732                   if (t->_ready_prev)
733                     {
734                       t = static_cast<Thread*>(t->_ready_prev);
735                       goto new_tcb;
736                     }
737                   break;
738                 }
739               break;
740 #endif
741             case 'p': // present-list or show_pages
742               putstr("[n]ext/[p]revious in present list?");
743               switch (c=Jdb_core::getchar()) 
744                 {
745                 case 'n':
746                   if (t->Present_list_item::next())
747                     {
748                       t = static_cast<Thread*>(t->Present_list_item::next());
749                       goto new_tcb;
750                     }
751                   break;
752                 case 'p':
753                   if (t->Present_list_item::prev())
754                     {
755                       t = static_cast<Thread*>(t->Present_list_item::prev());
756                       goto new_tcb;
757                     }
758                   break;
759                 default:
760                   Jdb::execute_command("p", c);
761                   return NOTHING;
762                 }
763               break;
764             case 'C':
765               _stack_view.memdump_is_colored = !_stack_view.memdump_is_colored;
766               redraw = true;
767               break;
768             case KEY_ESC:
769               Jdb::abort_command();
770               return NOTHING;
771             default:
772               if (Jdb::is_toplevel_cmd(c))
773                 return NOTHING;
774               break;
775             }
776         }
777       if (redraw_screen)
778         goto whole_screen;
779       if (redraw)
780         goto dump_stack;
781     }
782
783
784 /* --- original L4 screen ------------------------------------------------------
785 thread: 0081 (001.01) <00020401 00080000>                               prio: 10
786 state : 85, ready                            lists: 81                   mcp: ff
787
788 wait for: --                             rcv descr: 00000000   partner: 00000000
789 sndq    : 0081 0081                       timeouts: 00000000   waddr0/1: 000/000
790 cpu time: 0000000000 timeslice: 01/0a
791
792 pager   : --                            prsent lnk: 0080 0080
793 ipreempt: --                            ready link : 0080 0080
794 xpreempt: --
795                                         soon wakeup lnk: 
796 EAX=00202dfe  ESI=00020401  DS=0008     late wakeup lnk: 
797 EBX=00000028  EDI=00080000  ES=0008
798 ECX=00000003  EBP=e0020400
799 EDX=00000001  ESP=e00207b4
800
801 700:
802 720:
803 740:
804 760:
805 780:
806 7a0:                                                  0000897b 00000020 00240082
807 7c0:  00000000 00000000 00000000 00000000    00000000 00000000 00000000 00000000
808 7e0:  00000000 00000000 ffffff80 00000000    0000001b 00003200 00000000 00000013
809 L4KD: 
810 ------------------------------------------------------------------------------*/
811
812 PUBLIC
813 Jdb_module::Action_code
814 Jdb_tcb::action(int cmd, void *&args, char const *&fmt, int &next_char)
815 {
816   static Address tcb_addr = 0;
817   if (cmd == 0)
818     {
819       if (args == &first_char)
820         {
821           switch (first_char)
822             {
823               case '+':
824               case '-':
825                 printf("%c\n", first_char);
826                 auto_tcb = first_char == '+';
827                 break;
828               case '?':
829                 args      = &address;
830                 fmt       = " addr="ADDR_FMT" => ";
831                 putchar(first_char);
832                 return Jdb_module::EXTRA_INPUT;
833               case 'a':
834                 args      = &tcb_addr;
835                 fmt       = " tcb=%x => ";
836                 putchar(first_char);
837                 return Jdb_module::EXTRA_INPUT;
838               case KEY_RETURN:
839                 show(0, 0);
840                 return NOTHING;
841               default:
842                 args      = &threadid;
843                 fmt       = "%q";
844                 next_char = first_char;
845                 return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR;
846             }
847         }
848       else if (args == &address)
849         {
850           address &= ~(Config::thread_block_size-1);
851           Jdb_kobject::print_uid(reinterpret_cast<Thread*>(address)->kobject(), 3);
852           putchar('\n');
853         }
854       else if (args == &tcb_addr)
855         show((Thread*)tcb_addr, 0);
856       else
857         {
858           Thread *t = Kobject::dcast<Thread_object *>(threadid);
859           if (t)
860             show(t, 0);
861           else
862             printf("\nNot a thread\n");
863         }
864     }
865
866   return NOTHING;
867 }
868
869 PUBLIC
870 Kobject *
871 Jdb_tcb::follow_link(Kobject *o)
872 {
873   Thread *t = Kobject::dcast<Thread_object *>(o);
874   if (t->space() == Kernel_task::kernel_task())
875     return o;
876   return static_cast<Kobject*>(static_cast<Task*>(t->space()));
877 }
878
879 PUBLIC
880 bool
881 Jdb_tcb::show_kobject(Kobject *o, int level)
882 {
883   Thread *t = Kobject::dcast<Thread_object *>(o);
884   return show(t, level);
885 }
886
887 PUBLIC
888 int
889 Jdb_tcb::show_kobject_short(char *buf, int max, Kobject *o)
890 {
891   Thread *t = Kobject::dcast<Thread_object *>(o);
892   Thread *cur_t = Jdb::get_current_active();
893   int cnt = 0;
894   if (t->space() == Kernel_task::kernel_task())
895     {
896       cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu());
897       max -= cnt;
898       buf += cnt;
899     }
900   if (t->space() == Kernel_task::kernel_task())
901     return cnt + snprintf(buf, max, " R=%ld%s", t->ref_cnt(),
902                           cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
903
904   return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s", t->cpu(),
905                         Kobject_dbg::pointer_to_id(t->space()),
906                         t->ref_cnt(),
907                         cur_t == t ? " "JDB_ANSI_COLOR(green)"current"JDB_ANSI_END : "");
908 }
909
910 PUBLIC
911 char const *
912 Jdb_tcb::kobject_type() const
913 {
914   return JDB_ANSI_COLOR(green) "Thread" JDB_ANSI_COLOR(default);
915 }
916
917 PUBLIC
918 Jdb_module::Cmd const *
919 Jdb_tcb::cmds() const
920 {
921   static Cmd cs[] =
922     {
923         { 0, "t", "tcb", "%C",
924           "t[<threadid>]\tshow current/given thread control block (TCB)\n"
925           "t{+|-}\tshow current thread control block at Jdb every entry\n",
926           &first_char },
927     };
928   return cs;
929 }
930
931 PUBLIC
932 int
933 Jdb_tcb::num_cmds() const
934 { return 1; }
935
936 static Jdb_tcb jdb_tcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
937
938 int
939 jdb_show_tcb(Thread *t, int level)
940 { return Jdb_tcb::show(t, level); }
941
942 static inline
943 void
944 Jdb_tcb::print_thread_uid_raw(Thread *t)
945 {
946   printf(" <%p> ", t);
947 }
948
949 PRIVATE static
950 void
951 Jdb_tcb::print_kobject(Mword n)
952 {
953   printf("[C:%4lx]       ", n);
954 }
955
956 PRIVATE static
957 void
958 Jdb_tcb::print_kobject(Kobject *o)
959 {
960   printf("D:%4lx         ", o ? o->dbg_id() : 0);
961 }
962
963 PRIVATE static
964 void
965 Jdb_tcb::print_kobject(Thread *t, Mword capidx)
966 {
967   Space *space = t->space();
968   if (!space)
969     {
970       print_kobject(capidx);
971       return;
972     }
973
974   Obj_space::Capability *c = space->obj_space()->get_cap(capidx);
975   if (!c || !c->valid())
976     {
977       print_kobject(capidx);
978       return;
979     }
980
981   printf("[C:%4lx] D:%4lx", capidx, c->obj()->dbg_info()->dbg_id());
982 }
983
984 //
985 //-----------------------------------------------------------------------------
986 // prompt extension for thread names
987 class Jdb_thread_name_ext : public Jdb_prompt_ext
988 {
989 public:
990   void ext();
991   void update();
992 };
993
994 IMPLEMENT
995 void
996 Jdb_thread_name_ext::ext()
997 {
998   if (Jdb::get_current_active())
999     {
1000       Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension<Jdb_kobject_name>(Jdb::get_current_active()->kobject());
1001       if (nx && nx->name()[0])
1002         printf("[%*.*s] ", nx->max_len(), nx->max_len(), nx->name());
1003     }
1004 }
1005
1006 IMPLEMENT
1007 void
1008 Jdb_thread_name_ext::update()
1009 {
1010   Jdb::get_current(Jdb::current_cpu);
1011 }
1012
1013 static Jdb_thread_name_ext jdb_thread_name_ext INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
1014