summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/kernel/sched.h2
-rw-r--r--include/kernel/sys.h6
-rw-r--r--include/time.h2
-rw-r--r--include/unistd.h4
-rw-r--r--kernel/sched.c23
-rw-r--r--kernel/sys.c16
-rw-r--r--kernel/timer.s4
-rw-r--r--kernel/traps.s8
-rw-r--r--lib/pause.c3
-rw-r--r--lib/time.c2
-rw-r--r--usrbin/main.c28
11 files changed, 85 insertions, 13 deletions
diff --git a/include/kernel/sched.h b/include/kernel/sched.h
index 3d6699c..6b0488e 100644
--- a/include/kernel/sched.h
+++ b/include/kernel/sched.h
@@ -50,6 +50,7 @@ struct task_struct {
pid_t pid;
int state;
uint32_t signal;
+ unsigned int alarm;
void *sig_handlers[NRSIG];
struct tss_struct tss;
} __attribute__((packed));
@@ -58,5 +59,6 @@ extern struct task_struct *ctask;
extern uint32_t ticks;
void sched_init(void);
+void reschedule(void);
#endif
diff --git a/include/kernel/sys.h b/include/kernel/sys.h
index 2ec4490..ba2dc0c 100644
--- a/include/kernel/sys.h
+++ b/include/kernel/sys.h
@@ -6,6 +6,8 @@ extern int sys_getpid(void);
extern int sys_getpdir(void);
extern int sys_signal(void);
extern int sys_rsputs(void);
+extern int sys_alarm(void);
+extern int sys_pause(void);
extern int sys_dummy(void);
syscall_t call_table[256] = {
@@ -15,8 +17,8 @@ syscall_t call_table[256] = {
[3] = &sys_getpdir,
[4] = &sys_signal,
[5] = &sys_rsputs,
- [6] = &sys_dummy,
- [7] = &sys_dummy,
+ [6] = &sys_alarm,
+ [7] = &sys_pause,
[8] = &sys_dummy,
[9] = &sys_dummy,
[10] = &sys_dummy,
diff --git a/include/time.h b/include/time.h
index 732d33f..feb2225 100644
--- a/include/time.h
+++ b/include/time.h
@@ -10,6 +10,8 @@ typedef int32_t time_t;
time_t time(void);
+int alarm(unsigned int seconds);
+
void sleep(time_t);
#endif
diff --git a/include/unistd.h b/include/unistd.h
index a784e22..30d41c6 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -11,6 +11,8 @@ typedef uint16_t pid_t;
#define __SYS_getpdir 3
#define __SYS_signal 4
#define __SYS_rsputs 5
+#define __SYS_alarm 6
+#define __SYS_pause 7
#define _syscall0(type, name) \
type name(void) { \
@@ -37,4 +39,6 @@ typedef uint16_t pid_t;
pid_t getpid(void);
void *getpdir(void);
+int pause(void);
+
#endif
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
diff --git a/lib/pause.c b/lib/pause.c
new file mode 100644
index 0000000..1e316df
--- /dev/null
+++ b/lib/pause.c
@@ -0,0 +1,3 @@
+#include <unistd.h>
+
+_syscall0(int, pause);
diff --git a/lib/time.c b/lib/time.c
index 42ee601..0f4a251 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -3,6 +3,8 @@
_syscall0(time_t, time);
+_syscall1(int, alarm, unsigned int, seconds);
+
void sleep(time_t t) {
time_t start = time();
diff --git a/usrbin/main.c b/usrbin/main.c
index 2afcf0e..8c8d2dc 100644
--- a/usrbin/main.c
+++ b/usrbin/main.c
@@ -1,15 +1,37 @@
+#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
-void main(void) {
- int x = 0;
+void sighandler(int sig) {
+ printf("Caught SIGALRM!\n");
+}
- printf("We did it ma!\n");
+void pid1(void) {
+ signal(SIGALRM, &sighandler);
+ alarm(2);
+ pause();
+ printf("Alarm expired!\n");
+ pause();
+
+ while(1)
+ printf("It's didn't work!\n");
+}
+
+void pid2(void) {
+ int x = 0;
while(1) {
sleep(1);
printf("0x%04x:0x%08x: 0x%08x, 0x%08x\n", getpid(), (uint32_t) getpdir(), time(), x++);
}
}
+
+void main(void) {
+ printf("We did it ma!\n");
+
+ if(getpid() == 1)
+ pid1();
+ pid2();
+}