mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[kernel] Add debug names to processes
To make debugging easier, add names to processes. These are arbitrary and supplied by the caller of process_create. The max is 31 characters in debug configuration, and 0 in release.
This commit is contained in:
@@ -12,7 +12,9 @@ object process : object {
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Create a new empty process
|
# Create a new empty process
|
||||||
method create [constructor]
|
method create [constructor] {
|
||||||
|
param name string
|
||||||
|
}
|
||||||
|
|
||||||
# Stop all threads and exit the given process
|
# Stop all threads and exit the given process
|
||||||
method kill [destructor cap:kill]
|
method kill [destructor cap:kill]
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ load_init_server(bootproto::program &program, uintptr_t modules_address)
|
|||||||
using bootproto::section_flags;
|
using bootproto::section_flags;
|
||||||
using obj::vm_flags;
|
using obj::vm_flags;
|
||||||
|
|
||||||
obj::process *p = new obj::process;
|
obj::process *p = new obj::process {"srv.init"};
|
||||||
|
|
||||||
j6_handle_t sys_handle =
|
j6_handle_t sys_handle =
|
||||||
g_cap_table.create(&obj::system::get(), obj::system::init_caps);
|
g_cap_table.create(&obj::system::get(), obj::system::init_caps);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <j6/memutils.h>
|
||||||
#include <util/no_construct.h>
|
#include <util/no_construct.h>
|
||||||
|
|
||||||
#include "kassert.h"
|
#include "kassert.h"
|
||||||
@@ -18,10 +19,18 @@ obj::process &g_kernel_process = __g_kernel_process_storage.value;
|
|||||||
|
|
||||||
namespace obj {
|
namespace obj {
|
||||||
|
|
||||||
process::process() :
|
process::process(const char *name) :
|
||||||
kobject {kobject::type::process},
|
kobject {kobject::type::process},
|
||||||
m_state {state::running}
|
m_state {state::running}
|
||||||
{
|
{
|
||||||
|
if constexpr(__use_process_names) {
|
||||||
|
memset(m_name, 0, sizeof(m_name));
|
||||||
|
if (name) {
|
||||||
|
static constexpr size_t charlen = sizeof(m_name) - 1;
|
||||||
|
for (size_t i = 0; i < charlen && name[i]; ++i)
|
||||||
|
m_name[i] = name[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The "kernel process"-only constructor
|
// The "kernel process"-only constructor
|
||||||
@@ -30,6 +39,11 @@ process::process(page_table *kpml4) :
|
|||||||
m_space {kpml4},
|
m_space {kpml4},
|
||||||
m_state {state::running}
|
m_state {state::running}
|
||||||
{
|
{
|
||||||
|
if constexpr(__use_process_names) {
|
||||||
|
static constexpr char kernel[] = "KERNEL";
|
||||||
|
memcpy(m_name, kernel, sizeof(kernel));
|
||||||
|
memset(m_name + sizeof(kernel), 0, sizeof(m_name) - sizeof(kernel));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
process::~process()
|
process::~process()
|
||||||
|
|||||||
@@ -13,6 +13,14 @@
|
|||||||
|
|
||||||
namespace obj {
|
namespace obj {
|
||||||
|
|
||||||
|
static constexpr bool __use_process_names =
|
||||||
|
#ifdef __jsix_config_debug
|
||||||
|
true;
|
||||||
|
#else
|
||||||
|
false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class process :
|
class process :
|
||||||
public kobject
|
public kobject
|
||||||
{
|
{
|
||||||
@@ -32,7 +40,7 @@ public:
|
|||||||
static constexpr kobject::type type = kobject::type::process;
|
static constexpr kobject::type type = kobject::type::process;
|
||||||
|
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
process();
|
process(const char *name);
|
||||||
|
|
||||||
/// Destructor.
|
/// Destructor.
|
||||||
virtual ~process();
|
virtual ~process();
|
||||||
@@ -47,6 +55,9 @@ public:
|
|||||||
/// Get the process' virtual memory space
|
/// Get the process' virtual memory space
|
||||||
vm_space & space() { return m_space; }
|
vm_space & space() { return m_space; }
|
||||||
|
|
||||||
|
/// Get the debugging name of the process
|
||||||
|
const char *name() { if constexpr(__use_process_names) return m_name; else return nullptr; }
|
||||||
|
|
||||||
/// Create a new thread in this process
|
/// Create a new thread in this process
|
||||||
/// \args rsp3 If non-zero, sets the ring3 stack pointer to this value
|
/// \args rsp3 If non-zero, sets the ring3 stack pointer to this value
|
||||||
/// \args priority The new thread's scheduling priority
|
/// \args priority The new thread's scheduling priority
|
||||||
@@ -107,6 +118,15 @@ private:
|
|||||||
|
|
||||||
enum class state : uint8_t { running, exited };
|
enum class state : uint8_t { running, exited };
|
||||||
state m_state;
|
state m_state;
|
||||||
|
|
||||||
|
static constexpr size_t max_name_len =
|
||||||
|
#ifdef __jsix_config_debug
|
||||||
|
32;
|
||||||
|
#else
|
||||||
|
0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char m_name[max_name_len];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace obj
|
} // namespace obj
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "kernel.dir/memory.h"
|
||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
#include "objects/thread.h"
|
#include "objects/thread.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
@@ -9,6 +10,44 @@
|
|||||||
|
|
||||||
namespace panicking {
|
namespace panicking {
|
||||||
|
|
||||||
|
template <typename T> inline bool
|
||||||
|
check_pointer(T p)
|
||||||
|
{
|
||||||
|
static constexpr uint64_t large_flag = (1<<7);
|
||||||
|
static constexpr uint64_t pointer_mask = 0x0000fffffffff000;
|
||||||
|
static constexpr uintptr_t canon_mask = 0xffff800000000000;
|
||||||
|
|
||||||
|
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
|
||||||
|
|
||||||
|
uintptr_t canon_bits = addr & canon_mask;
|
||||||
|
if (canon_bits && canon_bits != canon_mask)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uintptr_t pml4 = 0;
|
||||||
|
asm volatile ( "mov %%cr3, %0" : "=r" (pml4) );
|
||||||
|
pml4 += mem::linear_offset;
|
||||||
|
|
||||||
|
uint64_t *table = reinterpret_cast<uint64_t*>(pml4);
|
||||||
|
unsigned shift = 39;
|
||||||
|
|
||||||
|
while (table) {
|
||||||
|
unsigned index = (addr >> shift) & 0x1ffull;
|
||||||
|
uint64_t entry = table[index];
|
||||||
|
|
||||||
|
if ((entry & 0x1) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((entry & large_flag) || shift <= 12)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
uint64_t next = (entry & pointer_mask) + mem::linear_offset;
|
||||||
|
table = reinterpret_cast<uint64_t*>(next);
|
||||||
|
shift -= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const char *clear = "\e[0m\n";
|
const char *clear = "\e[0m\n";
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -40,23 +79,17 @@ print_cpu(serial_port &out, cpu_data &cpu)
|
|||||||
{
|
{
|
||||||
uint32_t process = cpu.process ? cpu.process->obj_id() : 0;
|
uint32_t process = cpu.process ? cpu.process->obj_id() : 0;
|
||||||
uint32_t thread = cpu.thread ? cpu.thread->obj_id() : 0;
|
uint32_t thread = cpu.thread ? cpu.thread->obj_id() : 0;
|
||||||
|
const char *name = cpu.process ? cpu.process->name() : "<Unknown>";
|
||||||
|
|
||||||
out.write("\n \e[0;31m==[ CPU: ");
|
out.write("\n \e[0;31m==[ CPU: ");
|
||||||
|
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
util::format({buffer, sizeof(buffer)}, "%4d <%02lx:%02lx>",
|
size_t len = util::format({buffer, sizeof(buffer)}, "%4d <%02lx:%02lx> ]: %s ",
|
||||||
cpu.id + 1, process, thread);
|
cpu.id + 1, process, thread, name);
|
||||||
out.write(buffer);
|
out.write(buffer);
|
||||||
|
|
||||||
out.write(" ]=============================================================\n");
|
for (size_t i = 0; i < (74-len); ++i) out.write("=");
|
||||||
}
|
out.write("\n");
|
||||||
|
|
||||||
template <typename T> inline bool
|
|
||||||
canonical(T p)
|
|
||||||
{
|
|
||||||
static constexpr uintptr_t mask = 0xffff800000000000;
|
|
||||||
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
|
|
||||||
return (addr & mask) == mask || (addr & mask) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -65,18 +98,26 @@ print_callstack(serial_port &out, symbol_table &syms, frame const *fp)
|
|||||||
char message[512];
|
char message[512];
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
while (canonical(fp) && fp && fp->return_addr) {
|
while (fp && check_pointer(fp)) {
|
||||||
char const *name = syms.find_symbol(fp->return_addr);
|
const uintptr_t ret = fp->return_addr;
|
||||||
|
char const *name = ret ? syms.find_symbol(ret) : "<END>";
|
||||||
if (!name)
|
if (!name)
|
||||||
name = canonical(fp->return_addr) ? "<unknown>" : "<corrupt>";
|
name = check_pointer(fp->return_addr) ? "<unknown>" : "<unmapped>";
|
||||||
|
|
||||||
util::format({message, sizeof(message)},
|
util::format({message, sizeof(message)},
|
||||||
" \e[0;33mframe %2d: <0x%016lx> \e[1;33m%s\n",
|
" \e[0;33mframe %2d: <0x%016lx> <0x%016lx> \e[1;33m%s\n",
|
||||||
count++, fp->return_addr, name);
|
count++, fp, fp->return_addr, name);
|
||||||
|
|
||||||
out.write(message);
|
out.write(message);
|
||||||
|
|
||||||
|
if (!ret) return;
|
||||||
fp = fp->prev;
|
fp = fp->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *result = fp ? " <inaccessible>" : "";
|
||||||
|
util::format({message, sizeof(message)}, " \e[0mfinal <0x%016lx>%s\n",
|
||||||
|
fp, result);
|
||||||
|
out.write(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ using namespace obj;
|
|||||||
namespace syscalls {
|
namespace syscalls {
|
||||||
|
|
||||||
j6_status_t
|
j6_status_t
|
||||||
process_create(j6_handle_t *self)
|
process_create(j6_handle_t *self, const char *path)
|
||||||
{
|
{
|
||||||
process *p = construct_handle<process>(self);
|
process *p = construct_handle<process>(self, path);
|
||||||
log::info(logs::task, "Process <%02lx> created", p->obj_id());
|
log::info(logs::task, "Process <%02lx> created", p->obj_id());
|
||||||
return j6_status_ok;
|
return j6_status_ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ using system = class ::system;
|
|||||||
j6_status_t
|
j6_status_t
|
||||||
log(uint8_t area, uint8_t severity, const char *message)
|
log(uint8_t area, uint8_t severity, const char *message)
|
||||||
{
|
{
|
||||||
|
const char *name = process::current().name();
|
||||||
thread &th = thread::current();
|
thread &th = thread::current();
|
||||||
log::log(static_cast<logs>(area), static_cast<log::level>(severity),
|
log::log(static_cast<logs>(area), static_cast<log::level>(severity),
|
||||||
"<%02lx:%02lx>: %s", th.parent().obj_id(), th.obj_id(), message);
|
"<%02lx:%02lx> %s: %s", th.parent().obj_id(), th.obj_id(), name, message);
|
||||||
return j6_status_ok;
|
return j6_status_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,10 +192,10 @@ give_handle(j6_handle_t proc, j6_handle_t h, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static j6_handle_t
|
static j6_handle_t
|
||||||
create_process(j6_handle_t sys, j6_handle_t slp, j6_handle_t vfs)
|
create_process(j6_handle_t sys, j6_handle_t slp, j6_handle_t vfs, const char *path)
|
||||||
{
|
{
|
||||||
j6_handle_t proc = j6_handle_invalid;
|
j6_handle_t proc = j6_handle_invalid;
|
||||||
j6_status_t res = j6_process_create(&proc);
|
j6_status_t res = j6_process_create(&proc, path);
|
||||||
if (res != j6_status_ok) {
|
if (res != j6_status_ok) {
|
||||||
j6::syslog(j6::logs::srv, j6::log_level::error, "error loading program: creating process: %lx", res);
|
j6::syslog(j6::logs::srv, j6::log_level::error, "error loading program: creating process: %lx", res);
|
||||||
return j6_handle_invalid;
|
return j6_handle_invalid;
|
||||||
@@ -231,7 +231,7 @@ load_program(
|
|||||||
const module *arg)
|
const module *arg)
|
||||||
{
|
{
|
||||||
j6::syslog(j6::logs::srv, j6::log_level::info, "Loading program '%s' into new process", path);
|
j6::syslog(j6::logs::srv, j6::log_level::info, "Loading program '%s' into new process", path);
|
||||||
j6_handle_t proc = create_process(sys, slp, vfs);
|
j6_handle_t proc = create_process(sys, slp, vfs, path);
|
||||||
if (proc == j6_handle_invalid)
|
if (proc == j6_handle_invalid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user