Merge branch 'riscv-proc' into riscv
This commit is contained in:
		
						commit
						2f22a3ed6a
					
				
					 17 changed files with 176 additions and 117 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Frans Kaashoek
						Frans Kaashoek