Skip to content

Commit

Permalink
HW4 implement per-process CPU tick alarm
Browse files Browse the repository at this point in the history
  • Loading branch information
gw committed Jan 15, 2017
1 parent d8a88df commit d01981b
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 33 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ mkfs: mkfs.c fs.h
.PRECIOUS: %.o

UPROGS=\
_alarmtest\
_cat\
_date\
_echo\
Expand Down
24 changes: 24 additions & 0 deletions alarmtest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "types.h"
#include "stat.h"
#include "user.h"

void periodic();

int
main(int argc, char *argv[])
{
int i;
printf(1, "alarmtest starting\n");
alarm(5, periodic);
for(i = 0; i < 500*500000; i++){
if((i++ % 500000) == 0)
write(2, ".", 1);
}
exit();
}

void
periodic()
{
printf(1, "alarm!\n");
}
2 changes: 1 addition & 1 deletion proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ userinit(void)
extern char _binary_initcode_start[], _binary_initcode_size[];

p = allocproc();

initproc = p;
if((p->pgdir = setupkvm()) == 0)
panic("userinit: out of memory?");
Expand Down
3 changes: 3 additions & 0 deletions proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ struct proc {
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
int elapsed_ticks;
int alarm_ticks;
void (*alarm_fn)();
};

// Process memory is laid out contiguously, low addresses first:
Expand Down
53 changes: 28 additions & 25 deletions syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ extern int sys_wait(void);
extern int sys_write(void);
extern int sys_uptime(void);
extern int sys_date(void);
extern int sys_alarm(void);

static int (*syscalls[])(void) = {
[SYS_fork] = sys_fork,
Expand All @@ -123,32 +124,34 @@ static int (*syscalls[])(void) = {
[SYS_mkdir] = sys_mkdir,
[SYS_close] = sys_close,
[SYS_date] = sys_date,
[SYS_alarm] = sys_alarm,
};

static char *syscall_strings[] = {
[1] = "fork", // In syscall.h, SYS_fork is #define'd as 1
"exit",
"wait",
"pipe",
"read",
"kill",
"exec",
"fstat",
"chdir",
"dup",
"getpid",
"sbrk",
"sleep",
"uptime",
"open",
"write",
"mknod",
"unlink",
"link",
"mkdir",
"close",
"date",
};
// static char *syscall_strings[] = {
// [1] = "fork", // In syscall.h, SYS_fork is #define'd as 1
// "exit",
// "wait",
// "pipe",
// "read",
// "kill",
// "exec",
// "fstat",
// "chdir",
// "dup",
// "getpid",
// "sbrk",
// "sleep",
// "uptime",
// "open",
// "write",
// "mknod",
// "unlink",
// "link",
// "mkdir",
// "close",
// "date",
// "alarm",
// };

void
syscall(void)
Expand All @@ -160,7 +163,7 @@ syscall(void)
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
ret = syscalls[num]();
proc->tf->eax = ret;
cprintf("\n%s -> %x\n", syscall_strings[num], ret);
// cprintf("\n%s -> %x\n", syscall_strings[num], ret);
} else {
cprintf("%d %s: unknown sys call %d\n",
proc->pid, proc->name, num);
Expand Down
1 change: 1 addition & 0 deletions syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_date 22
#define SYS_alarm 23
16 changes: 16 additions & 0 deletions sysproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,19 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}

int
sys_alarm(void)
{
int intrvl; // Clock tick interval
void (*handler)(); // Callback pointer

if(argint(0, &intrvl) < 0 || intrvl <= 0)
return -1;
if(argptr(1, (void*)&handler, sizeof(handler)) < 0)
return -1;

proc->alarm_ticks = intrvl;
proc->alarm_fn = handler;
return 0;
}
30 changes: 28 additions & 2 deletions trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,32 @@ trap(struct trapframe *tf)
wakeup(&ticks);
release(&tickslock);
}
// Per-process ticking, alarm handling, for sys_alarm.
if (proc && (tf->cs & 3) == DPL_USER) {
proc->elapsed_ticks++;
if (proc->alarm_ticks && proc->elapsed_ticks >= proc->alarm_ticks) {
// Trapframe contains the user-prog's eip and esp
// at time of interrupt. We modify those values as if
// the user-prog had called its alarm handler immediately
// before the interrupt. It's hella sketchy to let the kernel
// jump to a user-specified address--we should check that it's
// within the bounds of the proc's address space.

// Place the original user-prog return address on
// the user's stack, as if the user-prog issued a `call`
// instruction.
tf->esp -= 4;
*(uint*)(tf->esp) = tf->eip;

// Make trapret return to the alarmhandler instead
// of the user-prog. When the alarmhandler calls `ret`,
// it will jump to the original user-prog return address
// we placed on the stack above.
tf->eip = (uint)proc->alarm_fn;

proc->elapsed_ticks = 0;
}
}
lapiceoi();
break;
case T_IRQ0 + IRQ_IDE:
Expand All @@ -79,8 +105,8 @@ trap(struct trapframe *tf)
lapiceoi();
break;
case T_PGFLT:
// Check that the PFLA isn't in the guard page below the stack.
cprintf("PFLT\n");
// TODO: Check that the PFLA isn't in the guard page below the stack.
cprintf("PFLT at: %x\n", rcr2());
if ((mem = kalloc()) == 0)
panic("page fault handler OOM\n");

Expand Down
6 changes: 4 additions & 2 deletions trapasm.S
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ alltraps:
pushl %fs
pushl %gs
pushal

# Set up data and per-cpu segments.
movw $(SEG_KDATA<<3), %ax
movw %ax, %ds
Expand All @@ -26,10 +26,12 @@ alltraps:
# Return falls through to trapret...
.globl trapret
trapret:
# Restore context of running process.
# Mirrors lines 7-11 above.
popal
popl %gs
popl %fs
popl %es
popl %ds
addl $0x8, %esp # trapno and errcode
iret
iret # "return from trap"
1 change: 1 addition & 0 deletions user.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ struct stat;
struct rtcdate;

// system calls
int alarm(int, void (*)(void));
int date(struct rtcdate*);
int fork(void);
int exit(void) __attribute__((noreturn));
Expand Down
1 change: 1 addition & 0 deletions usys.S
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
int $T_SYSCALL; \
ret

SYSCALL(alarm)
SYSCALL(fork)
SYSCALL(exit)
SYSCALL(wait)
Expand Down
6 changes: 3 additions & 3 deletions x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ lcr3(uint val)
// Layout of the trap frame built on the stack by the
// hardware and by trapasm.S, and passed to trap().
struct trapframe {
// registers as pushed by pusha
// registers as pushed by pushal in alltraps in trapasm.S
uint edi;
uint esi;
uint ebp;
Expand All @@ -168,9 +168,9 @@ struct trapframe {
ushort padding2;
ushort es;
ushort padding3;
ushort ds;
ushort ds; // This, up to gs above, pushed by alltraps in trapasm.S
ushort padding4;
uint trapno;
uint trapno; // Pushed by vectors.S

// below here defined by x86 hardware
uint err;
Expand Down

0 comments on commit d01981b

Please sign in to comment.