Fork Assingnment
Fork Assingnment
khadija 023-17-0042
sumra 051-18-0009
Coding
#include "kernel.hh"
#include "k-ahci.hh"
#include "k-apic.hh"
#include "k-chkfs.hh"
#include "k-chkfsiter.hh"
#include "k-devices.hh"
#include "k-vmiter.hh"
#ifndef CHICKADEE_FIRST_PROCESS
#define CHICKADEE_FIRST_PROCESS "allocator"
#endif
// kernel.cc
//
// This is the kernel.
// kernel_start(command)
// Initialize the hardware and processes and start running. The
`command`
// string is an optional string passed from the boot loader.
// process_setup(pid, name)
// Load application program `name` as process number `pid`.
// This loads the application's code and data into memory, sets its
// %rip and %rsp, gives it a stack page, and marks it as runnable.
assert(!ptable[pid]);
proc* p = ptable[pid] = knew<proc>();
p->init_user(pid, ld.pagetable_);
p->regs_->reg_rip = ld.entry_rip_;
// proc::exception(reg)
// Exception handler (for interrupts, traps, and faults).
//
// The register values from exception time are stored in `reg`.
// The processor responds to an exception by saving application
state on
// the current CPU stack, then jumping to kernel assembly code
(in
// k-exception.S). That code transfers the state to the current
kernel
// task's stack, then calls proc::exception().
if ((regs->reg_cs & 5) == 0) {
panic("Kernel page fault for %p (%s %s, rip=%p)!\n",
addr, operation, problem, regs->reg_rip);
}
error_printf(CPOS(24, 0), 0x0C00,
"Process %d page fault for %p (%s %s, rip=%p)!\n",
id_, addr, operation, problem, regs->reg_rip);
this->state_ = proc::broken;
this->yield();
break;
}
default:
if (sata_disk && regs->reg_intno == INT_IRQ + sata_disk-
>irq_) {
sata_disk->handle_interrupt();
} else {
panic("Unexpected exception %d!\n", regs->reg_intno);
}
break; /* will not be reached */
// proc::syscall(regs)
// System call handler.
//
// The register values from system call time are stored in `regs`.
// The return value from `proc::syscall()` is returned to the user
// process in `%rax`.
uintptr_t proc::syscall(regstate* regs) {
switch (regs->reg_rax) {
case SYSCALL_KDISPLAY:
if (kdisplay != (int) regs->reg_rdi) {
console_clear();
}
kdisplay = regs->reg_rdi;
return 0;
case SYSCALL_PANIC:
panic(nullptr);
break; // will not be reached
case SYSCALL_GETPID:
return id_;
case SYSCALL_YIELD:
this->yield();
return 0;
case SYSCALL_PAGE_ALLOC: {
uintptr_t addr = regs->reg_rdi;
if (addr >= VA_LOWEND || addr & 0xFFF) {
return -1;
}
void* pg = kalloc(PAGESIZE);
if (!pg || vmiter(this, addr).map(ka2pa(pg)) < 0) {
return -1;
}
return 0;
}
case SYSCALL_PAUSE: {
sti();
for (uintptr_t delay = 0; delay < 1000000; ++delay) {
pause();
}
cli();
return 0;
}
case SYSCALL_FORK:
return syscall_fork(regs);
case SYSCALL_READ:
return syscall_read(regs);
case SYSCALL_WRITE:
return syscall_write(regs);
case SYSCALL_READDISKFILE:
return syscall_readdiskfile(regs);
case SYSCALL_SYNC: {
int drop = regs->reg_rdi;
// `drop > 1` asserts that no data blocks are referenced (except
// possibly superblock and FBB blocks). This can only be
ensured on
// tests that run as the first process.
if (drop > 1 && strncmp(CHICKADEE_FIRST_PROCESS,
"test", 4) != 0) {
drop = 1;
}
return bufcache::get().sync(drop);
}
default:
// no such system call
log_printf("%d: no such system call %u\n", id_, regs-
>reg_rax);
return E_NOSYS;
}
}
// proc::syscall_read(regs), proc::syscall_write(regs)
// Handle read and write system calls.
kbd.lock_.unlock(irqs);
return n;
}
pid_t pid = 1;
for(;pid<NPROC;pid++){
if(ptable[pid] == nullptr){
break;
}
else if(pid == 15)
return -1;
}
process_setup(i, CHICKADEE_FIRST_PROCESS);
ptable_lock.unlock(irqs);
proc* p = knew<proc>();
ptable[pid] = p;
ptable[pid]->pagetable_ = kalloc_pagetable();
memfile_loader ld(pid, p->pagetable_);
p->init_user(pid,ld.pagetable_);
memcpy(p->regs_,par->regs_,sizeof(regs_));
p->regs_->reg_rax=0;
ptable[pid]->regs_->reg_rip = regs->reg_rip;
//p->regs_->reg_rip =regs->entry_rip_;
memcpy(&p->regs_->reg_rcx,&ptable[cp]->regs_-
>reg_rcx,sizeof(regs));
void* stkpg = kalloc(PAGESIZE);
assert(stkpg);
int r = proc::load(ld);
r = vmiter(p, MEMSIZE_VIRTUAL -
PAGESIZE).map(ka2pa(stkpg));
assert(r >= 0);
p->regs_->reg_rsp = MEMSIZE_VIRTUAL;
//scehdualling
int cpu = pid % ncpu;
cpus[cpu].runq_lock_.lock_noirq();
cpus[cpu].enqueue(ptable[pid]);
cpus[cpu].runq_lock_.unlock_noirq();
ptable_lock.unlock(irqs);
return pid++;
size_t nread = 0;
while (nread < sz) {
// copy data from current block
if (bcentry* e = it.find(off).get_disk_entry()) {
unsigned b = it.block_relative_offset();
size_t ncopy = min(
size_t(ino->size - it.offset()), // bytes left in file
chkfs::blocksize - b, // bytes left in block
sz - nread // bytes left in request
);
memcpy(buf + nread, e->buf_ + b, ncopy);
e->put();
nread += ncopy;
off += ncopy;
if (ncopy == 0) {
break;
}
} else {
break;
}
}
ino->unlock_read();
ino->put();
return 0;//nread;
}
// memshow()
// Draw a picture of memory (physical and virtual) on the CGA
console.
// Switches to a new process's virtual memory map every 0.25
sec.
// Uses `console_memviewer()`, a function defined in `k-
memviewer.cc`.
int search = 0;
while ((!ptable[showing]
|| !ptable[showing]->pagetable_
|| ptable[showing]->pagetable_ == early_pagetable)
&& search < NPROC) {
showing = (showing + 1) % NPROC;
++search;
}
extern void console_memviewer(proc* vmp);
console_memviewer(ptable[showing]);
ptable_lock.unlock(irqs);
}
// kdisplay_ontick()
// Shows the currently-configured kdisplay. Called once every
tick
// (every 0.01 sec) by CPU 0.
void kdisplay_ontick() {
if (kdisplay == KDISPLAY_MEMVIEWER) {
memshow();
}
}
Result: