maybe i'm close to fixing multitasking
This commit is contained in:
+94
-70
@@ -11,120 +11,144 @@ uint32_t irq_disable_counter = 0;
|
||||
uint32_t pid_counter;
|
||||
uint32_t task_count;
|
||||
|
||||
#define STACK_SIZE 4096
|
||||
#define KSTACKSIZE 4096
|
||||
#define USTACKSIZE 4096
|
||||
|
||||
extern void trapret(void);
|
||||
extern void switchProcess(Process* next);
|
||||
extern Process* queue;
|
||||
extern Process* current;
|
||||
extern uint32_t pid_counter;
|
||||
extern uint32_t task_count;
|
||||
|
||||
// Функция запуска процесса в ядре, после которой произойдёт переход в ring 3
|
||||
static void processStartup()
|
||||
{
|
||||
printf("startup\n");
|
||||
scheduler_unlock();
|
||||
printf("startup\n");
|
||||
scheduler_unlock();
|
||||
// Возврат из этой функции приведёт к вызову trapret
|
||||
}
|
||||
|
||||
Process* task_create(EntryPoint func, void** args, uint32_t arg_count)
|
||||
Process* task_create(EntryPoint func, void** args, uint32_t arg_count, uint32_t ring)
|
||||
{
|
||||
Process* p = heap_alloc(sizeof(Process));
|
||||
p->pid = ++pid_counter;
|
||||
p->state = Ready;
|
||||
p->programCounter = 0;
|
||||
p->stackBase = heap_alloc(STACK_SIZE);
|
||||
p->stackPointer = (uintptr_t*)((uint32_t)p->stackBase + STACK_SIZE);
|
||||
Process* p = alloc_page();//heap_alloc(sizeof(Process));
|
||||
p->pid = ++pid_counter;
|
||||
p->state = Ready;
|
||||
p->ring = ring;
|
||||
|
||||
//put the arguments in stack
|
||||
for(int i = arg_count-1; i >=0; i--)
|
||||
*(--p->stackPointer) = (uintptr_t)args[i];
|
||||
// Выделяем стек ядра
|
||||
p->kstack = alloc_page();//heap_alloc(KSTACKSIZE);
|
||||
uint32_t* sp = (uint32_t*)(p->kstack + KSTACKSIZE);
|
||||
|
||||
// Добавляем адрес возврата (фиктивный, для выравнивания)
|
||||
*(--p->stackPointer) = 0; // Фиктивный адрес возврата (не используется напрямую)
|
||||
if (ring == DPL_USER) {
|
||||
// Настраиваем trap frame для ring 3
|
||||
sp -= sizeof(TrapFrame) / 4;
|
||||
p->tf = (TrapFrame*)sp;
|
||||
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
|
||||
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
|
||||
p->tf->es = p->tf->ds;
|
||||
p->tf->fs = p->tf->ds;
|
||||
p->tf->gs = p->tf->ds;
|
||||
p->tf->ss = p->tf->ds;
|
||||
p->tf->eflags = FL_IF;
|
||||
p->tf->eip = (uint32_t)func;
|
||||
p->tf->esp = USTACKSIZE; // Предполагаем, что пользовательский стек настроен
|
||||
|
||||
*(--p->stackPointer) = (uintptr_t)func;
|
||||
*(--p->stackPointer) = (uintptr_t)processStartup;
|
||||
*(--p->stackPointer) = 0;//ebp
|
||||
*(--p->stackPointer) = 0;//edi
|
||||
*(--p->stackPointer) = 0;//esi
|
||||
*(--p->stackPointer) = 0;//ebx
|
||||
// Добавляем адрес возврата для trapret
|
||||
sp -= 1;
|
||||
*sp = (uint32_t)trapret;
|
||||
} else {
|
||||
// Для ring 0 не используем trap frame
|
||||
p->tf = NULL;
|
||||
}
|
||||
// Настраиваем начальный контекст
|
||||
sp -= 5; // Место для edi, esi, ebx, ebp, eip
|
||||
p->context = (Context*)sp;
|
||||
p->context->edi = 0;
|
||||
p->context->esi = 0;
|
||||
p->context->ebx = 0;
|
||||
p->context->ebp = 0;
|
||||
if (ring == DPL_USER) {
|
||||
p->context->eip = (uint32_t)processStartup;
|
||||
} else {
|
||||
p->context->eip = (uint32_t)func; // Прямо в ring 0
|
||||
}
|
||||
|
||||
p->page_directory = kernel_page_directory;
|
||||
p->page_directory = kernel_page_directory;
|
||||
|
||||
p->next = 0;
|
||||
p->next = 0;
|
||||
|
||||
if(!queue)
|
||||
{
|
||||
queue = p;
|
||||
current = queue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Process* curr = queue;
|
||||
while(curr->next)
|
||||
curr = curr->next;
|
||||
curr->next = p;
|
||||
}
|
||||
task_count++;
|
||||
return p;
|
||||
if (!queue) {
|
||||
queue = p;
|
||||
current = queue;
|
||||
} else {
|
||||
Process* curr = queue;
|
||||
while (curr->next)
|
||||
curr = curr->next;
|
||||
curr->next = p;
|
||||
}
|
||||
task_count++;
|
||||
return p;
|
||||
}
|
||||
|
||||
// Остальные функции остаются без изменений
|
||||
void scheduler_lock()
|
||||
{
|
||||
asm volatile("cli");
|
||||
irq_disable_counter++;
|
||||
asm volatile("cli");
|
||||
irq_disable_counter++;
|
||||
}
|
||||
|
||||
void scheduler_unlock()
|
||||
{
|
||||
irq_disable_counter--;
|
||||
if(irq_disable_counter == 0)
|
||||
asm volatile("sti");
|
||||
irq_disable_counter--;
|
||||
if (irq_disable_counter == 0)
|
||||
asm volatile("sti");
|
||||
}
|
||||
|
||||
void schedule()
|
||||
{
|
||||
if(!current)
|
||||
return;
|
||||
if (!current)
|
||||
return;
|
||||
|
||||
Process* next = current->next;
|
||||
if(!next)
|
||||
next = queue;
|
||||
if(next != current)
|
||||
{
|
||||
//loadPageDirectory(next->page_directory);
|
||||
switchProcess(next);
|
||||
}
|
||||
Process* next = current->next;
|
||||
if (!next)
|
||||
next = queue;
|
||||
if (next != current)
|
||||
{
|
||||
//loadPageDirectory(next->page_directory);
|
||||
switchProcess(next);
|
||||
}
|
||||
}
|
||||
|
||||
void idle()
|
||||
{
|
||||
while(1){}
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
void task1(int arg1, char* arg2)
|
||||
{
|
||||
while(1){
|
||||
if(arg1 == 42)
|
||||
printf("task1 0x%x %s\n", arg1, arg2);
|
||||
else
|
||||
printf("ZHOPA %s\n", arg2);
|
||||
}
|
||||
while (1) {
|
||||
if (arg1 == 42)
|
||||
printf("task1 0x%x %s\n", arg1, arg2);
|
||||
else
|
||||
printf("ZHOPA %s\n", arg2);
|
||||
}
|
||||
}
|
||||
|
||||
void task2(int arg1, int arg2)
|
||||
{
|
||||
while(1){printf("task2 %X %X\n", arg1, arg2);}
|
||||
while (1) { arg1++; printf("task2 %X %X\n", arg1, arg2); }
|
||||
}
|
||||
|
||||
void jump_usermode2(void);
|
||||
|
||||
void scheduler_init()
|
||||
{
|
||||
jump_usermode2();
|
||||
//we create this task two times because in other case it just won't start
|
||||
task_create((EntryPoint)&idle, NULL, 0);
|
||||
task_create((EntryPoint)&idle, NULL, 0);
|
||||
task_create((EntryPoint)idle, NULL, 0, 0);
|
||||
task_create((EntryPoint)idle, NULL, 0, 0);
|
||||
|
||||
void* args1[] = {(void*)42, (void*)"ebalo"};
|
||||
task_create((EntryPoint)&task1, args1, 2);
|
||||
void* args2[] = {(void*)69, (void*)420};
|
||||
task_create((EntryPoint)&task2, args2, 2);
|
||||
void* args1[] = {(void*)42, (void*)"ebalo"};
|
||||
task_create((EntryPoint)task1, args1, 2, 0);
|
||||
void* args2[] = {(void*)69, (void*)420};
|
||||
task_create((EntryPoint)task2, args2, 2, 0);
|
||||
}
|
||||
|
||||
#include "../include/string.h"
|
||||
|
||||
Reference in New Issue
Block a user