Diagrams from Class 9, thanks to Weiwei Gong:
ex. pid = getpid();
Added notes:
These pictures are OK for both Xinu and UNIX/Linux, but some details are different in the two cases:
· syscall instruction: trap type instruction on UNIX/Linux, plain call instruction for Xinu
· return from kernel execution: iret instruction for interrupt handler return and UNIX/Linux syscall on x86, but Xinu uses plain ret instruction for syscall return
Xinu use of stacks:
· Kernel stack grows on top of user stack starting from a syscall in user code.
· Interrupt stack grows on top of user or kernel stack.
· This all works because a process is only making progress in one activity at a time: a system call in execution means the user code is not making progress, an interrupt means the underlying user and/or kernel code is not making progress. When the interrupt is done, the underlying activity resumes.
UNIX/Linux:
· Each thread has a kernel stack separate from its user stack
· Interrupt stack may be separate or grow on top of kernel stack
Xinu Examples using hw2 solution (thanks to Truong Tran)
Case of plain user stack: worker calls lckwait, a user function:
Breakpoint 1, lckwait (lock={mutex = 86, users = 0x109010}) at lock.c:54
54 return wait(lock.mutex);
(gdb) where
#0 lckwait (lock={mutex = 86, users = 0x109010}) at lock.c:54
#1 0x100ace in worker (c=66 'B', lockp=0x3fd7dc) at test1.c:67
(gdb) c
Continuing.
Case of kernel stack growing on top of user stack, from syscall wait:
Breakpoint 2, enqueue (item=47, tail=223) at ../sys/queue.c:18
18 tptr = &q[tail];
(gdb) where
#0 enqueue (item=47, tail=223) at ../sys/queue.c:18
#1 0x102879 in wait (sem=86) at ../sys/wait.c:28 <--syscall “wait”
#2 0x1008f8 in lckwait (lock={mutex = 86, users = 0x109010}) at lock.c:54
#3 0x100ace in worker (c=66 'B', lockp=0x3fd7dc) at test1.c:67 <---worker process
(gdb) b putc
Breakpoint 3 at 0x102aa2: file ../sys/putc.c, line 17.
(gdb) c
Continuing.
Case of kernel stack growing on top of user stack, from syscall putc
Breakpoint 3, putc (descrp=0, ch=108 'l') at ../sys/putc.c:17
17 if (isbaddev (descrp) )
(gdb) where
#0 putc (descrp=0, ch=108 'l') at ../sys/putc.c:17 <--syscall “putc”
#1 0x100be9 in _doprnt (
fmt=0x100923 "ockkill: see lock.users = %d, nusers = %d\n", args=0x3fd7c0,
func=0x102a94 <putc>, farg=0) at doprnt.c:44
#2 0x100b9f in printf (
fmt=0x100922 "lockkill: see lock.users = %d, nusers = %d\n", args=0)
at printf.c:15
#3 0x100974 in lckkill (lock={mutex = 86, users = 0x109010}, nusers=2) at lock.c:79
#4 0x100a87 in main (argc=0, argv=0x102d70) at test1.c:55 <---main process start
#5 0x101948 in startmain () at ../sys/main.c:18 <--kernel sets up user main
(gdb) b clkint
Breakpoint 6 at 0x100752
(gdb) c
Continuing.
Case of interrupt stack on top of user stack: clock interrupt during printf execution
Breakpoint 6, 0x100752 in clkint () at ../sys/initialize.c:201
201 }
(gdb) where
#0 0x100752 in clkint () at ../sys/initialize.c:201
#1 0x100be9 in _doprnt (fmt=0x100925 "kkill: see lock.users = %d, nusers = %d\n",
args=0x3fd7c0, func=0x102a94 <putc>, farg=0) at doprnt.c:44
#2 0x100b9f in printf (
fmt=0x100922 "lockkill: see lock.users = %d, nusers = %d\n", args=0)
at printf.c:15
#3 0x100974 in lckkill (lock={mutex = 86, users = 0x109010}, nusers=2) at lock.c:79
#4 0x100a87 in main (argc=0, argv=0x102d70) at test1.c:55
#5 0x101948 in startmain () at ../sys/main.c:18