summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-08-07 15:18:20 +1000
committerJake Mannens <jake72360@gmail.com>2018-08-07 15:18:20 +1000
commit55c31434991a9c7cb20f7df06e4039fdd8f7152b (patch)
tree76628d95755dbd2330964b95f067e296a15783d3
parent3ed830019561a06b0cb98f792cc447a157fd4ef2 (diff)
Fixed a bug where the panic() function called printf() instead of
printk() to notify the user of the kernel panic. This resulted in a system call being made to the kernel itself and the machine not fully halting. Fixed an issue with the serial driver in which the functions rsputs() and rsread() will still attempt a data transfer even if serial_init() failed to detect and initialize a serial port. Added the ability for tasks to be interrupted whilst reading from the serial port. This was done by putting the task into TSTATE_INTERRUPTIBLE instead of TSTATE_UNINTERRUPTIBLE when waiting for data in the serial buffer. Furthermore, a check was introduced after the task wakes up to see if any data was put in the buffer, or if the task was awoken by another source. Changed the type pid_t from an unsigned 16-bit integer to a signed 16-bit integer. This was done to make passing PID's to certain functions easier. Added the new system call sys_kill which will allow one process to send a signal to another. Added the kill_proc() function to sched.c to kill a process. Currently, this works by nullifying the PID field in the process' task structure, marking all the pages mapped to it's address space as free for use, then calling the scheduler to switch to another runnable task (or to idle). Modified the default signal handler within the kernel to now handle the SIGKILL signal by calling kill_proc().
-rw-r--r--include/kernel/sys.h3
-rw-r--r--include/signal.h4
-rw-r--r--include/unistd.h3
-rw-r--r--kernel/memory.c2
-rw-r--r--kernel/panic.s4
-rw-r--r--kernel/sched.c52
-rw-r--r--kernel/serial.c19
-rw-r--r--lib/signal.c4
-rw-r--r--usrbin/main.c16
9 files changed, 97 insertions, 10 deletions
diff --git a/include/kernel/sys.h b/include/kernel/sys.h
index c428c72..2cefd09 100644
--- a/include/kernel/sys.h
+++ b/include/kernel/sys.h
@@ -9,6 +9,7 @@ extern int sys_alarm(void);
extern int sys_pause(void);
extern int sys_ctty(void);
extern int sys_read(void);
+extern int sys_kill(void);
extern int sys_dummy(void);
syscall_t call_table[256] = {
@@ -21,7 +22,7 @@ syscall_t call_table[256] = {
[6] = &sys_pause,
[7] = &sys_ctty,
[8] = &sys_read,
- [9] = &sys_dummy,
+ [9] = &sys_kill,
[10] = &sys_dummy,
[11] = &sys_dummy,
[12] = &sys_dummy,
diff --git a/include/signal.h b/include/signal.h
index fee6c2b..792a342 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -1,6 +1,8 @@
#ifndef _SIGNAL_H
#define _SIGNAL_H
+#include <unistd.h>
+
#define NRSIG 32
#define SIGHUP 1
@@ -32,4 +34,6 @@
void *signal(int, void (*)(int));
+int kill(pid_t, int);
+
#endif
diff --git a/include/unistd.h b/include/unistd.h
index ef6d059..c337e57 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -8,7 +8,7 @@
typedef int32_t ssize_t;
#endif
-typedef uint16_t pid_t;
+typedef int16_t pid_t;
#define __SYS_puts 0
#define __SYS_time 1
@@ -19,6 +19,7 @@ typedef uint16_t pid_t;
#define __SYS_pause 6
#define __SYS_ctty 7
#define __SYS_read 8
+#define __SYS_kill 9
#define _syscall0(type, name) \
type name(void) { \
diff --git a/kernel/memory.c b/kernel/memory.c
index 67ad69c..b369519 100644
--- a/kernel/memory.c
+++ b/kernel/memory.c
@@ -123,5 +123,5 @@ void paging_init(void) {
"or $0x80000000, %%eax\n"
"mov %%eax, %%cr0\n"
:: "a" (&kpdir)
- :);
+ );
}
diff --git a/kernel/panic.s b/kernel/panic.s
index f4e0f26..1f4605d 100644
--- a/kernel/panic.s
+++ b/kernel/panic.s
@@ -7,13 +7,13 @@
;
global panic
-extern printf
+extern printk
panic:
push ebp
mov ebp, esp
push .msg
- call printf
+ call printk
add esp, 4
cli
hlt
diff --git a/kernel/sched.c b/kernel/sched.c
index ae2fb38..c502024 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1,4 +1,5 @@
#include <asm/system.h>
+#include <errno.h>
#include <kernel/con.h>
#include <kernel/kernel.h>
#include <kernel/memory.h>
@@ -6,6 +7,7 @@
#include <signal.h>
#include <string.h>
#include <sys/types.h>
+#include <unistd.h>
/*
* WARNING!
@@ -75,7 +77,7 @@ struct task_struct *create_proc(void *bin, size_t len) {
for(i = 0; i < NRTASKS; i++) {
if(tasks[i].pid == nextpid) {
/* TODO: handle PID exhaustion */
- nextpid++;
+ nextpid = (nextpid + 1) % 0x8000;
if(nextpid == 0)
nextpid++;
i = 0;
@@ -168,11 +170,32 @@ struct task_struct *create_proc(void *bin, size_t len) {
"pushf\n" \
"pop %%eax" \
: "=a" (task->tss.eflags) \
- ::);
+ );
return task;
}
+void kill_proc(struct task_struct *task) {
+ int i, j;
+ uint32_t *x;
+
+ task->pid = 0;
+
+ for(i = 0; i < PGENT; i++) {
+ x = map_page((void*) task->tss.cr3);
+ if(!x[i])
+ continue;
+ x = map_page((void*) (x[i] & 0xFFFFF000));
+ for(j = 0; j < PGENT; j++) {
+ if(x[i] & 1)
+ free_physical_page((void*) (x[i] & 0xFFFFF000));
+ }
+ }
+ free_physical_page((void*) task->tss.cr3);
+
+ reschedule();
+}
+
void sched_init(void) {
int i;
struct task_struct *task;
@@ -236,5 +259,28 @@ void wake_up(struct task_struct **task) {
}
void sighandler_default(uint32_t sig) {
- printk("[kernel] Handling signal 0x%02x for PID 0x%04x\n", sig, ctask->pid);
+ switch(sig) {
+ case SIGKILL:
+ kill_proc(ctask);
+ break;
+ default:
+ printk("[kernel] Handling signal 0x%02x for PID 0x%04x\n", sig, ctask->pid);
+ break;
+ }
+}
+
+int sys_kill(pid_t pid, int sig) {
+ int i;
+
+ if(sig == 0)
+ return 0;
+
+ for(i = 0; i < NRTASKS; i++) {
+ if(tasks[i].pid == pid) {
+ tasks[i].signal |= (1 << (sig - 1));
+ return 0;
+ }
+ }
+
+ return -ESRCH;
}
diff --git a/kernel/serial.c b/kernel/serial.c
index d96359b..911f02c 100644
--- a/kernel/serial.c
+++ b/kernel/serial.c
@@ -1,5 +1,6 @@
#include <asm/interrupt.h>
#include <asm/io.h>
+#include <errno.h>
#include <kernel/con.h>
#include <kernel/sched.h>
#include <sys/types.h>
@@ -24,11 +25,16 @@
extern void rs_isr(void);
+static char present;
+
static char rxbuf[256];
static unsigned rxread, rxwrite;
static struct task_struct *waiting_task;
int rsputs(char *s) {
+ if(!present)
+ return -ENXIO;
+
while(*s) {
rswait();
if(*s == '\n' || *s == '\r') {
@@ -45,6 +51,8 @@ int rsputs(char *s) {
}
void serial_init(void) {
+ present = 0;
+
outb(RSSCRATCH, 0x00);
outb(RSSCRATCH, 0xAA);
if(inb(RSSCRATCH) != 0xAA) {
@@ -75,12 +83,16 @@ void serial_init(void) {
rxread = 0;
rxwrite = 1;
waiting_task = NULL;
+ present = 1;
}
ssize_t rsread(void *buf, size_t len) {
ssize_t n = len;
char *b = buf;
+ if(!present)
+ return -ENXIO;
+
if(len == 0)
return 0;
@@ -88,9 +100,14 @@ ssize_t rsread(void *buf, size_t len) {
if(rxread == rxwrite) {
/* put the current task to sleep */
waiting_task = ctask;
- ctask->state = TSTATE_UNINTERRUPTIBLE;
+ ctask->state = TSTATE_INTERRUPTIBLE;
reschedule();
}
+ /* check again to see if anything was read, or we were interrupted */
+ if(rxread == rxwrite) {
+ waiting_task = NULL;
+ return -EINTR;
+ }
*b++ = rxbuf[rxread];
rxread = rxread + 1 % sizeof(rxbuf);
diff --git a/lib/signal.c b/lib/signal.c
index 343e2cc..b89985a 100644
--- a/lib/signal.c
+++ b/lib/signal.c
@@ -1,11 +1,13 @@
#include <unistd.h>
+_syscall2(int, kill, pid_t, pid, int, sig);
+
void *signal(int sig, void (*func)(int)) {
void *__res;
__asm__ volatile (
"int $0x80"
: "=a" (__res)
: "a" (__SYS_signal), "b" (sig), "c" (func)
- :);
+ );
return __res;
}
diff --git a/usrbin/main.c b/usrbin/main.c
index 31d38c1..d1e3adc 100644
--- a/usrbin/main.c
+++ b/usrbin/main.c
@@ -1,17 +1,31 @@
+#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
+void sighandler(int sig) {
+ printf("Signal received!\n");
+}
+
void pid1(void) {
ssize_t in;
char buf[2] = { 0, 0 };
printf("We did it ma!\n");
+ signal(1, &sighandler);
while(1) {
in = read(buf, 1);
+ if(in <= 0) {
+ if(in == -EINTR) {
+ printf("Read call interrupted!\n");
+ kill(getpid(), SIGKILL);
+ } else {
+ pause();
+ }
+ }
if(in > 0)
puts(buf);
}
@@ -24,6 +38,8 @@ void pid2(void) {
while(1) {
sleep(1);
+ if(time() == 2)
+ kill(1, 1);
printf("0x%04x:0x%08x: 0x%08x, 0x%08x\n", getpid(), (uint32_t) getpdir(), time(), x++);
}
}