Merge branch 'riscv' into uvm-perm
This commit is contained in:
commit
ccb7bd14c7
|
@ -89,7 +89,7 @@ consoleread(int user_dst, uint64 dst, int n)
|
||||||
// wait until interrupt handler has put some
|
// wait until interrupt handler has put some
|
||||||
// input into cons.buffer.
|
// input into cons.buffer.
|
||||||
while(cons.r == cons.w){
|
while(cons.r == cons.w){
|
||||||
if(myproc()->killed){
|
if(killed(myproc())){
|
||||||
release(&cons.lock);
|
release(&cons.lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,8 @@ void proc_mapstacks(pagetable_t);
|
||||||
pagetable_t proc_pagetable(struct proc *);
|
pagetable_t proc_pagetable(struct proc *);
|
||||||
void proc_freepagetable(pagetable_t, uint64);
|
void proc_freepagetable(pagetable_t, uint64);
|
||||||
int kill(int);
|
int kill(int);
|
||||||
|
int killed(struct proc*);
|
||||||
|
void setkilled(struct proc*);
|
||||||
struct cpu* mycpu(void);
|
struct cpu* mycpu(void);
|
||||||
struct cpu* getmycpu(void);
|
struct cpu* getmycpu(void);
|
||||||
struct proc* myproc();
|
struct proc* myproc();
|
||||||
|
@ -132,9 +134,9 @@ int strncmp(const char*, const char*, uint);
|
||||||
char* strncpy(char*, const char*, int);
|
char* strncpy(char*, const char*, int);
|
||||||
|
|
||||||
// syscall.c
|
// syscall.c
|
||||||
int argint(int, int*);
|
void argint(int, int*);
|
||||||
int argstr(int, char*, int);
|
int argstr(int, char*, int);
|
||||||
int argaddr(int, uint64 *);
|
void argaddr(int, uint64 *);
|
||||||
int fetchstr(uint64, char*, int);
|
int fetchstr(uint64, char*, int);
|
||||||
int fetchaddr(uint64, uint64*);
|
int fetchaddr(uint64, uint64*);
|
||||||
void syscall();
|
void syscall();
|
||||||
|
|
|
@ -573,6 +573,7 @@ dirlookup(struct inode *dp, char *name, uint *poff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a new directory entry (name, inum) into the directory dp.
|
// Write a new directory entry (name, inum) into the directory dp.
|
||||||
|
// Returns 0 on success, -1 on failure (e.g. out of disk blocks).
|
||||||
int
|
int
|
||||||
dirlink(struct inode *dp, char *name, uint inum)
|
dirlink(struct inode *dp, char *name, uint inum)
|
||||||
{
|
{
|
||||||
|
@ -597,7 +598,7 @@ dirlink(struct inode *dp, char *name, uint inum)
|
||||||
strncpy(de.name, name, DIRSIZ);
|
strncpy(de.name, name, DIRSIZ);
|
||||||
de.inum = inum;
|
de.inum = inum;
|
||||||
if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
|
if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de))
|
||||||
panic("dirlink");
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ pipewrite(struct pipe *pi, uint64 addr, int n)
|
||||||
|
|
||||||
acquire(&pi->lock);
|
acquire(&pi->lock);
|
||||||
while(i < n){
|
while(i < n){
|
||||||
if(pi->readopen == 0 || pr->killed){
|
if(pi->readopen == 0 || killed(pr)){
|
||||||
release(&pi->lock);
|
release(&pi->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ piperead(struct pipe *pi, uint64 addr, int n)
|
||||||
|
|
||||||
acquire(&pi->lock);
|
acquire(&pi->lock);
|
||||||
while(pi->nread == pi->nwrite && pi->writeopen){ //DOC: pipe-empty
|
while(pi->nread == pi->nwrite && pi->writeopen){ //DOC: pipe-empty
|
||||||
if(pr->killed){
|
if(killed(pr)){
|
||||||
release(&pi->lock);
|
release(&pi->lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ userinit(void)
|
||||||
int
|
int
|
||||||
growproc(int n)
|
growproc(int n)
|
||||||
{
|
{
|
||||||
uint sz;
|
uint64 sz;
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
|
|
||||||
sz = p->sz;
|
sz = p->sz;
|
||||||
|
@ -390,7 +390,7 @@ exit(int status)
|
||||||
int
|
int
|
||||||
wait(uint64 addr)
|
wait(uint64 addr)
|
||||||
{
|
{
|
||||||
struct proc *np;
|
struct proc *pp;
|
||||||
int havekids, pid;
|
int havekids, pid;
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
|
|
||||||
|
@ -399,32 +399,32 @@ wait(uint64 addr)
|
||||||
for(;;){
|
for(;;){
|
||||||
// Scan through table looking for exited children.
|
// Scan through table looking for exited children.
|
||||||
havekids = 0;
|
havekids = 0;
|
||||||
for(np = proc; np < &proc[NPROC]; np++){
|
for(pp = proc; pp < &proc[NPROC]; pp++){
|
||||||
if(np->parent == p){
|
if(pp->parent == p){
|
||||||
// make sure the child isn't still in exit() or swtch().
|
// make sure the child isn't still in exit() or swtch().
|
||||||
acquire(&np->lock);
|
acquire(&pp->lock);
|
||||||
|
|
||||||
havekids = 1;
|
havekids = 1;
|
||||||
if(np->state == ZOMBIE){
|
if(pp->state == ZOMBIE){
|
||||||
// Found one.
|
// Found one.
|
||||||
pid = np->pid;
|
pid = pp->pid;
|
||||||
if(addr != 0 && copyout(p->pagetable, addr, (char *)&np->xstate,
|
if(addr != 0 && copyout(p->pagetable, addr, (char *)&pp->xstate,
|
||||||
sizeof(np->xstate)) < 0) {
|
sizeof(pp->xstate)) < 0) {
|
||||||
release(&np->lock);
|
release(&pp->lock);
|
||||||
release(&wait_lock);
|
release(&wait_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
freeproc(np);
|
freeproc(pp);
|
||||||
release(&np->lock);
|
release(&pp->lock);
|
||||||
release(&wait_lock);
|
release(&wait_lock);
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
release(&np->lock);
|
release(&pp->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 || killed(p)){
|
||||||
release(&wait_lock);
|
release(&wait_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -603,6 +603,25 @@ kill(int pid)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setkilled(struct proc *p)
|
||||||
|
{
|
||||||
|
acquire(&p->lock);
|
||||||
|
p->killed = 1;
|
||||||
|
release(&p->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
killed(struct proc *p)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
acquire(&p->lock);
|
||||||
|
k = p->killed;
|
||||||
|
release(&p->lock);
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy to either a user address, or kernel address,
|
// Copy to either a user address, or kernel address,
|
||||||
// depending on usr_dst.
|
// depending on usr_dst.
|
||||||
// Returns 0 on success, -1 on error.
|
// Returns 0 on success, -1 on error.
|
||||||
|
|
|
@ -12,7 +12,7 @@ int
|
||||||
fetchaddr(uint64 addr, uint64 *ip)
|
fetchaddr(uint64 addr, uint64 *ip)
|
||||||
{
|
{
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
if(addr >= p->sz || addr+sizeof(uint64) > p->sz)
|
if(addr >= p->sz || addr+sizeof(uint64) > p->sz) // both tests needed, in case of overflow
|
||||||
return -1;
|
return -1;
|
||||||
if(copyin(p->pagetable, (char *)ip, addr, sizeof(*ip)) != 0)
|
if(copyin(p->pagetable, (char *)ip, addr, sizeof(*ip)) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -25,9 +25,8 @@ int
|
||||||
fetchstr(uint64 addr, char *buf, int max)
|
fetchstr(uint64 addr, char *buf, int max)
|
||||||
{
|
{
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
int err = copyinstr(p->pagetable, buf, addr, max);
|
if(copyinstr(p->pagetable, buf, addr, max) < 0)
|
||||||
if(err < 0)
|
return -1;
|
||||||
return err;
|
|
||||||
return strlen(buf);
|
return strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,21 +53,19 @@ argraw(int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the nth 32-bit system call argument.
|
// Fetch the nth 32-bit system call argument.
|
||||||
int
|
void
|
||||||
argint(int n, int *ip)
|
argint(int n, int *ip)
|
||||||
{
|
{
|
||||||
*ip = argraw(n);
|
*ip = argraw(n);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve an argument as a pointer.
|
// Retrieve an argument as a pointer.
|
||||||
// Doesn't check for legality, since
|
// Doesn't check for legality, since
|
||||||
// copyin/copyout will do that.
|
// copyin/copyout will do that.
|
||||||
int
|
void
|
||||||
argaddr(int n, uint64 *ip)
|
argaddr(int n, uint64 *ip)
|
||||||
{
|
{
|
||||||
*ip = argraw(n);
|
*ip = argraw(n);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the nth word-sized system call argument as a null-terminated string.
|
// Fetch the nth word-sized system call argument as a null-terminated string.
|
||||||
|
@ -78,8 +75,7 @@ int
|
||||||
argstr(int n, char *buf, int max)
|
argstr(int n, char *buf, int max)
|
||||||
{
|
{
|
||||||
uint64 addr;
|
uint64 addr;
|
||||||
if(argaddr(n, &addr) < 0)
|
argaddr(n, &addr);
|
||||||
return -1;
|
|
||||||
return fetchstr(addr, buf, max);
|
return fetchstr(addr, buf, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,7 @@ argfd(int n, int *pfd, struct file **pf)
|
||||||
int fd;
|
int fd;
|
||||||
struct file *f;
|
struct file *f;
|
||||||
|
|
||||||
if(argint(n, &fd) < 0)
|
argint(n, &fd);
|
||||||
return -1;
|
|
||||||
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
|
if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(pfd)
|
if(pfd)
|
||||||
|
@ -73,7 +72,9 @@ sys_read(void)
|
||||||
int n;
|
int n;
|
||||||
uint64 p;
|
uint64 p;
|
||||||
|
|
||||||
if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argaddr(1, &p) < 0)
|
argaddr(1, &p);
|
||||||
|
argint(2, &n);
|
||||||
|
if(argfd(0, 0, &f) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return fileread(f, p, n);
|
return fileread(f, p, n);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +86,9 @@ sys_write(void)
|
||||||
int n;
|
int n;
|
||||||
uint64 p;
|
uint64 p;
|
||||||
|
|
||||||
if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argaddr(1, &p) < 0)
|
argaddr(1, &p);
|
||||||
|
argint(2, &n);
|
||||||
|
if(argfd(0, 0, &f) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return filewrite(f, p, n);
|
return filewrite(f, p, n);
|
||||||
|
@ -110,7 +113,8 @@ sys_fstat(void)
|
||||||
struct file *f;
|
struct file *f;
|
||||||
uint64 st; // user pointer to struct stat
|
uint64 st; // user pointer to struct stat
|
||||||
|
|
||||||
if(argfd(0, 0, &f) < 0 || argaddr(1, &st) < 0)
|
argaddr(1, &st);
|
||||||
|
if(argfd(0, 0, &f) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return filestat(f, st);
|
return filestat(f, st);
|
||||||
}
|
}
|
||||||
|
@ -268,19 +272,31 @@ create(char *path, short type, short major, short minor)
|
||||||
iupdate(ip);
|
iupdate(ip);
|
||||||
|
|
||||||
if(type == T_DIR){ // Create . and .. entries.
|
if(type == T_DIR){ // Create . and .. entries.
|
||||||
dp->nlink++; // for ".."
|
|
||||||
iupdate(dp);
|
|
||||||
// No ip->nlink++ for ".": avoid cyclic ref count.
|
// No ip->nlink++ for ".": avoid cyclic ref count.
|
||||||
if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
|
if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
|
||||||
panic("create dots");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dirlink(dp, name, ip->inum) < 0)
|
if(dirlink(dp, name, ip->inum) < 0)
|
||||||
panic("create: dirlink");
|
goto fail;
|
||||||
|
|
||||||
|
if(type == T_DIR){
|
||||||
|
// now that success is guaranteed:
|
||||||
|
dp->nlink++; // for ".."
|
||||||
|
iupdate(dp);
|
||||||
|
}
|
||||||
|
|
||||||
iunlockput(dp);
|
iunlockput(dp);
|
||||||
|
|
||||||
return ip;
|
return ip;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
// something went wrong. de-allocate ip.
|
||||||
|
ip->nlink = 0;
|
||||||
|
iupdate(ip);
|
||||||
|
iunlockput(ip);
|
||||||
|
iunlockput(dp);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
|
@ -292,7 +308,8 @@ sys_open(void)
|
||||||
struct inode *ip;
|
struct inode *ip;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0)
|
argint(1, &omode);
|
||||||
|
if((n = argstr(0, path, MAXPATH)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
begin_op();
|
begin_op();
|
||||||
|
@ -375,9 +392,9 @@ sys_mknod(void)
|
||||||
int major, minor;
|
int major, minor;
|
||||||
|
|
||||||
begin_op();
|
begin_op();
|
||||||
|
argint(1, &major);
|
||||||
|
argint(2, &minor);
|
||||||
if((argstr(0, path, MAXPATH)) < 0 ||
|
if((argstr(0, path, MAXPATH)) < 0 ||
|
||||||
argint(1, &major) < 0 ||
|
|
||||||
argint(2, &minor) < 0 ||
|
|
||||||
(ip = create(path, T_DEVICE, major, minor)) == 0){
|
(ip = create(path, T_DEVICE, major, minor)) == 0){
|
||||||
end_op();
|
end_op();
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -419,7 +436,8 @@ sys_exec(void)
|
||||||
int i;
|
int i;
|
||||||
uint64 uargv, uarg;
|
uint64 uargv, uarg;
|
||||||
|
|
||||||
if(argstr(0, path, MAXPATH) < 0 || argaddr(1, &uargv) < 0){
|
argaddr(1, &uargv);
|
||||||
|
if(argstr(0, path, MAXPATH) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(argv, 0, sizeof(argv));
|
memset(argv, 0, sizeof(argv));
|
||||||
|
@ -462,8 +480,7 @@ sys_pipe(void)
|
||||||
int fd0, fd1;
|
int fd0, fd1;
|
||||||
struct proc *p = myproc();
|
struct proc *p = myproc();
|
||||||
|
|
||||||
if(argaddr(0, &fdarray) < 0)
|
argaddr(0, &fdarray);
|
||||||
return -1;
|
|
||||||
if(pipealloc(&rf, &wf) < 0)
|
if(pipealloc(&rf, &wf) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
fd0 = -1;
|
fd0 = -1;
|
||||||
|
|
|
@ -10,8 +10,7 @@ uint64
|
||||||
sys_exit(void)
|
sys_exit(void)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
if(argint(0, &n) < 0)
|
argint(0, &n);
|
||||||
return -1;
|
|
||||||
exit(n);
|
exit(n);
|
||||||
return 0; // not reached
|
return 0; // not reached
|
||||||
}
|
}
|
||||||
|
@ -32,19 +31,17 @@ uint64
|
||||||
sys_wait(void)
|
sys_wait(void)
|
||||||
{
|
{
|
||||||
uint64 p;
|
uint64 p;
|
||||||
if(argaddr(0, &p) < 0)
|
argaddr(0, &p);
|
||||||
return -1;
|
|
||||||
return wait(p);
|
return wait(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64
|
uint64
|
||||||
sys_sbrk(void)
|
sys_sbrk(void)
|
||||||
{
|
{
|
||||||
int addr;
|
uint64 addr;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if(argint(0, &n) < 0)
|
argint(0, &n);
|
||||||
return -1;
|
|
||||||
addr = myproc()->sz;
|
addr = myproc()->sz;
|
||||||
if(growproc(n) < 0)
|
if(growproc(n) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -57,12 +54,11 @@ sys_sleep(void)
|
||||||
int n;
|
int n;
|
||||||
uint ticks0;
|
uint ticks0;
|
||||||
|
|
||||||
if(argint(0, &n) < 0)
|
argint(0, &n);
|
||||||
return -1;
|
|
||||||
acquire(&tickslock);
|
acquire(&tickslock);
|
||||||
ticks0 = ticks;
|
ticks0 = ticks;
|
||||||
while(ticks - ticks0 < n){
|
while(ticks - ticks0 < n){
|
||||||
if(myproc()->killed){
|
if(killed(myproc())){
|
||||||
release(&tickslock);
|
release(&tickslock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -77,8 +73,7 @@ sys_kill(void)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
if(argint(0, &pid) < 0)
|
argint(0, &pid);
|
||||||
return -1;
|
|
||||||
return kill(pid);
|
return kill(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
#
|
#
|
||||||
# code to switch between user and kernel space.
|
# low-level code to handle traps from user space into
|
||||||
|
# the kernel, and returns from kernel to user.
|
||||||
#
|
#
|
||||||
# this code is mapped at the same virtual address
|
# the kernel maps the page holding this code
|
||||||
# (TRAMPOLINE) in user and kernel space so that
|
# at the same virtual address (TRAMPOLINE)
|
||||||
# it continues to work when it switches page tables.
|
# in user and kernel space so that it continues
|
||||||
#
|
# to work when it switches page tables.
|
||||||
# kernel.ld causes this to be aligned
|
# kernel.ld causes this code to start at
|
||||||
# to a page boundary.
|
# a page boundary.
|
||||||
#
|
#
|
||||||
|
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
|
|
||||||
.section trampsec
|
.section trampsec
|
||||||
.globl trampoline
|
.globl trampoline
|
||||||
trampoline:
|
trampoline:
|
||||||
.align 4
|
.align 4
|
||||||
|
@ -31,7 +32,7 @@ uservec:
|
||||||
|
|
||||||
# each process has a separate p->trapframe memory area,
|
# each process has a separate p->trapframe memory area,
|
||||||
# but it's mapped to the same virtual address
|
# but it's mapped to the same virtual address
|
||||||
# (TRAPFRAME) in every process.
|
# (TRAPFRAME) in every process's user page table.
|
||||||
li a0, TRAPFRAME
|
li a0, TRAPFRAME
|
||||||
|
|
||||||
# save the user registers in TRAPFRAME
|
# save the user registers in TRAPFRAME
|
||||||
|
@ -70,29 +71,27 @@ uservec:
|
||||||
csrr t0, sscratch
|
csrr t0, sscratch
|
||||||
sd t0, 112(a0)
|
sd t0, 112(a0)
|
||||||
|
|
||||||
# restore kernel stack pointer from p->trapframe->kernel_sp
|
# initialize kernel stack pointer, from p->trapframe->kernel_sp
|
||||||
ld sp, 8(a0)
|
ld sp, 8(a0)
|
||||||
|
|
||||||
# make tp hold the current hartid, from p->trapframe->kernel_hartid
|
# make tp hold the current hartid, from p->trapframe->kernel_hartid
|
||||||
ld tp, 32(a0)
|
ld tp, 32(a0)
|
||||||
|
|
||||||
# load the address of usertrap(), p->trapframe->kernel_trap
|
# load the address of usertrap(), from p->trapframe->kernel_trap
|
||||||
ld t0, 16(a0)
|
ld t0, 16(a0)
|
||||||
|
|
||||||
# restore kernel page table from p->trapframe->kernel_satp
|
# load the kernel page table, from p->trapframe->kernel_satp
|
||||||
ld t1, 0(a0)
|
ld t1, 0(a0)
|
||||||
csrw satp, t1
|
csrw satp, t1
|
||||||
sfence.vma zero, zero
|
sfence.vma zero, zero
|
||||||
|
|
||||||
# a0 is no longer valid, since the kernel page
|
|
||||||
# table does not specially map p->tf.
|
|
||||||
|
|
||||||
# jump to usertrap(), which does not return
|
# jump to usertrap(), which does not return
|
||||||
jr t0
|
jr t0
|
||||||
|
|
||||||
.globl userret
|
.globl userret
|
||||||
userret:
|
userret:
|
||||||
# userret(pagetable)
|
# userret(pagetable)
|
||||||
|
# called by usertrapret() in trap.c to
|
||||||
# switch from kernel to user.
|
# switch from kernel to user.
|
||||||
# a0: user page table, for satp.
|
# a0: user page table, for satp.
|
||||||
|
|
||||||
|
|
|
@ -53,15 +53,15 @@ usertrap(void)
|
||||||
if(r_scause() == 8){
|
if(r_scause() == 8){
|
||||||
// system call
|
// system call
|
||||||
|
|
||||||
if(p->killed)
|
if(killed(p))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
||||||
// sepc points to the ecall instruction,
|
// sepc points to the ecall instruction,
|
||||||
// but we want to return to the next instruction.
|
// but we want to return to the next instruction.
|
||||||
p->trapframe->epc += 4;
|
p->trapframe->epc += 4;
|
||||||
|
|
||||||
// an interrupt will change sstatus &c registers,
|
// an interrupt will change sepc, scause, and sstatus,
|
||||||
// so don't enable until done with those registers.
|
// so enable only now that we're done with those registers.
|
||||||
intr_on();
|
intr_on();
|
||||||
|
|
||||||
syscall();
|
syscall();
|
||||||
|
@ -70,10 +70,10 @@ usertrap(void)
|
||||||
} else {
|
} else {
|
||||||
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
|
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
|
||||||
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
||||||
p->killed = 1;
|
setkilled(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p->killed)
|
if(killed(p))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
||||||
// give up the CPU if this is a timer interrupt.
|
// give up the CPU if this is a timer interrupt.
|
||||||
|
@ -101,7 +101,7 @@ usertrapret(void)
|
||||||
w_stvec(trampoline_uservec);
|
w_stvec(trampoline_uservec);
|
||||||
|
|
||||||
// set up trapframe values that uservec will need when
|
// set up trapframe values that uservec will need when
|
||||||
// the process next re-enters the kernel.
|
// the process next traps into the kernel.
|
||||||
p->trapframe->kernel_satp = r_satp(); // kernel page table
|
p->trapframe->kernel_satp = r_satp(); // kernel page table
|
||||||
p->trapframe->kernel_sp = p->kstack + PGSIZE; // process's kernel stack
|
p->trapframe->kernel_sp = p->kstack + PGSIZE; // process's kernel stack
|
||||||
p->trapframe->kernel_trap = (uint64)usertrap;
|
p->trapframe->kernel_trap = (uint64)usertrap;
|
||||||
|
|
|
@ -92,22 +92,18 @@ uartputc(int c)
|
||||||
for(;;)
|
for(;;)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
while(uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE){
|
||||||
while(1){
|
|
||||||
if(uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE){
|
|
||||||
// buffer is full.
|
// buffer is full.
|
||||||
// wait for uartstart() to open up space in the buffer.
|
// wait for uartstart() to open up space in the buffer.
|
||||||
sleep(&uart_tx_r, &uart_tx_lock);
|
sleep(&uart_tx_r, &uart_tx_lock);
|
||||||
} else {
|
}
|
||||||
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
|
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
|
||||||
uart_tx_w += 1;
|
uart_tx_w += 1;
|
||||||
uartstart();
|
uartstart();
|
||||||
release(&uart_tx_lock);
|
release(&uart_tx_lock);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// alternate version of uartputc() that doesn't
|
// alternate version of uartputc() that doesn't
|
||||||
// use interrupts, for use by kernel printf() and
|
// use interrupts, for use by kernel printf() and
|
||||||
// to echo characters. it spins waiting for the uart's
|
// to echo characters. it spins waiting for the uart's
|
||||||
|
|
|
@ -62,7 +62,8 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regexp matcher from Kernighan & Pike,
|
// Regexp matcher from Kernighan & Pike,
|
||||||
// The Practice of Programming, Chapter 9.
|
// The Practice of Programming, Chapter 9, or
|
||||||
|
// https://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html
|
||||||
|
|
||||||
int matchhere(char*, char*);
|
int matchhere(char*, char*);
|
||||||
int matchstar(int, char*, char*);
|
int matchstar(int, char*, char*);
|
||||||
|
|
|
@ -9,7 +9,7 @@ int write(int, const void*, int);
|
||||||
int read(int, void*, int);
|
int read(int, void*, int);
|
||||||
int close(int);
|
int close(int);
|
||||||
int kill(int);
|
int kill(int);
|
||||||
int exec(char*, char**);
|
int exec(const char*, char**);
|
||||||
int open(const char*, int);
|
int open(const char*, int);
|
||||||
int mknod(const char*, short, short);
|
int mknod(const char*, short, short);
|
||||||
int unlink(const char*);
|
int unlink(const char*);
|
||||||
|
|
|
@ -2738,6 +2738,8 @@ diskfull(char *s)
|
||||||
int fi;
|
int fi;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
|
unlink("diskfulldir");
|
||||||
|
|
||||||
for(fi = 0; done == 0; fi++){
|
for(fi = 0; done == 0; fi++){
|
||||||
char name[32];
|
char name[32];
|
||||||
name[0] = 'b';
|
name[0] = 'b';
|
||||||
|
@ -2763,6 +2765,39 @@ diskfull(char *s)
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now that there are no free blocks, test that dirlink()
|
||||||
|
// merely fails (doesn't panic) if it can't extend
|
||||||
|
// directory content.
|
||||||
|
int nzz = 128;
|
||||||
|
for(int i = 0; i < nzz; i++){
|
||||||
|
char name[32];
|
||||||
|
name[0] = 'z';
|
||||||
|
name[1] = 'z';
|
||||||
|
name[2] = '0' + (i / 32);
|
||||||
|
name[3] = '0' + (i % 32);
|
||||||
|
name[4] = '\0';
|
||||||
|
unlink(name);
|
||||||
|
int fd = open(name, O_CREATE|O_RDWR|O_TRUNC);
|
||||||
|
if(fd < 0){
|
||||||
|
printf("%s: could not create file %s\n", s, name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir("diskfulldir");
|
||||||
|
unlink("diskfulldir");
|
||||||
|
|
||||||
|
for(int i = 0; i < nzz; i++){
|
||||||
|
char name[32];
|
||||||
|
name[0] = 'z';
|
||||||
|
name[1] = 'z';
|
||||||
|
name[2] = '0' + (i / 32);
|
||||||
|
name[3] = '0' + (i % 32);
|
||||||
|
name[4] = '\0';
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < fi; i++){
|
for(int i = 0; i < fi; i++){
|
||||||
char name[32];
|
char name[32];
|
||||||
name[0] = 'b';
|
name[0] = 'b';
|
||||||
|
|
Loading…
Reference in a new issue