diff options
| -rw-r--r-- | include/kernel/sched.h | 2 | ||||
| -rw-r--r-- | include/kernel/sys.h | 6 | ||||
| -rw-r--r-- | include/time.h | 2 | ||||
| -rw-r--r-- | include/unistd.h | 4 | ||||
| -rw-r--r-- | kernel/sched.c | 23 | ||||
| -rw-r--r-- | kernel/sys.c | 16 | ||||
| -rw-r--r-- | kernel/timer.s | 4 | ||||
| -rw-r--r-- | kernel/traps.s | 8 | ||||
| -rw-r--r-- | lib/pause.c | 3 | ||||
| -rw-r--r-- | lib/time.c | 2 | ||||
| -rw-r--r-- | usrbin/main.c | 28 |
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); @@ -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(); +} |
