Merge branch 'riscv-proc' into riscv
This commit is contained in:
commit
2f22a3ed6a
|
@ -2,6 +2,7 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
@ -19,7 +20,6 @@ exec(char *path, char **argv)
|
||||||
struct proghdr ph;
|
struct proghdr ph;
|
||||||
pagetable_t pagetable = 0, oldpagetable;
|
pagetable_t pagetable = 0, oldpagetable;
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
uint64 oldsz = p->sz;
|
|
||||||
|
|
||||||
begin_op();
|
begin_op();
|
||||||
|
|
||||||
|
@ -60,6 +60,9 @@ exec(char *path, char **argv)
|
||||||
end_op();
|
end_op();
|
||||||
ip = 0;
|
ip = 0;
|
||||||
|
|
||||||
|
p = myproc();
|
||||||
|
uint64 oldsz = p->sz;
|
||||||
|
|
||||||
// Allocate two pages at the next page boundary.
|
// Allocate two pages at the next page boundary.
|
||||||
// Use the second as the user stack.
|
// Use the second as the user stack.
|
||||||
sz = PGROUNDUP(sz);
|
sz = PGROUNDUP(sz);
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "stat.h"
|
#include "stat.h"
|
||||||
#include "proc.h"
|
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
#include "proc.h"
|
||||||
#include "sleeplock.h"
|
#include "sleeplock.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "buf.h"
|
#include "buf.h"
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "spinlock.h"
|
|
||||||
#include "sleeplock.h"
|
#include "sleeplock.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
|
||||||
|
|
242
kernel/proc.c
242
kernel/proc.c
|
@ -2,33 +2,36 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "proc.h"
|
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
struct {
|
struct proc proc[NPROC];
|
||||||
struct spinlock lock;
|
|
||||||
struct proc proc[NPROC];
|
|
||||||
} ptable;
|
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
struct cpu cpus[NCPU];
|
||||||
|
|
||||||
struct proc *initproc;
|
struct proc *initproc;
|
||||||
|
|
||||||
|
struct spinlock pid_lock;
|
||||||
int nextpid = 1;
|
int nextpid = 1;
|
||||||
|
|
||||||
extern void forkret(void);
|
extern void forkret(void);
|
||||||
|
|
||||||
// for returning out of the kernel
|
// for returning out of the kernel
|
||||||
extern void sysexit(void);
|
extern void sysexit(void);
|
||||||
|
|
||||||
static void wakeup1(void *chan);
|
static void wakeup1(struct proc *chan);
|
||||||
|
|
||||||
extern char trampout[]; // trampoline.S
|
extern char trampout[]; // trampoline.S
|
||||||
|
|
||||||
void
|
void
|
||||||
procinit(void)
|
procinit(void)
|
||||||
{
|
{
|
||||||
initlock(&ptable.lock, "ptable");
|
struct proc *p;
|
||||||
|
|
||||||
|
initlock(&pid_lock, "nextpid");
|
||||||
|
for(p = proc; p < &proc[NPROC]; p++)
|
||||||
|
initlock(&p->lock, "proc");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must be called with interrupts disabled,
|
// Must be called with interrupts disabled,
|
||||||
|
@ -60,40 +63,48 @@ myproc(void) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
allocpid() {
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
acquire(&pid_lock);
|
||||||
|
pid = nextpid++;
|
||||||
|
release(&pid_lock);
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
//PAGEBREAK: 32
|
//PAGEBREAK: 32
|
||||||
// Look in the process table for an UNUSED proc.
|
// Look in the process table for an UNUSED proc.
|
||||||
// If found, change state to EMBRYO and initialize
|
// If found, initialize state required to run in the kernel,
|
||||||
// state required to run in the kernel.
|
// and return with p->lock held.
|
||||||
// Otherwise return 0.
|
// Otherwise return 0.
|
||||||
static struct proc*
|
static struct proc*
|
||||||
allocproc(void)
|
allocproc(void)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
for(p = proc; p < &proc[NPROC]; p++) {
|
||||||
|
acquire(&p->lock);
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
|
if(p->state == UNUSED) {
|
||||||
if(p->state == UNUSED)
|
|
||||||
goto found;
|
goto found;
|
||||||
|
} else {
|
||||||
release(&ptable.lock);
|
release(&p->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
p->state = EMBRYO;
|
p->pid = allocpid();
|
||||||
p->pid = nextpid++;
|
|
||||||
|
|
||||||
release(&ptable.lock);
|
|
||||||
|
|
||||||
// Allocate a page for the kernel stack.
|
// Allocate a page for the kernel stack.
|
||||||
if((p->kstack = kalloc()) == 0){
|
if((p->kstack = kalloc()) == 0){
|
||||||
p->state = UNUSED;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a trapframe page.
|
// Allocate a trapframe page.
|
||||||
if((p->tf = (struct trapframe *)kalloc()) == 0){
|
if((p->tf = (struct trapframe *)kalloc()) == 0){
|
||||||
p->state = UNUSED;
|
kfree(p->kstack);
|
||||||
|
p->kstack = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +122,7 @@ found:
|
||||||
|
|
||||||
// free a proc structure and the data hanging from it,
|
// free a proc structure and the data hanging from it,
|
||||||
// including user pages.
|
// including user pages.
|
||||||
// the proc lock must be held.
|
// p->lock must be held.
|
||||||
static void
|
static void
|
||||||
freeproc(struct proc *p)
|
freeproc(struct proc *p)
|
||||||
{
|
{
|
||||||
|
@ -195,22 +206,16 @@ userinit(void)
|
||||||
uvminit(p->pagetable, initcode, sizeof(initcode));
|
uvminit(p->pagetable, initcode, sizeof(initcode));
|
||||||
p->sz = PGSIZE;
|
p->sz = PGSIZE;
|
||||||
|
|
||||||
// prepare for the very first kernel->user.
|
// prepare for the very first "return" from kernel to user.
|
||||||
p->tf->epc = 0;
|
p->tf->epc = 0;
|
||||||
p->tf->sp = PGSIZE;
|
p->tf->sp = PGSIZE;
|
||||||
|
|
||||||
safestrcpy(p->name, "initcode", sizeof(p->name));
|
safestrcpy(p->name, "initcode", sizeof(p->name));
|
||||||
p->cwd = namei("/");
|
p->cwd = namei("/");
|
||||||
|
|
||||||
// this assignment to p->state lets other cores
|
|
||||||
// run this process. the acquire forces the above
|
|
||||||
// writes to be visible, and the lock is also needed
|
|
||||||
// because the assignment might not be atomic.
|
|
||||||
acquire(&ptable.lock);
|
|
||||||
|
|
||||||
p->state = RUNNABLE;
|
p->state = RUNNABLE;
|
||||||
|
|
||||||
release(&ptable.lock);
|
release(&p->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow current process's memory by n bytes.
|
// Grow current process's memory by n bytes.
|
||||||
|
@ -223,11 +228,13 @@ growproc(int n)
|
||||||
|
|
||||||
sz = p->sz;
|
sz = p->sz;
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0)
|
if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
} else if(n < 0){
|
} else if(n < 0){
|
||||||
if((sz = uvmdealloc(p->pagetable, sz, sz + n)) == 0)
|
if((sz = uvmdealloc(p->pagetable, sz, sz + n)) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p->sz = sz;
|
p->sz = sz;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -250,6 +257,7 @@ fork(void)
|
||||||
// Copy user memory from parent to child.
|
// Copy user memory from parent to child.
|
||||||
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
|
if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
|
||||||
freeproc(np);
|
freeproc(np);
|
||||||
|
release(&np->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
np->sz = p->sz;
|
np->sz = p->sz;
|
||||||
|
@ -272,15 +280,39 @@ fork(void)
|
||||||
|
|
||||||
pid = np->pid;
|
pid = np->pid;
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
|
||||||
|
|
||||||
np->state = RUNNABLE;
|
np->state = RUNNABLE;
|
||||||
|
|
||||||
release(&ptable.lock);
|
release(&np->lock);
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pass p's abandoned children to init. p and p's parent
|
||||||
|
// are locked.
|
||||||
|
void
|
||||||
|
reparent(struct proc *p, struct proc *parent) {
|
||||||
|
struct proc *pp;
|
||||||
|
int child_of_init = (p->parent == initproc);
|
||||||
|
|
||||||
|
for(pp = proc; pp < &proc[NPROC]; pp++){
|
||||||
|
if (pp != p && pp != parent) {
|
||||||
|
acquire(&pp->lock);
|
||||||
|
if(pp->parent == p){
|
||||||
|
pp->parent = initproc;
|
||||||
|
if(pp->state == ZOMBIE) {
|
||||||
|
if(!child_of_init)
|
||||||
|
acquire(&initproc->lock);
|
||||||
|
wakeup1(initproc);
|
||||||
|
if(!child_of_init)
|
||||||
|
release(&initproc->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release(&pp->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Exit the current process. Does not return.
|
// Exit the current process. Does not return.
|
||||||
// An exited process remains in the zombie state
|
// An exited process remains in the zombie state
|
||||||
// until its parent calls wait().
|
// until its parent calls wait().
|
||||||
|
@ -288,7 +320,6 @@ void
|
||||||
exit(void)
|
exit(void)
|
||||||
{
|
{
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
struct proc *pp;
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if(p == initproc)
|
if(p == initproc)
|
||||||
|
@ -297,7 +328,8 @@ exit(void)
|
||||||
// Close all open files.
|
// Close all open files.
|
||||||
for(fd = 0; fd < NOFILE; fd++){
|
for(fd = 0; fd < NOFILE; fd++){
|
||||||
if(p->ofile[fd]){
|
if(p->ofile[fd]){
|
||||||
fileclose(p->ofile[fd]);
|
struct file *f = p->ofile[fd];
|
||||||
|
fileclose(f);
|
||||||
p->ofile[fd] = 0;
|
p->ofile[fd] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,22 +339,20 @@ exit(void)
|
||||||
end_op();
|
end_op();
|
||||||
p->cwd = 0;
|
p->cwd = 0;
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
acquire(&p->parent->lock);
|
||||||
|
|
||||||
|
acquire(&p->lock);
|
||||||
|
|
||||||
|
reparent(p, p->parent);
|
||||||
|
|
||||||
|
p->state = ZOMBIE;
|
||||||
|
|
||||||
// Parent might be sleeping in wait().
|
// Parent might be sleeping in wait().
|
||||||
wakeup1(p->parent);
|
wakeup1(p->parent);
|
||||||
|
|
||||||
// Pass abandoned children to init.
|
release(&p->parent->lock);
|
||||||
for(pp = ptable.proc; pp < &ptable.proc[NPROC]; pp++){
|
|
||||||
if(pp->parent == p){
|
|
||||||
pp->parent = initproc;
|
|
||||||
if(pp->state == ZOMBIE)
|
|
||||||
wakeup1(initproc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump into the scheduler, never to return.
|
// Jump into the scheduler, never to return.
|
||||||
p->state = ZOMBIE;
|
|
||||||
sched();
|
sched();
|
||||||
panic("zombie exit");
|
panic("zombie exit");
|
||||||
}
|
}
|
||||||
|
@ -336,31 +366,34 @@ wait(void)
|
||||||
int havekids, pid;
|
int havekids, pid;
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
acquire(&p->lock);
|
||||||
for(;;){
|
for(;;){
|
||||||
// Scan through table looking for exited children.
|
// Scan through table looking for exited children.
|
||||||
havekids = 0;
|
havekids = 0;
|
||||||
for(np = ptable.proc; np < &ptable.proc[NPROC]; np++){
|
for(np = proc; np < &proc[NPROC]; np++){
|
||||||
if(np->parent != p)
|
if(np->parent != p)
|
||||||
continue;
|
continue;
|
||||||
|
acquire(&np->lock);
|
||||||
havekids = 1;
|
havekids = 1;
|
||||||
if(np->state == ZOMBIE){
|
if(np->state == ZOMBIE){
|
||||||
// Found one.
|
// Found one.
|
||||||
pid = np->pid;
|
pid = np->pid;
|
||||||
freeproc(np);
|
freeproc(np);
|
||||||
release(&ptable.lock);
|
release(&np->lock);
|
||||||
|
release(&p->lock);
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
release(&np->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No point waiting if we don't have any children.
|
// No point waiting if we don't have any children.
|
||||||
if(!havekids || p->killed){
|
if(!havekids || p->killed){
|
||||||
release(&ptable.lock);
|
release(&p->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for children to exit. (See wakeup1 call in proc_exit.)
|
// Wait for children to exit. (See wakeup1 call in reparent.)
|
||||||
sleep(p, &ptable.lock); //DOC: wait-sleep
|
sleep(p, &p->lock); //DOC: wait-sleep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,29 +416,26 @@ scheduler(void)
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
intr_on();
|
intr_on();
|
||||||
|
|
||||||
// Loop over process table looking for process to run.
|
for(p = proc; p < &proc[NPROC]; p++) {
|
||||||
acquire(&ptable.lock);
|
acquire(&p->lock);
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
if(p->state == RUNNABLE) {
|
||||||
if(p->state != RUNNABLE)
|
// Switch to chosen process. It is the process's job
|
||||||
continue;
|
// to release its lock and then reacquire it
|
||||||
|
// before jumping back to us.
|
||||||
|
p->state = RUNNING;
|
||||||
|
c->proc = p;
|
||||||
|
swtch(&c->scheduler, &p->context);
|
||||||
|
|
||||||
// Switch to chosen process. It is the process's job
|
// Process is done running for now.
|
||||||
// to release ptable.lock and then reacquire it
|
// It should have changed its p->state before coming back.
|
||||||
// before jumping back to us.
|
c->proc = 0;
|
||||||
c->proc = p;
|
}
|
||||||
p->state = RUNNING;
|
release(&p->lock);
|
||||||
|
|
||||||
swtch(&c->scheduler, &p->context);
|
|
||||||
|
|
||||||
// Process is done running for now.
|
|
||||||
// It should have changed its p->state before coming back.
|
|
||||||
c->proc = 0;
|
|
||||||
}
|
}
|
||||||
release(&ptable.lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter scheduler. Must hold only ptable.lock
|
// Enter scheduler. Must hold only p->lock
|
||||||
// and have changed proc->state. Saves and restores
|
// and have changed proc->state. Saves and restores
|
||||||
// intena because intena is a property of this
|
// intena because intena is a property of this
|
||||||
// kernel thread, not this CPU. It should
|
// kernel thread, not this CPU. It should
|
||||||
|
@ -418,8 +448,8 @@ sched(void)
|
||||||
int intena;
|
int intena;
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
|
|
||||||
if(!holding(&ptable.lock))
|
if(!holding(&p->lock))
|
||||||
panic("sched ptable.lock");
|
panic("sched p->lock");
|
||||||
if(mycpu()->noff != 1)
|
if(mycpu()->noff != 1)
|
||||||
panic("sched locks");
|
panic("sched locks");
|
||||||
if(p->state == RUNNING)
|
if(p->state == RUNNING)
|
||||||
|
@ -436,10 +466,11 @@ sched(void)
|
||||||
void
|
void
|
||||||
yield(void)
|
yield(void)
|
||||||
{
|
{
|
||||||
acquire(&ptable.lock); //DOC: yieldlock
|
struct proc *p = myproc();
|
||||||
myproc()->state = RUNNABLE;
|
acquire(&p->lock); //DOC: yieldlock
|
||||||
|
p->state = RUNNABLE;
|
||||||
sched();
|
sched();
|
||||||
release(&ptable.lock);
|
release(&p->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A fork child's very first scheduling by scheduler()
|
// A fork child's very first scheduling by scheduler()
|
||||||
|
@ -449,8 +480,8 @@ forkret(void)
|
||||||
{
|
{
|
||||||
static int first = 1;
|
static int first = 1;
|
||||||
|
|
||||||
// Still holding ptable.lock from scheduler.
|
// Still holding p->lock from scheduler.
|
||||||
release(&ptable.lock);
|
release(&myproc()->lock);
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
// Some initialization functions must be run in the context
|
// Some initialization functions must be run in the context
|
||||||
|
@ -477,14 +508,14 @@ sleep(void *chan, struct spinlock *lk)
|
||||||
if(lk == 0)
|
if(lk == 0)
|
||||||
panic("sleep without lk");
|
panic("sleep without lk");
|
||||||
|
|
||||||
// Must acquire ptable.lock in order to
|
// Must acquire p->lock in order to
|
||||||
// change p->state and then call sched.
|
// change p->state and then call sched.
|
||||||
// Once we hold ptable.lock, we can be
|
// Once we hold p->lock, we can be
|
||||||
// guaranteed that we won't miss any wakeup
|
// guaranteed that we won't miss any wakeup
|
||||||
// (wakeup runs with ptable.lock locked),
|
// (wakeup runs with p->lock locked),
|
||||||
// so it's okay to release lk.
|
// so it's okay to release lk.
|
||||||
if(lk != &ptable.lock){ //DOC: sleeplock0
|
if(lk != &p->lock){ //DOC: sleeplock0
|
||||||
acquire(&ptable.lock); //DOC: sleeplock1
|
acquire(&p->lock); //DOC: sleeplock1
|
||||||
release(lk);
|
release(lk);
|
||||||
}
|
}
|
||||||
// Go to sleep.
|
// Go to sleep.
|
||||||
|
@ -497,32 +528,37 @@ sleep(void *chan, struct spinlock *lk)
|
||||||
p->chan = 0;
|
p->chan = 0;
|
||||||
|
|
||||||
// Reacquire original lock.
|
// Reacquire original lock.
|
||||||
if(lk != &ptable.lock){ //DOC: sleeplock2
|
if(lk != &p->lock){ //DOC: sleeplock2
|
||||||
release(&ptable.lock);
|
release(&p->lock);
|
||||||
acquire(lk);
|
acquire(lk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//PAGEBREAK!
|
//PAGEBREAK!
|
||||||
// Wake up all processes sleeping on chan.
|
// Wake up p, used by exit()
|
||||||
// The ptable lock must be held.
|
// Caller should lock p.
|
||||||
static void
|
static void
|
||||||
wakeup1(void *chan)
|
wakeup1(struct proc *p)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
if(p->chan == p && p->state == SLEEPING) {
|
||||||
|
p->state = RUNNABLE;
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
|
}
|
||||||
if(p->state == SLEEPING && p->chan == chan)
|
|
||||||
p->state = RUNNABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wake up all processes sleeping on chan.
|
// Wake up all processes sleeping on chan. Never
|
||||||
|
// called when holding a p->lock
|
||||||
void
|
void
|
||||||
wakeup(void *chan)
|
wakeup(void *chan)
|
||||||
{
|
{
|
||||||
acquire(&ptable.lock);
|
struct proc *p;
|
||||||
wakeup1(chan);
|
|
||||||
release(&ptable.lock);
|
for(p = proc; p < &proc[NPROC]; p++) {
|
||||||
|
acquire(&p->lock);
|
||||||
|
if(p->state == SLEEPING && p->chan == chan) {
|
||||||
|
p->state = RUNNABLE;
|
||||||
|
}
|
||||||
|
release(&p->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill the process with the given pid.
|
// Kill the process with the given pid.
|
||||||
|
@ -533,18 +569,19 @@ kill(int pid)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
|
|
||||||
acquire(&ptable.lock);
|
for(p = proc; p < &proc[NPROC]; p++){
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
|
||||||
if(p->pid == pid){
|
if(p->pid == pid){
|
||||||
|
acquire(&p->lock);
|
||||||
|
if(p->pid != pid)
|
||||||
|
panic("kill");
|
||||||
p->killed = 1;
|
p->killed = 1;
|
||||||
// Wake process from sleep if necessary.
|
// Wake process from sleep if necessary.
|
||||||
if(p->state == SLEEPING)
|
if(p->state == SLEEPING)
|
||||||
p->state = RUNNABLE;
|
p->state = RUNNABLE;
|
||||||
release(&ptable.lock);
|
release(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
release(&ptable.lock);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +623,6 @@ procdump(void)
|
||||||
{
|
{
|
||||||
static char *states[] = {
|
static char *states[] = {
|
||||||
[UNUSED] "unused",
|
[UNUSED] "unused",
|
||||||
[EMBRYO] "embryo",
|
|
||||||
[SLEEPING] "sleep ",
|
[SLEEPING] "sleep ",
|
||||||
[RUNNABLE] "runble",
|
[RUNNABLE] "runble",
|
||||||
[RUNNING] "run ",
|
[RUNNING] "run ",
|
||||||
|
@ -595,7 +631,7 @@ procdump(void)
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
char *state;
|
char *state;
|
||||||
|
|
||||||
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
|
for(p = proc; p < &proc[NPROC]; p++){
|
||||||
if(p->state == UNUSED)
|
if(p->state == UNUSED)
|
||||||
continue;
|
continue;
|
||||||
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
|
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
|
||||||
|
|
|
@ -78,10 +78,11 @@ struct trapframe {
|
||||||
/* 280 */ uint64 t6;
|
/* 280 */ uint64 t6;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
enum procstate { UNUSED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
||||||
|
|
||||||
// Per-process state
|
// Per-process state
|
||||||
struct proc {
|
struct proc {
|
||||||
|
struct spinlock lock;
|
||||||
char *kstack; // Bottom of kernel stack for this process
|
char *kstack; // Bottom of kernel stack for this process
|
||||||
uint64 sz; // Size of process memory (bytes)
|
uint64 sz; // Size of process memory (bytes)
|
||||||
pagetable_t pagetable; // Page table
|
pagetable_t pagetable; // Page table
|
||||||
|
|
|
@ -304,6 +304,15 @@ w_tp(uint64 x)
|
||||||
asm volatile("mv tp, %0" : : "r" (x));
|
asm volatile("mv tp, %0" : : "r" (x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint64
|
||||||
|
r_ra()
|
||||||
|
{
|
||||||
|
uint64 x;
|
||||||
|
asm volatile("mv %0, ra" : "=r" (x) );
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define PGSIZE 4096 // bytes per page
|
#define PGSIZE 4096 // bytes per page
|
||||||
#define PGSHIFT 12 // bits of offset within a page
|
#define PGSHIFT 12 // bits of offset within a page
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "proc.h"
|
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
#include "proc.h"
|
||||||
#include "sleeplock.h"
|
#include "sleeplock.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -5,5 +5,7 @@ struct spinlock {
|
||||||
// For debugging:
|
// For debugging:
|
||||||
char *name; // Name of lock.
|
char *name; // Name of lock.
|
||||||
struct cpu *cpu; // The cpu holding the lock.
|
struct cpu *cpu; // The cpu holding the lock.
|
||||||
|
struct cpu *last_release;
|
||||||
|
uint64 last_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
#define T_DEVICE 3 // Device
|
#define T_DEVICE 3 // Device
|
||||||
|
|
||||||
struct stat {
|
struct stat {
|
||||||
short type; // Type of file
|
|
||||||
int dev; // File system's disk device
|
int dev; // File system's disk device
|
||||||
uint ino; // Inode number
|
uint ino; // Inode number
|
||||||
|
short type; // Type of file
|
||||||
short nlink; // Number of links to file
|
short nlink; // Number of links to file
|
||||||
uint size; // Size of file in bytes
|
uint64 size; // Size of file in bytes
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
@ -170,7 +171,9 @@ dosyscall(void)
|
||||||
|
|
||||||
num = p->tf->a7;
|
num = p->tf->a7;
|
||||||
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
|
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
|
||||||
|
//printf("%d: syscall %d\n", p->pid, num);
|
||||||
p->tf->a0 = syscalls[num]();
|
p->tf->a0 = syscalls[num]();
|
||||||
|
//printf("%d: syscall %d -> %d\n", p->pid, num, p->tf->a0);
|
||||||
} else {
|
} else {
|
||||||
printf("%d %s: unknown sys call %d\n",
|
printf("%d %s: unknown sys call %d\n",
|
||||||
p->pid, p->name, num);
|
p->pid, p->name, num);
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "stat.h"
|
#include "stat.h"
|
||||||
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "spinlock.h"
|
|
||||||
#include "sleeplock.h"
|
#include "sleeplock.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
|
#include "spinlock.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "proc.h"
|
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
struct spinlock tickslock;
|
struct spinlock tickslock;
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "proc.h"
|
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
|
#include "proc.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -9,6 +9,7 @@ kernel/date.h
|
||||||
|
|
||||||
# entering xv6
|
# entering xv6
|
||||||
kernel/entry.S
|
kernel/entry.S
|
||||||
|
kernel/start.c
|
||||||
kernel/main.c
|
kernel/main.c
|
||||||
|
|
||||||
# locks
|
# locks
|
||||||
|
@ -24,6 +25,7 @@ kernel/kalloc.c
|
||||||
|
|
||||||
# system calls
|
# system calls
|
||||||
user/usys.pl
|
user/usys.pl
|
||||||
|
kernel/kernelvec.S
|
||||||
kernel/trap.c
|
kernel/trap.c
|
||||||
kernel/syscall.h
|
kernel/syscall.h
|
||||||
kernel/syscall.c
|
kernel/syscall.c
|
||||||
|
|
|
@ -43,7 +43,7 @@ ls(char *path)
|
||||||
|
|
||||||
switch(st.type){
|
switch(st.type){
|
||||||
case T_FILE:
|
case T_FILE:
|
||||||
printf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size);
|
printf(1, "%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_DIR:
|
case T_DIR:
|
||||||
|
|
|
@ -68,6 +68,8 @@ printf(int fd, const char *fmt, ...)
|
||||||
} else if(state == '%'){
|
} else if(state == '%'){
|
||||||
if(c == 'd'){
|
if(c == 'd'){
|
||||||
printint(fd, va_arg(ap, int), 10, 1);
|
printint(fd, va_arg(ap, int), 10, 1);
|
||||||
|
} else if(c == 'l') {
|
||||||
|
printint(fd, va_arg(ap, uint64), 10, 0);
|
||||||
} else if(c == 'x') {
|
} else if(c == 'x') {
|
||||||
printint(fd, va_arg(ap, int), 16, 0);
|
printint(fd, va_arg(ap, int), 16, 0);
|
||||||
} else if(c == 'p') {
|
} else if(c == 'p') {
|
||||||
|
|
Loading…
Reference in a new issue