Add new threads to runnable threads list
More safely handle nested interrupts. Switch to newly created thread immediately.
This commit is contained in:
parent
44a305721e
commit
9874802ee4
@ -254,8 +254,7 @@ void cpuid1(uint * ebx, uint * ecx, uint * edx)
|
||||
__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 $$`, swint_id, `", "");`);
|
||||
mixin(`__asm("int $$`, cast(int)cast(uint)swint_id, `", "");`);
|
||||
}
|
||||
|
@ -236,6 +236,7 @@ struct Him
|
||||
mov %rsp, %rbp
|
||||
mov %rsp, %rsi
|
||||
and $$0xFFFFFFFFFFFFFFF0, %rsp
|
||||
mov %rsp, %rdx
|
||||
mov %rax, %rdi
|
||||
movabs $$isr, %rax
|
||||
callq *%rax
|
||||
@ -273,10 +274,13 @@ struct Him
|
||||
* This function returns the stack pointer of the thread to execute when
|
||||
* 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++;
|
||||
Thread.current_thread.stack_pointer = stack_frame;
|
||||
if (interrupt_level == 1)
|
||||
{
|
||||
Thread.current_thread.stack_pointer = stack_frame;
|
||||
}
|
||||
if ((vector >= INT_APIC_BASE) && (vector < (INT_APIC_BASE + INT_APIC_COUNT)))
|
||||
{
|
||||
Apic.isr(vector);
|
||||
@ -292,6 +296,10 @@ public extern(C) ulong * isr(ulong vector, ulong * stack_frame)
|
||||
Apic.isr(vector);
|
||||
break;
|
||||
|
||||
case INT_KERNEL_SWINT:
|
||||
Thread.handle_swint(stack_frame);
|
||||
break;
|
||||
|
||||
default:
|
||||
Fb.rect(0, 0, Fb.width, Kfont.line_height, 0xCC0000u);
|
||||
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;
|
||||
interrupt_level--;
|
||||
return Thread.current_thread.stack_pointer;
|
||||
if (interrupt_level == 0)
|
||||
{
|
||||
return Thread.current_thread.stack_pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return rsp;
|
||||
}
|
||||
}
|
||||
|
@ -92,11 +92,22 @@ void hulk_start()
|
||||
/* Run kernel tests. */
|
||||
Test.run();
|
||||
Klog.writefln("\a5HULK Initialization Complete!");
|
||||
|
||||
Thread.start(&th);
|
||||
/* Idle loop. */
|
||||
Time.msleep(1);
|
||||
Time.msleep(500);
|
||||
Klog.writefln("Main thread!");
|
||||
for (;;)
|
||||
{
|
||||
hlt();
|
||||
}
|
||||
}
|
||||
|
||||
void th()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Klog.writefln("Hello from thread.");
|
||||
Time.msleep(1000);
|
||||
}
|
||||
}
|
||||
|
@ -10,12 +10,15 @@ import hulk.memory;
|
||||
import hulk.list;
|
||||
import hulk.cpu;
|
||||
import hulk.hurl;
|
||||
import ldc.llvmasm;
|
||||
|
||||
struct Thread
|
||||
{
|
||||
/* TODO: currently kernel thread stack size is fixed. */
|
||||
enum STACK_SIZE = 16 * 1024;
|
||||
|
||||
enum ulong INT_TCTRL_YIELD = 0;
|
||||
|
||||
/** Interrupt stack template. */
|
||||
static immutable __gshared ulong[ISF_COUNT] interrupt_stack_template = [
|
||||
0x16161616_16161616u, /* RBP */
|
||||
@ -41,8 +44,8 @@ struct Thread
|
||||
Gdt.SELECTOR_KERNEL_DATA, /* SS */
|
||||
];
|
||||
|
||||
/** List of all kernel threads. */
|
||||
private static __gshared Thread * threads;
|
||||
/** List of all runnable kernel threads. */
|
||||
private static __gshared Thread * runnable_threads;
|
||||
|
||||
/** Currently executing kernel thread. */
|
||||
static __gshared Thread * current_thread;
|
||||
@ -62,11 +65,9 @@ struct Thread
|
||||
public void initialize(void function() fn)
|
||||
{
|
||||
list_init();
|
||||
if (threads == null)
|
||||
{
|
||||
threads = &this;
|
||||
}
|
||||
suspend_interrupts();
|
||||
list_insert_after(current_thread);
|
||||
resume_interrupts();
|
||||
stack_addr = A1.allocate(STACK_SIZE);
|
||||
ulong * stack_top = cast(ulong *)(stack_addr + STACK_SIZE);
|
||||
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();
|
||||
if (threads == null)
|
||||
{
|
||||
threads = &this;
|
||||
}
|
||||
runnable_threads = &this;
|
||||
stack_addr = cast(void *)(Hurl.HULK_STACK_TOP - STACK_SIZE);
|
||||
}
|
||||
|
||||
@ -95,7 +93,7 @@ struct Thread
|
||||
public static void initialize()
|
||||
{
|
||||
Thread * thread = A1.allocate!Thread();
|
||||
thread.initialize_main_thread();
|
||||
thread.initialize_first_thread();
|
||||
current_thread = thread;
|
||||
}
|
||||
|
||||
@ -110,6 +108,36 @@ struct Thread
|
||||
{
|
||||
Thread * thread = A1.allocate!Thread();
|
||||
thread.initialize(fn);
|
||||
swint(INT_TCTRL_YIELD);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user