xv6, line by line
lab 5
Lab 55 sigalarm and sigreturn: calling a user handler from a timer

Lab 5 · reveal · 19 steps · 8 commits

sigalarm and sigreturn: calling a user handler from a timer: the reference solution

You add two system calls. sigalarm(n, handler) asks the kernel to call handler in user space after every n timer ticks of CPU time the process uses; sigreturn(), called at the end of the handler, puts the process back exactly where the timer interrupted it, with every register as it was. sigalarm(0, 0) turns the alarm off. It is a small version of what Unix calls a signal: the kernel makes a running program jump to a function it never called, then makes it carry on as if nothing had happened.

About sixty lines of kernel code (not counting comments), and almost every one of them touches something central. You will decide what “a tick of this process” means when three harts each take their own timer interrupt but only hart 0 advances ticks. You will find out where the hart decides which user instruction comes next, and whether you can change it from usertrap. You will decide what to save so that the interrupted code notices nothing, and where to keep it. Along the way: is user address 0 a valid handler? What happens to a0 when sigreturn, itself a system call, returns a value? And what if the handler runs longer than its interval?

Each step shows one change on the branch ext/05-sigalarm, the code around it, and the state of the machine when that code runs.

The route
  1. 1Two new numbers kernel/syscall.h
  2. 2sys_sigalarm records three numbers kernel/sysproc.c
  3. 3The state is private to the process kernel/proc.h
  4. 4Counting ticks where the process is known kernel/trap.c
  5. 5Why not next to ticks++? kernel/trap.c
  6. 6Redirecting the return to the handler kernel/trap.c
  7. 7A second trapframe in struct proc kernel/proc.h
  8. 8prepare_return puts the handler in sepc kernel/trap.c
  9. 9sret lands at address 0 kernel/trampoline.S
  10. 10sigreturn copies the frame back kernel/sysproc.c
  11. 11The return value lands in a0 kernel/syscall.c
  12. 12No delivery while the handler runs kernel/trap.c
  13. 13sigreturn only inside a handler kernel/sysproc.c
  14. 14exec turns the alarm off kernel/exec.c
  15. 15freeproc clears the alarm kernel/proc.c
  16. 16A handler at address 0 user/alarmtest.c
  17. 17Checking 26 registers at once user/alarmtest.c
  18. 18Keeping a0 live on purpose user/alarmtest.c
  19. 19Measuring the rate user/alarmrate.c

Keys: ← → step · Home start