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 */