summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-07-30 02:09:12 +1000
committerJake Mannens <jake72360@gmail.com>2018-07-30 02:09:12 +1000
commit902abebefe10e5e8bc9d80b73e46bcb1635f0be8 (patch)
tree303aaed0f6f274e37ee069c120e5e6bec3b5c9c9 /kernel
parent4a91e12af177dc50a2427d335fd522658d821194 (diff)
Fixed a bug where the tick_handler() and sigret() functions did not pass
a pointer to the saved state information to check_signals(). This bug would have only manifested itself if multiple signals were to be processed (sigret) or if a signal had been set during the handling of a timer interrupt (tick_handler) and *ONLY* if switching to the user's own handler since the state information is not needed to invoke the kernel's default signal handler. Implemented alarms for userspace processes. This required significant modification of the scheduler algorithm. When idling waiting for a process that can run, the scheduler now continually checks the alarms and signals of each process and updates their state accordingly. Implemented the sys_alarm system call to set the new 'alarm' field for the calling process. Created the sys_pause system call which changes the state of the calling process to TSTATE_INTERRUPTIBLE, effectively removing it from the scheduler's run queue, putting it to sleep until a signal arrives.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c23
-rw-r--r--kernel/sys.c16
-rw-r--r--kernel/timer.s4
-rw-r--r--kernel/traps.s8
4 files changed, 43 insertions, 8 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 529db61..9f955d2 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -199,12 +199,25 @@ void reschedule(void) {
n = ctaskn;
while(1) {
- n = (n + 1) % NRTASKS;
- if(tasks[n].pid && tasks[n].state == TSTATE_RUNNING)
- break;
- }
+ /* check alarms and signals */
+ for(i = 0; i < NRTASKS; i++) {
+ if(tasks[i].alarm && tasks[i].alarm < ticks) {
+ tasks[i].alarm = 0;
+ tasks[i].signal |= 1 << (SIGALRM - 1);
+ }
+ if(tasks[i].signal && tasks[i].state == TSTATE_INTERRUPTIBLE)
+ tasks[i].state = TSTATE_RUNNING;
+ }
- switch_to(n, &tasks[n]);
+ /* check if a process is ready to run */
+ for(i = 0; i < NRTASKS; i++) {
+ n = (n + 1) % NRTASKS;
+ if(tasks[n].pid && tasks[n].state == TSTATE_RUNNING) {
+ switch_to(n, &tasks[n]);
+ return;
+ }
+ }
+ }
}
void sched_tick(void) {
diff --git a/kernel/sys.c b/kernel/sys.c
index 20494de..c2256c1 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -36,12 +36,26 @@ void *sys_signal(int sig, void (*func)(int)) {
if(sig == SIGKILL || sig == SIGSTOP)
return NULL;
- printk("Task %x registered new signal handler 0x%08x for signal %01x\n", ctask->pid, (uint32_t) func, sig);
ctask->sig_handlers[sig] = func;
return func;
}
+int sys_alarm(unsigned int seconds) {
+ if(!seconds) {
+ ctask->alarm = 0;
+ return 0;
+ }
+
+ ctask->alarm = ticks + (seconds * 100);
+}
+
+int sys_pause(void) {
+ ctask->state = TSTATE_INTERRUPTIBLE;
+ reschedule();
+ return -1;
+}
+
int sys_dummy(void) {
return -ENOSYS;
}
diff --git a/kernel/timer.s b/kernel/timer.s
index b96e1f1..6d95281 100644
--- a/kernel/timer.s
+++ b/kernel/timer.s
@@ -19,6 +19,8 @@ tick_handler:
mov es, ax
mov fs, ax
mov gs, ax
+ ; save a pointer to the state information
+ mov ebx, esp
; handle the timer tick
mov dword [ticked], 1
inc dword [ticks]
@@ -31,7 +33,9 @@ tick_handler:
; if it isn't, call the scheduler
call sched_tick
; handle any pending signals before returning to normal execution
+ push ebx
call check_signals
+ add esp, 4
.end:
; restore the data segment selectors
pop ax
diff --git a/kernel/traps.s b/kernel/traps.s
index 36b3423..0a0d202 100644
--- a/kernel/traps.s
+++ b/kernel/traps.s
@@ -21,8 +21,8 @@ extern ticked
; too.
%define ts_signal 6
-%define ts_sig_handlers 10
-%define ts_tss_esp0 142
+%define ts_sig_handlers 14
+%define ts_tss_esp0 146
%macro SAVE 0
pusha
@@ -323,6 +323,7 @@ check_signals:
shl ebx, cl
xor ebx, 0xFFFFFFFF
and dword [eax+ts_signal], ebx
+ inc ecx
mov ebx, ecx
; calculate offset to the handler function
shl ecx, 2
@@ -374,7 +375,10 @@ check_signals:
ret
sigret:
+ mov ebx, esp
+ push ebx
call check_signals
+ add esp, 4
; restore our original stack frame and reset the TSS's ESP0
mov esp, [eax+ts_tss_esp0]
mov dword [eax+ts_tss_esp0], 0xFFFFFFFF