3 schedule = page fault
Posted: Thu Oct 21, 2010 11:16 am
Yeah, again, it's a problem with my multitasking code for Asmadian.
I fork()'ed the kernel process. Then I got a page fault (address 0xF000E752). I decided to check what's up...
Well, I just got my schedule() function to print "schedule!" whenever it is called, and here's what I got:
There are two processes, but the first one (0x0) runs at start, so the first schedule causes it to go to 0x1, then to 0x0 and then to 0x1 again. What caused this error??
Here's all my multitasking code:
Any help? Thanks.
I fork()'ed the kernel process. Then I got a page fault (address 0xF000E752). I decided to check what's up...
Well, I just got my schedule() function to print "schedule!" whenever it is called, and here's what I got:
Code: Select all
fork() returned 0x1 and getpid() returned 0x0
=============================
schedule!
schedule!
schedule!
PAGE FAULT! HOORAY!
Address: 0xf000e752
Here's all my multitasking code:
Code: Select all
/*
proc.h -- process structures and scheduler.
*/
#ifndef _PROC
#define _PROC
#include "common.h"
#include "kernel.h"
#include "paging.h"
#include "memory.h"
#include "heap.h"
// process states
#define P_ALIVE 0x01
#define P_SLEEP 0x02
#define P_DEAD 0x03
// OR this with the task state to get a daemon/root task
#define P_ROOT 0x80
#define P_DAEMON P_ROOT
struct process;
struct process
{
char name[50]; // e.g. KERNEL TASK, or Asmadianet
int pid;
u32int eax, ebx, ecx, edx, eip, esp, ebp, esi, edi;
struct page_directory * pdir;
u8int state;
struct process * next;
};
struct process * kernel_proc = NULL; // also the FIRST process.
struct process * current_proc; // currently running process
int pid_top = 0; // highest pid so far.
u32int ebp;
extern u32int read_eip();
void init_sched();
void schedule();
int fork();
int getpid();
struct process * getproc(int);
struct process * find_free_proc();
void init_sched()
{
asm volatile ("cli"); // important stuff happening; disabled interrupt!
print("sched start\n");
kernel_proc = (struct process *) malloc(sizeof(struct process));
if (kernel_proc == NULL)
{
failure("could not initialise multitasking; out of memory in critical state\n");
};
strcpy(kernel_proc->name, "KERNEL TASK");
kernel_proc->pid = pid_top++;
kernel_proc->eax = kernel_proc->ebx = kernel_proc->ecx = kernel_proc->edx = kernel_proc->esi = kernel_proc->edi = 0;
kernel_proc->ebp = kernel_proc->esp = 0;
kernel_proc->eip = read_eip();
if (kernel_proc->eip == 0x12345)
{
print ("init_sched() success\n");
return;
};
kernel_proc->pdir = kernel_directory;
kernel_proc->state = P_SLEEP;
kernel_proc->next = NULL;
current_proc = kernel_proc;
asm volatile ("mov $0x12345, %%eax;" : :);
asm volatile ("sti"); // done with the important stuff.. you can start interrupting!
print("end sched\n");
};
struct process * find_free_proc()
{
struct process * proc = kernel_proc;
while (proc->state != P_DEAD)
{
if (proc->next != NULL)
{
proc = proc->next;
} else {
proc->next = (struct process *) malloc(sizeof(struct process));
proc = proc->next;
proc->pid = pid_top++;
return proc;
};
};
// found a dead process; reuse
return proc;
};
int fork()
{
asm volatile ("cli"); // we shall not be interrupted
struct process * parent_proc = current_proc; // needed so we don't confuse namespaces.
struct page_directory * pdir = clone_directory(current_directory);
struct process * proc = find_free_proc();
int pid = proc->pid; // save
memcpy(proc, current_proc, sizeof(struct process)); // copy process
if (parent_proc == current_proc)
{
proc->pid = pid;
proc->next = NULL;
asm ("sti");
return pid;
} else {
return 0;
};
};
void schedule()
{
print("schedule!\n");
if (kernel_proc == NULL) return;
u32int esp, ebp, eip;
asm volatile("mov %%esp, %0" : "=r"(esp));
asm volatile("mov %%ebp, %0" : "=r"(ebp));
eip = read_eip();
if (eip == 0x12345)
{
return;
};
current_proc->eip = eip;
current_proc->esp = esp;
current_proc->ebp = ebp;
current_proc = current_proc->next;
if (current_proc->state != P_ALIVE)
{
schedule();
return;
};
if (!current_proc) current_proc = kernel_proc;
esp = current_proc->esp;
ebp = current_proc->ebp;
asm volatile(" \
cli; \
mov %0, %%ecx; \
mov %1, %%esp; \
mov %2, %%ebp; \
mov %3, %%cr3; \
mov $0x12345, %%eax; \
sti; \
jmp *%%ecx "
: : "r"(eip), "r"(esp), "r"(ebp), "r"(current_directory->physicalAddr));
};
int getpid()
{
return current_proc->pid;
};
#endif /* _PROC */