diff --git a/assets/debugging/jsix.elf-gdb.py b/assets/debugging/jsix.elf-gdb.py index 23b1ec7..01e0164 100644 --- a/assets/debugging/jsix.elf-gdb.py +++ b/assets/debugging/jsix.elf-gdb.py @@ -26,6 +26,25 @@ class PrintStackCommand(gdb.Command): continue +def stack_walk(frame, depth): + for i in range(depth-1, -1, -1): + ret = gdb.parse_and_eval(f"*(uint64_t*)({frame:#x} + 0x8)") + + name = "" + try: + block = gdb.block_for_pc(int(ret)) + if block: + name = block.function or "" + except RuntimeError: + pass + + print("{:016x}: {:016x} {}".format(int(frame), int(ret), name)) + + frame = int(gdb.parse_and_eval(f"*(uint64_t*)({frame:#x})")) + if frame == 0 or ret == 0: + return + + class PrintBacktraceCommand(gdb.Command): def __init__(self): super().__init__("j6bt", gdb.COMMAND_DATA) @@ -43,22 +62,7 @@ class PrintBacktraceCommand(gdb.Command): if len(args) > 1: depth = int(gdb.parse_and_eval(args[1])) - for i in range(depth-1, -1, -1): - ret = gdb.parse_and_eval(f"*(uint64_t*)({frame:#x} + 0x8)") - - name = "" - try: - block = gdb.block_for_pc(int(ret)) - if block: - name = block.function or "" - except RuntimeError: - pass - - print("{:016x}: {:016x} {}".format(int(frame), int(ret), name)) - - frame = int(gdb.parse_and_eval(f"*(uint64_t*)({frame:#x})")) - if frame == 0 or ret == 0: - return + stack_walk(frame, depth) class TableWalkCommand(gdb.Command): @@ -128,10 +132,78 @@ class TableWalkCommand(gdb.Command): table = (entry & 0x7ffffffffffffe00) | 0xffffc00000000000 +class GetThreadsCommand(gdb.Command): + def __init__(self): + super().__init__("j6threads", gdb.COMMAND_DATA) + + def print_thread(self, addr): + if addr == 0: + print(" \n") + return + + tcb = f"((TCB*){addr:#x})" + thread = f"({tcb}->thread)" + stack = int(gdb.parse_and_eval(f"{tcb}->kernel_stack")) + rsp = int(gdb.parse_and_eval(f"{tcb}->rsp")) + pri = int(gdb.parse_and_eval(f"{tcb}->priority")) + koid = int(gdb.parse_and_eval(f"{thread}->m_koid")) + proc = int(gdb.parse_and_eval(f"{thread}->m_parent.m_koid")) + + creator = int(gdb.parse_and_eval(f"{thread}->m_creator")) + if creator != 0: + creator_koid = int(gdb.parse_and_eval(f"{thread}->m_creator->m_koid")) + creator = f"{creator_koid:x}" + else: + creator = "" + + print(f" Thread {proc:x}:{koid:x}") + print(f" creator: {creator}") + print(f" priority: {pri}") + print(f" kstack: {stack:#x}") + print(f" rsp: {rsp:#x}") + print("------------------------------------") + + if stack != 0: + rsp = int(gdb.parse_and_eval(f"{tcb}->rsp")) + stack_walk(rsp + 5*8, 5) + + print("") + + def print_thread_list(self, addr, name): + if addr == 0: + return + + print(f"=== {name} ===") + + while addr != 0: + self.print_thread(addr) + addr = int(gdb.parse_and_eval(f"((tcb_node*){addr:#x})->m_next")) + + + def invoke(self, arg, from_tty): + args = gdb.string_to_argv(arg) + if len(args) != 1: + raise RuntimeError("Usage: j6threads ") + + ncpu = int(args[0]) + runlist = f"scheduler::s_instance->m_run_queues.m_elements[{ncpu:#x}]" + + print("CURRENT:") + current = int(gdb.parse_and_eval(f"{runlist}.current")) + self.print_thread(current) + + for pri in range(8): + ready = int(gdb.parse_and_eval(f"{runlist}.ready[{pri:#x}].m_head")) + self.print_thread_list(ready, f"PRIORITY {pri}") + + blocked = int(gdb.parse_and_eval(f"{runlist}.blocked.m_head")) + self.print_thread_list(ready, "BLOCKED") PrintStackCommand() PrintBacktraceCommand() TableWalkCommand() +GetThreadsCommand() -gdb.execute("target remote :1234") gdb.execute("display/i $rip") +if not gdb.selected_inferior().was_attached: + gdb.execute("target remote :1234") diff --git a/src/kernel/cpu.cpp b/src/kernel/cpu.cpp index 64fb482..de8a574 100644 --- a/src/kernel/cpu.cpp +++ b/src/kernel/cpu.cpp @@ -9,7 +9,9 @@ #include "idt.h" #include "log.h" #include "msr.h" +#include "objects/thread.h" #include "objects/vm_area.h" +#include "scheduler.h" #include "syscall.h" #include "tss.h" @@ -60,10 +62,6 @@ cpu_early_init(cpu_data *cpu) // Install the GS base pointint to the cpu_data wrmsr(msr::ia32_gs_base, reinterpret_cast(cpu)); - - // Set the initial process as the kernel "process" - extern process &g_kernel_process; - cpu->process = &g_kernel_process; } void @@ -74,6 +72,18 @@ cpu_init(cpu_data *cpu, bool bsp) cpu_early_init(cpu); } + // Set the initial process as the kernel "process" + extern process &g_kernel_process; + cpu->process = &g_kernel_process; + + thread *idle = thread::create_idle_thread( + g_kernel_process, + scheduler::max_priority, + cpu->rsp0); + + cpu->thread = idle; + cpu->tcb = idle->tcb(); + // Set up the syscall MSRs syscall_enable(); diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index 70c3d56..f782e6a 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -24,12 +24,14 @@ thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) : { parent.space().initialize_tcb(m_tcb); m_tcb.priority = pri; + m_tcb.thread = this; if (!rsp0) setup_kernel_stack(); else m_tcb.rsp0 = rsp0; + m_creator = current_cpu().thread; m_self_handle = parent.add_handle(this); } @@ -38,14 +40,6 @@ thread::~thread() g_kernel_stacks.return_section(m_tcb.kernel_stack); } -thread * -thread::from_tcb(TCB *tcb) -{ - static ptrdiff_t offset = - -1 * static_cast(offsetof(thread, m_tcb)); - return reinterpret_cast(util::offset_pointer(tcb, offset)); -} - thread & thread::current() { return *current_cpu().thread; } inline void schedule_if_current(thread *t) { if (t == current_cpu().thread) scheduler::get().schedule(); } diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index 39fbcc1..a3ec55d 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -18,6 +18,9 @@ struct TCB uintptr_t rsp3; uintptr_t rflags3; uintptr_t pml4; + // End of area used by asembly + + thread* thread; uint8_t priority; // note: 3 bytes padding @@ -46,9 +49,6 @@ public: none = 0x00 }; - /// Get the pointer to the thread object containing this TCB - static thread * from_tcb(TCB *tcb); - /// Destructor virtual ~thread(); @@ -175,6 +175,7 @@ private: tcb_node m_tcb; process &m_parent; + thread *m_creator; state m_state; wait_type m_wait_type; diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 023e338..0d7e43a 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -97,16 +97,8 @@ scheduler::start() { util::scoped_lock lock {queue.lock}; - - process *kp = &process::kernel_process(); - thread *idle = thread::create_idle_thread(*kp, max_priority, cpu.rsp0); - - auto *tcb = idle->tcb(); - cpu.process = kp; - cpu.thread = idle; - cpu.tcb = tcb; - - queue.current = tcb; + thread *idle = cpu.thread; + queue.current = idle->tcb(); } cpu.apic->enable_timer(isr::isrTimer, false); @@ -130,7 +122,7 @@ void scheduler::prune(run_queue &queue, uint64_t now) // move them to the appropriate lists. auto *tcb = queue.blocked.front(); while (tcb) { - thread *th = thread::from_tcb(tcb); + thread *th = tcb->thread; uint8_t priority = tcb->priority; bool ready = th->has_state(thread::state::ready); @@ -171,7 +163,7 @@ scheduler::check_promotions(run_queue &queue, uint64_t now) { for (auto &pri_list : queue.ready) { for (auto *tcb : pri_list) { - const thread *th = thread::from_tcb(queue.current); + const thread *th = queue.current->thread; const bool constant = th->has_state(thread::state::constant); if (constant) continue; @@ -266,7 +258,7 @@ scheduler::schedule() queue.lock.acquire(&waiter); queue.current->time_left = remaining; - thread *th = thread::from_tcb(queue.current); + thread *th = queue.current->thread; uint8_t priority = queue.current->priority; const bool constant = th->has_state(thread::state::constant); @@ -313,7 +305,7 @@ scheduler::schedule() return; } - thread *next_thread = thread::from_tcb(next); + thread *next_thread = next->thread; cpu.thread = next_thread; cpu.process = &next_thread->parent();