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);
|
__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, `", "");`);
|
|
||||||
}
|
}
|
||||||
|
@ -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++;
|
||||||
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)))
|
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--;
|
||||||
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. */
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user