Skip to content

Commit d01981b

Browse files
committed
HW4 implement per-process CPU tick alarm
1 parent d8a88df commit d01981b

File tree

12 files changed

+111
-33
lines changed

12 files changed

+111
-33
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ mkfs: mkfs.c fs.h
160160
.PRECIOUS: %.o
161161

162162
UPROGS=\
163+
_alarmtest\
163164
_cat\
164165
_date\
165166
_echo\

alarmtest.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "types.h"
2+
#include "stat.h"
3+
#include "user.h"
4+
5+
void periodic();
6+
7+
int
8+
main(int argc, char *argv[])
9+
{
10+
int i;
11+
printf(1, "alarmtest starting\n");
12+
alarm(5, periodic);
13+
for(i = 0; i < 500*500000; i++){
14+
if((i++ % 500000) == 0)
15+
write(2, ".", 1);
16+
}
17+
exit();
18+
}
19+
20+
void
21+
periodic()
22+
{
23+
printf(1, "alarm!\n");
24+
}

proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ userinit(void)
8585
extern char _binary_initcode_start[], _binary_initcode_size[];
8686

8787
p = allocproc();
88-
88+
8989
initproc = p;
9090
if((p->pgdir = setupkvm()) == 0)
9191
panic("userinit: out of memory?");

proc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ struct proc {
6363
struct file *ofile[NOFILE]; // Open files
6464
struct inode *cwd; // Current directory
6565
char name[16]; // Process name (debugging)
66+
int elapsed_ticks;
67+
int alarm_ticks;
68+
void (*alarm_fn)();
6669
};
6770

6871
// Process memory is laid out contiguously, low addresses first:

syscall.c

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ extern int sys_wait(void);
9999
extern int sys_write(void);
100100
extern int sys_uptime(void);
101101
extern int sys_date(void);
102+
extern int sys_alarm(void);
102103

103104
static int (*syscalls[])(void) = {
104105
[SYS_fork] = sys_fork,
@@ -123,32 +124,34 @@ static int (*syscalls[])(void) = {
123124
[SYS_mkdir] = sys_mkdir,
124125
[SYS_close] = sys_close,
125126
[SYS_date] = sys_date,
127+
[SYS_alarm] = sys_alarm,
126128
};
127129

128-
static char *syscall_strings[] = {
129-
[1] = "fork", // In syscall.h, SYS_fork is #define'd as 1
130-
"exit",
131-
"wait",
132-
"pipe",
133-
"read",
134-
"kill",
135-
"exec",
136-
"fstat",
137-
"chdir",
138-
"dup",
139-
"getpid",
140-
"sbrk",
141-
"sleep",
142-
"uptime",
143-
"open",
144-
"write",
145-
"mknod",
146-
"unlink",
147-
"link",
148-
"mkdir",
149-
"close",
150-
"date",
151-
};
130+
// static char *syscall_strings[] = {
131+
// [1] = "fork", // In syscall.h, SYS_fork is #define'd as 1
132+
// "exit",
133+
// "wait",
134+
// "pipe",
135+
// "read",
136+
// "kill",
137+
// "exec",
138+
// "fstat",
139+
// "chdir",
140+
// "dup",
141+
// "getpid",
142+
// "sbrk",
143+
// "sleep",
144+
// "uptime",
145+
// "open",
146+
// "write",
147+
// "mknod",
148+
// "unlink",
149+
// "link",
150+
// "mkdir",
151+
// "close",
152+
// "date",
153+
// "alarm",
154+
// };
152155

153156
void
154157
syscall(void)
@@ -160,7 +163,7 @@ syscall(void)
160163
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
161164
ret = syscalls[num]();
162165
proc->tf->eax = ret;
163-
cprintf("\n%s -> %x\n", syscall_strings[num], ret);
166+
// cprintf("\n%s -> %x\n", syscall_strings[num], ret);
164167
} else {
165168
cprintf("%d %s: unknown sys call %d\n",
166169
proc->pid, proc->name, num);

syscall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@
2121
#define SYS_mkdir 20
2222
#define SYS_close 21
2323
#define SYS_date 22
24+
#define SYS_alarm 23

sysproc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,19 @@ sys_uptime(void)
8888
release(&tickslock);
8989
return xticks;
9090
}
91+
92+
int
93+
sys_alarm(void)
94+
{
95+
int intrvl; // Clock tick interval
96+
void (*handler)(); // Callback pointer
97+
98+
if(argint(0, &intrvl) < 0 || intrvl <= 0)
99+
return -1;
100+
if(argptr(1, (void*)&handler, sizeof(handler)) < 0)
101+
return -1;
102+
103+
proc->alarm_ticks = intrvl;
104+
proc->alarm_fn = handler;
105+
return 0;
106+
}

trap.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,32 @@ trap(struct trapframe *tf)
5555
wakeup(&ticks);
5656
release(&tickslock);
5757
}
58+
// Per-process ticking, alarm handling, for sys_alarm.
59+
if (proc && (tf->cs & 3) == DPL_USER) {
60+
proc->elapsed_ticks++;
61+
if (proc->alarm_ticks && proc->elapsed_ticks >= proc->alarm_ticks) {
62+
// Trapframe contains the user-prog's eip and esp
63+
// at time of interrupt. We modify those values as if
64+
// the user-prog had called its alarm handler immediately
65+
// before the interrupt. It's hella sketchy to let the kernel
66+
// jump to a user-specified address--we should check that it's
67+
// within the bounds of the proc's address space.
68+
69+
// Place the original user-prog return address on
70+
// the user's stack, as if the user-prog issued a `call`
71+
// instruction.
72+
tf->esp -= 4;
73+
*(uint*)(tf->esp) = tf->eip;
74+
75+
// Make trapret return to the alarmhandler instead
76+
// of the user-prog. When the alarmhandler calls `ret`,
77+
// it will jump to the original user-prog return address
78+
// we placed on the stack above.
79+
tf->eip = (uint)proc->alarm_fn;
80+
81+
proc->elapsed_ticks = 0;
82+
}
83+
}
5884
lapiceoi();
5985
break;
6086
case T_IRQ0 + IRQ_IDE:
@@ -79,8 +105,8 @@ trap(struct trapframe *tf)
79105
lapiceoi();
80106
break;
81107
case T_PGFLT:
82-
// Check that the PFLA isn't in the guard page below the stack.
83-
cprintf("PFLT\n");
108+
// TODO: Check that the PFLA isn't in the guard page below the stack.
109+
cprintf("PFLT at: %x\n", rcr2());
84110
if ((mem = kalloc()) == 0)
85111
panic("page fault handler OOM\n");
86112

trapasm.S

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ alltraps:
99
pushl %fs
1010
pushl %gs
1111
pushal
12-
12+
1313
# Set up data and per-cpu segments.
1414
movw $(SEG_KDATA<<3), %ax
1515
movw %ax, %ds
@@ -26,10 +26,12 @@ alltraps:
2626
# Return falls through to trapret...
2727
.globl trapret
2828
trapret:
29+
# Restore context of running process.
30+
# Mirrors lines 7-11 above.
2931
popal
3032
popl %gs
3133
popl %fs
3234
popl %es
3335
popl %ds
3436
addl $0x8, %esp # trapno and errcode
35-
iret
37+
iret # "return from trap"

user.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ struct stat;
22
struct rtcdate;
33

44
// system calls
5+
int alarm(int, void (*)(void));
56
int date(struct rtcdate*);
67
int fork(void);
78
int exit(void) __attribute__((noreturn));

0 commit comments

Comments
 (0)