summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/cxx.cc6
-rw-r--r--src/kernel/proc/proc.cc32
-rw-r--r--src/kernel/sbi.cc14
-rw-r--r--src/kernel/syscall.cc297
-rw-r--r--src/kernel/timer.cc38
-rw-r--r--src/kernel/trap/handler.cc3
6 files changed, 373 insertions, 17 deletions
diff --git a/src/kernel/cxx.cc b/src/kernel/cxx.cc
index f9541b5..14bfe68 100644
--- a/src/kernel/cxx.cc
+++ b/src/kernel/cxx.cc
@@ -65,4 +65,10 @@ void operator delete[](void *p, unsigned long size)
(void)size;
if (p)
PMM::free_page(p);
+}
+
+void *operator new(unsigned long size, void *ptr)
+{
+ (void)size;
+ return ptr;
} \ No newline at end of file
diff --git a/src/kernel/proc/proc.cc b/src/kernel/proc/proc.cc
index 5db5f7a..6940a3e 100644
--- a/src/kernel/proc/proc.cc
+++ b/src/kernel/proc/proc.cc
@@ -152,7 +152,8 @@ void forkret()
struct cpu *c = mycpu();
c->runqueue->lock.release();
- Drivers::uart_puts("[Proc] forkret: jumping to user.\n");
+ // Debug
+ // Drivers::uart_puts("[Proc] forkret: jumping to user.\n");
// Enter user mode
usertrapret();
@@ -185,6 +186,7 @@ static Proc *allocproc()
p->state = USED;
p->pid = nextpid++;
p->priority = 0;
+ p->killed = 0;
p->cpu = mycpu();
p->cwd = nullptr;
for (int i = 0; i < NOFILE; i++)
@@ -587,6 +589,34 @@ namespace ProcManager
}
}
+ int kill(int pid)
+ {
+ Proc* p;
+ proc_mem_lock.acquire();
+ for (p = proc_list_head; p != nullptr; p = p->all_next)
+ {
+ if (p->pid == pid)
+ {
+ p->killed = 1;
+
+ if (p->state == SLEEPING)
+ {
+ p->state = RUNNABLE;
+
+ struct cpu *c = mycpu();
+ c->runqueue->lock.acquire();
+ c->runqueue->enqueue(p);
+ c->runqueue->lock.release();
+ }
+
+ proc_mem_lock.release();
+ return 0;
+ }
+ }
+ proc_mem_lock.release();
+ return -1;
+ }
+
int growproc(int n)
{
uint64 sz;
diff --git a/src/kernel/sbi.cc b/src/kernel/sbi.cc
index 442d219..9570d74 100644
--- a/src/kernel/sbi.cc
+++ b/src/kernel/sbi.cc
@@ -1,4 +1,5 @@
#include "common/types.h"
+#include "kernel/sbi.h"
namespace SBI
{
@@ -31,4 +32,17 @@ namespace SBI
{
sbi_call(0x54494D45, 0, stime_value, 0, 0);
}
+
+ void sbi_shutdown()
+ {
+ sbi_call(0x53525354, 0, 0, 0, 0);
+ sbi_call(0x08, 0, 0, 0, 0);
+ while (1)
+ ;
+ }
+
+ void sbi_reboot()
+ {
+ sbi_call(SBI_EID_SRST, SBI_FID_SRST_RESET, SBI_SRST_TYPE_COLD_REBOOT, SBI_SRST_REASON_NONE, 0);
+ }
} \ No newline at end of file
diff --git a/src/kernel/syscall.cc b/src/kernel/syscall.cc
index 6af7730..259a5e6 100644
--- a/src/kernel/syscall.cc
+++ b/src/kernel/syscall.cc
@@ -9,6 +9,7 @@
#include "kernel/mm.h"
#include "kernel/trap.h"
#include "kernel/slab.h"
+#include "kernel/sbi.h"
#include "fs/fat32.h"
#include "fs/file.h"
#include "lib/string.h"
@@ -113,12 +114,38 @@ static uint64 sys_open()
if (argstr(0, path, 128) < 0 || argint(1, &omode) < 0)
return -1;
- ip = VFS::namei(path);
+ if (omode & O_CREATE)
+ {
+ ip = VFS::namei(path);
+ if (ip == nullptr)
+ {
+ char name[128];
+ Inode *dp = VFS::nameiparent(path, name);
+ if (dp)
+ {
+ VFS::ilock(dp);
+ ip = dp->create(name, T_FILE, 0, 0);
+ VFS::iunlockput(dp);
+ }
+ }
+ }
+ else
+ {
+ ip = VFS::namei(path);
+ }
+
if (ip == nullptr)
{
return -1;
}
+ VFS::ilock(ip);
+ if ((omode & O_TRUNC) && ip->type == T_FILE)
+ {
+ ip->truncate();
+ }
+ VFS::iunlock(ip);
+
f = FileTable::alloc();
if (f == nullptr)
{
@@ -144,6 +171,128 @@ static uint64 sys_open()
return fd;
}
+static uint64 sys_mkdir()
+{
+ char path[128];
+ if (argstr(0, path, 128) < 0)
+ return -1;
+
+ Inode *ip = VFS::namei(path);
+ if (ip != nullptr)
+ {
+ VFS::iput(ip);
+ return -1; // the dir is exist
+ }
+
+ char name[128];
+ Inode *dp = VFS::nameiparent(path, name);
+ if (dp == nullptr)
+ return -1;
+
+ VFS::ilock(dp);
+ ip = dp->create(name, T_DIR, 0, 0);
+ VFS::iunlockput(dp);
+
+ if (ip == nullptr)
+ return -1;
+
+ VFS::iput(ip);
+ return 0;
+}
+
+static uint64 sys_chdir()
+{
+ char path[128];
+ if (argstr(0, path, 128) < 0)
+ return -1;
+
+ Inode *ip = VFS::namei(path);
+ if (ip == nullptr)
+ return -1;
+
+ VFS::ilock(ip);
+ if (ip->type != T_DIR)
+ {
+ VFS::iunlockput(ip);
+ return -1;
+ }
+ VFS::iunlock(ip);
+
+ struct Proc *p = myproc();
+ VFS::iput(p->cwd); // release old cwd
+ p->cwd = ip; // switch to new cwd
+
+ return 0;
+}
+
+static uint64 sys_dup()
+{
+ int oldfd;
+ if (argint(0, &oldfd) < 0)
+ return -1;
+
+ struct Proc *p = myproc();
+ if (oldfd < 0 || oldfd >= NOFILE || p->ofile[oldfd] == nullptr)
+ return -1;
+
+ struct file *f = FileTable::dup(p->ofile[oldfd]);
+ int newfd = fdalloc(f);
+ if (newfd < 0)
+ {
+ FileTable::close(f); // fdalloc failed
+ return -1;
+ }
+ return newfd;
+}
+
+static uint64 sys_fstat()
+{
+ int fd;
+ uint64 stat_addr;
+
+ if (argint(0, &fd) < 0 || argint(1, (int *)&stat_addr) < 0)
+ return -1;
+
+ struct Proc *p = myproc();
+ if (fd < 0 || fd >= NOFILE || p->ofile[fd] == nullptr)
+ return -1;
+
+ return FileTable::stat(p->ofile[fd], stat_addr);
+}
+
+static uint64 sys_mknod()
+{
+ char path[128];
+ int major, minor;
+
+ if (argstr(0, path, 128) < 0 || argint(1, &major) < 0 || argint(2, &minor) < 0)
+ return -1;
+
+ Inode *ip = VFS::namei(path);
+ if (ip != nullptr)
+ {
+ VFS::iput(ip);
+ return -1;
+ }
+
+ char name[128];
+ Inode *dp = VFS::nameiparent(path, name);
+ if (dp == nullptr)
+ return -1;
+
+ VFS::ilock(dp);
+ ip = dp->create(name, T_DEVICE, major, minor);
+ VFS::iunlockput(dp);
+
+ if (ip == nullptr)
+ return -1;
+
+ VFS::iput(ip);
+ return 0;
+}
+
+
+
static uint64 sys_close()
{
int fd;
@@ -159,6 +308,63 @@ static uint64 sys_close()
return 0;
}
+static uint64 sys_pipe()
+{
+ uint64 fdarray; // int fd[2]
+ struct file *rf, *wf;
+ int fd0, fd1;
+ struct Proc *p = myproc();
+
+ if (argint(0, (int *)&fdarray) < 0)
+ return -1;
+
+ if(Pipe::create_pair(&rf, &wf) < 0)
+ return -1;
+
+ if ((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0)
+ {
+ if (fd0 >= 0)
+ p->ofile[fd0] = nullptr;
+ FileTable::close(rf);
+ FileTable::close(wf);
+ return -1;
+ }
+
+ if (VM::copyout(p->pagetable, fdarray, (char *)&fd0, sizeof(int)) < 0 ||
+ VM::copyout(p->pagetable, fdarray + sizeof(int), (char *)&fd1, sizeof(int)) < 0)
+ {
+ p->ofile[fd0] = nullptr;
+ p->ofile[fd1] = nullptr;
+ FileTable::close(rf);
+ FileTable::close(wf);
+ return -1;
+ }
+ return 0;
+}
+
+static uint64 sys_link()
+{
+ Drivers::uart_puts("Not supported now");
+ return -1;
+}
+
+static uint64 sys_unlink()
+{
+ char path[128], name[128];
+ if (argstr(0, path, 128) < 0)
+ return -1;
+
+ Inode *dp = VFS::nameiparent(path, name);
+ if (!dp)
+ return -1;
+
+ VFS::ilock(dp);
+ int ret = dp->unlink(name);
+ VFS::iunlockput(dp);
+
+ return ret;
+}
+
static uint64 sys_exec()
{
char path[128];
@@ -169,10 +375,7 @@ static uint64 sys_exec()
return -1;
}
- if (argint(1, (int *)&uargv_ptr) < 0)
- {
- return -1;
- }
+ uargv_ptr = argraw(1);
KernelArgv kargv;
@@ -328,6 +531,48 @@ static uint64 sys_sbrk()
return addr;
}
+static uint64 sys_uptime()
+{
+ return Timer::get_ticks();
+}
+
+static uint64 sys_kill()
+{
+ int pid;
+ if (argint(0, &pid) < 0)
+ return -1;
+
+ return ProcManager::kill(pid);
+}
+
+static uint64 sys_sleep()
+{
+ int n;
+ uint64 ticks0;
+
+ if (argint(0, &n) < 0)
+ return -1;
+
+ Spinlock *lk = Timer::get_lock();
+ lk->acquire();
+
+ ticks0 = Timer::get_ticks();
+
+ while (Timer::get_ticks() - ticks0 < (uint64)n)
+ {
+ if (myproc()->killed)
+ {
+ lk->release();
+ return -1;
+ }
+
+ ProcManager::sleep(Timer::get_tick_chan(), lk);
+ }
+
+ lk->release();
+ return 0;
+}
+
static uint64 sys_disk_test()
{
// VirtIO::test_rw();
@@ -349,6 +594,14 @@ static uint64 sys_lseek()
return FileTable::lseek(p->ofile[fd], offset, whence);
}
+static uint64 sys_shutdown()
+{
+ SBI::sbi_shutdown();
+ while (1)
+ ;
+ return 0;
+}
+
void syscall()
{
Proc *p = myproc();
@@ -383,9 +636,7 @@ void syscall()
case SYS_exec:
ret = sys_exec();
if (ret != static_cast<uint64>(-1))
- {
return;
- }
break;
case SYS_exit:
ret = sys_exit();
@@ -405,16 +656,42 @@ void syscall()
case SYS_lseek:
ret = sys_lseek();
break;
- case SYS_pipe:
case SYS_dup:
- case SYS_chdir:
+ ret = sys_dup();
+ break;
case SYS_fstat:
+ ret = sys_fstat();
+ break;
+ case SYS_chdir:
+ ret = sys_chdir();
+ break;
case SYS_mkdir:
+ ret = sys_mkdir();
+ break;
case SYS_mknod:
+ ret = sys_mknod();
+ break;
+ case SYS_pipe:
+ ret = sys_pipe();
+ break;
case SYS_unlink:
+ ret = sys_unlink();
+ break;
case SYS_link:
Drivers::uart_puts("Unimplemented syscall\n");
- ret = static_cast<uint64>(-1);
+ ret = sys_link();
+ break;
+ case SYS_uptime:
+ ret = sys_uptime();
+ break;
+ case SYS_sleep:
+ ret = sys_sleep();
+ break;
+ case SYS_kill:
+ ret = sys_kill();
+ break;
+ case SYS_shutdown:
+ ret = sys_shutdown();
break;
default:
Drivers::uart_puts("Unknown Syscall ID: ");
diff --git a/src/kernel/timer.cc b/src/kernel/timer.cc
index fb871d5..3cbf11e 100644
--- a/src/kernel/timer.cc
+++ b/src/kernel/timer.cc
@@ -1,15 +1,16 @@
#include "common/types.h"
#include "kernel/config.h"
-
-namespace SBI
-{
- void set_timer(uint64 stime_value);
-}
+#include "kernel/spinlock.h"
+#include "kernel/proc.h"
+#include "kernel/sbi.h"
#define INTERVAL 1000000
namespace Timer
{
+ uint64 ticks;
+ Spinlock tickslock;
+
uint64 get_time()
{
uint64 time;
@@ -31,4 +32,31 @@ namespace Timer
sie |= (1L << 5);
asm volatile("csrw sie, %0" : : "r"(sie));
}
+
+ void tick()
+ {
+ tickslock.acquire();
+ ticks++;
+ ProcManager::wakeup(&ticks);
+ tickslock.release();
+ set_next_trigger();
+ }
+
+ uint64 get_ticks()
+ {
+ tickslock.acquire();
+ uint64 t = ticks;
+ tickslock.release();
+ return t;
+ }
+
+ Spinlock *get_lock()
+ {
+ return &tickslock;
+ }
+
+ void *get_tick_chan()
+ {
+ return &ticks;
+ }
} \ No newline at end of file
diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc
index 3fb772e..7e4d11e 100644
--- a/src/kernel/trap/handler.cc
+++ b/src/kernel/trap/handler.cc
@@ -85,7 +85,8 @@ namespace Trap
else if (is_interrupt && code == 5)
{
// Supervisor Timer Interrupt (IRQ 5)
- Timer::set_next_trigger();
+ // Timer::set_next_trigger();
+ Timer::tick();
// w_sip(r_sip() & ~2);
return 2;
}