Add new threads to runnable threads list

More safely handle nested interrupts.
Switch to newly created thread immediately.
This commit is contained in:
Josh Holtrop 2023-12-08 12:16:35 -05:00
parent 44a305721e
commit 9874802ee4
4 changed files with 73 additions and 20 deletions

View File

@ -254,8 +254,7 @@ void cpuid1(uint * ebx, uint * ecx, uint * edx)
__asm("cpuid", "=*{ebx},=*{ecx},=*{edx},{eax}", ebx, ecx, edx, 1u); __asm("cpuid", "=*{ebx},=*{ecx},=*{edx},{eax}", ebx, ecx, edx, 1u);
} }
void swint(int swint_id)() void swint(ubyte swint_id)()
{ {
static assert((0 <= swint_id) && (swint_id <= 255)); mixin(`__asm("int $$`, cast(int)cast(uint)swint_id, `", "");`);
mixin(`__asm("int $$`, swint_id, `", "");`);
} }

View File

@ -236,6 +236,7 @@ struct Him
mov %rsp, %rbp mov %rsp, %rbp
mov %rsp, %rsi mov %rsp, %rsi
and $$0xFFFFFFFFFFFFFFF0, %rsp and $$0xFFFFFFFFFFFFFFF0, %rsp
mov %rsp, %rdx
mov %rax, %rdi mov %rax, %rdi
movabs $$isr, %rax movabs $$isr, %rax
callq *%rax callq *%rax
@ -273,10 +274,13 @@ struct Him
* This function returns the stack pointer of the thread to execute when * This function returns the stack pointer of the thread to execute when
* returning from this function. * returning from this function.
*/ */
public extern(C) ulong * isr(ulong vector, ulong * stack_frame) public extern(C) ulong * isr(ulong vector, ulong * stack_frame, ulong * rsp)
{ {
interrupt_level++; interrupt_level++;
if (interrupt_level == 1)
{
Thread.current_thread.stack_pointer = stack_frame; Thread.current_thread.stack_pointer = stack_frame;
}
if ((vector >= INT_APIC_BASE) && (vector < (INT_APIC_BASE + INT_APIC_COUNT))) if ((vector >= INT_APIC_BASE) && (vector < (INT_APIC_BASE + INT_APIC_COUNT)))
{ {
Apic.isr(vector); Apic.isr(vector);
@ -292,6 +296,10 @@ public extern(C) ulong * isr(ulong vector, ulong * stack_frame)
Apic.isr(vector); Apic.isr(vector);
break; break;
case INT_KERNEL_SWINT:
Thread.handle_swint(stack_frame);
break;
default: default:
Fb.rect(0, 0, Fb.width, Kfont.line_height, 0xCC0000u); Fb.rect(0, 0, Fb.width, Kfont.line_height, 0xCC0000u);
Klog.writefln("\n **** Unhandled ISR %u ****", vector); Klog.writefln("\n **** Unhandled ISR %u ****", vector);
@ -310,5 +318,12 @@ public extern(C) ulong * isr(ulong vector, ulong * stack_frame)
} }
Thread.current_thread = Thread.current_thread.list_next; Thread.current_thread = Thread.current_thread.list_next;
interrupt_level--; interrupt_level--;
if (interrupt_level == 0)
{
return Thread.current_thread.stack_pointer; return Thread.current_thread.stack_pointer;
} }
else
{
return rsp;
}
}

View File

@ -92,11 +92,22 @@ void hulk_start()
/* Run kernel tests. */ /* Run kernel tests. */
Test.run(); Test.run();
Klog.writefln("\a5HULK Initialization Complete!"); Klog.writefln("\a5HULK Initialization Complete!");
Thread.start(&th);
/* Idle loop. */ /* Idle loop. */
Time.msleep(1); Time.msleep(1);
Time.msleep(500);
Klog.writefln("Main thread!");
for (;;) for (;;)
{ {
hlt(); hlt();
} }
} }
void th()
{
for (;;)
{
Klog.writefln("Hello from thread.");
Time.msleep(1000);
}
}

View File

@ -10,12 +10,15 @@ import hulk.memory;
import hulk.list; import hulk.list;
import hulk.cpu; import hulk.cpu;
import hulk.hurl; import hulk.hurl;
import ldc.llvmasm;
struct Thread struct Thread
{ {
/* TODO: currently kernel thread stack size is fixed. */ /* TODO: currently kernel thread stack size is fixed. */
enum STACK_SIZE = 16 * 1024; enum STACK_SIZE = 16 * 1024;
enum ulong INT_TCTRL_YIELD = 0;
/** Interrupt stack template. */ /** Interrupt stack template. */
static immutable __gshared ulong[ISF_COUNT] interrupt_stack_template = [ static immutable __gshared ulong[ISF_COUNT] interrupt_stack_template = [
0x16161616_16161616u, /* RBP */ 0x16161616_16161616u, /* RBP */
@ -41,8 +44,8 @@ struct Thread
Gdt.SELECTOR_KERNEL_DATA, /* SS */ Gdt.SELECTOR_KERNEL_DATA, /* SS */
]; ];
/** List of all kernel threads. */ /** List of all runnable kernel threads. */
private static __gshared Thread * threads; private static __gshared Thread * runnable_threads;
/** Currently executing kernel thread. */ /** Currently executing kernel thread. */
static __gshared Thread * current_thread; static __gshared Thread * current_thread;
@ -62,11 +65,9 @@ struct Thread
public void initialize(void function() fn) public void initialize(void function() fn)
{ {
list_init(); list_init();
if (threads == null) suspend_interrupts();
{
threads = &this;
}
list_insert_after(current_thread); list_insert_after(current_thread);
resume_interrupts();
stack_addr = A1.allocate(STACK_SIZE); stack_addr = A1.allocate(STACK_SIZE);
ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE); ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE);
stack_pointer = stack_top - ISF_COUNT; stack_pointer = stack_top - ISF_COUNT;
@ -77,15 +78,12 @@ struct Thread
} }
/** /**
* Initialize main kernel thread. * Initialize first kernel thread.
*/ */
public void initialize_main_thread() public void initialize_first_thread()
{ {
list_init(); list_init();
if (threads == null) runnable_threads = &this;
{
threads = &this;
}
stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE); stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE);
} }
@ -95,7 +93,7 @@ struct Thread
public static void initialize() public static void initialize()
{ {
Thread * thread = A1.allocate!Thread(); Thread * thread = A1.allocate!Thread();
thread.initialize_main_thread(); thread.initialize_first_thread();
current_thread = thread; current_thread = thread;
} }
@ -110,6 +108,36 @@ struct Thread
{ {
Thread * thread = A1.allocate!Thread(); Thread * thread = A1.allocate!Thread();
thread.initialize(fn); thread.initialize(fn);
swint(INT_TCTRL_YIELD);
return thread; return thread;
} }
/**
* Trigger a thread management software interrupt.
*/
public static void swint(T1)(T1 v1)
{
mixin(`__asm("int $$`, cast(int)INT_KERNEL_SWINT, `", "{rax}", v1);`);
}
/**
* Handle a thread management software interrupt.
*
* This function is called in interrupt context.
*
* @param stack_frame
* Pointer to the stack frame.
*/
public static void handle_swint(ulong * stack_frame)
{
switch (stack_frame[ISF_RAX])
{
case INT_TCTRL_YIELD:
Thread.current_thread = Thread.current_thread.list_next;
break;
default:
break;
}
}
} }