LECTURE 15: Thursday, Week 8
Scribe Noters:
   Tanya Gillis
   Stefan Vainberg
   Yahya Fahimuddin
Better page replacement policy
	- if it's good enough, then Belody's Anomaly should never occur
 
	
What is the optimal page replacement policy?
Ex. ref string: 0  1  2  3  0  1  4  0  1  2  3  4
| A | 
f0 | 
0 | 
0 | 
0 | 
0 | 
0 | 
0 | 
0 | 
0 | 
f2 | 
2 | 
2 | 
| B | 
 | 
f1 | 
1 | 
1 | 
1 | 
1 | 
1 | 
1 | 
1 | 
1 | 
f3 | 
3 | 
| C | 
 | 
 | 
f2 | 
f3 | 
3 | 
3 | 
f4 | 
4 | 
4 | 
4 | 
4 | 
4 | 
Total: 7 faults
- look into the future to find the page you don't need for the longest time- that page will fault
 
- is there an approimation to the next page fault?
 
Least recently used:
- if a page has been used a lot, it probably will be used more
 
- LRU assumes temporal locality of reference
 
- accessing page i @ time t -> high probabilty of accessing page i at times: t+1, t+2, t+3...
 
Ex. using LRU on the previous example:
ref string:	0  1  2  3  0  1  4  0  1  2  3  4
| A | 
f0 | 
0 | 
0 | 
f3 | 
3 | 
3 | 
3 | 
3 | 
f4 | 
4 | 
f2 | 
2 | 
| B | 
 | 
f1 | 
1 | 
1 | 
f0 | 
0 | 
0 | 
0 | 
0 | 
0 | 
f3 | 
3 | 
| C | 
 | 
 | 
f2 | 
2 | 
2 | 
f1 | 
1 | 
1 | 
1 | 
1 | 
1 | 
f4 | 
Total: 10 faults
How to implement LRU:
A)
- Mark all PTE's as pointing to inaccessible pages
 
- a page fault on every access
 
- kernel stores timestamps for that page. will this work?
 
	- it will be slow and have loops!
 
B)
 
    *p = syscall load(p)
	load tells content of location
	*p =v,  syscall store(p,v)
- clock interrupt (every 10ms, or so)
 
	
	
	
- how about:
 
	
	
	
-> have hardware update PTE on each access
Optimizations for paging:
Demand paging: 
    - load just 1 page of program into RAM
  
	- mark other PTEs as inaccessible
 
	- run!
 
+ program starts faster
vs
load 1st N pages at once, where N is the number of pages in the program that fit.
+ better batching
vs
Dirty Bit Optimization:
code inside kernel to do paging:
void pfault(int va, )
{
	    if (swapmap (va, current) == FaIL)
	       kill (current, SIGSEGV)
	    else {
	       (p,va)=removal_policy()
	       pa = p_pmap(va)
	       write pa to disk at swapmap(va',p)
	       read pa from disk_swapmap
	       current -> p_pmap(v)=pa
	   }
}
int swapmap(va,p)
{
	   return disk address for va 
	   or
	   FAIL
}
- Assume no thrashing
 
- U = # of pages used. 1 <= U <= N
 
- C = cost of reading a page
 
- demand paging, startup cost
 
- demand F+C
 
- w/o demand NC
 
- program cost = U(F+C) if U
  
-  program cost = NC if U == N 
 
When can we skip dirty bit test?
- if the page hasn't changed
 
- hardware support for dirty bit
 
	- whenever you store into page, set dirty bit to 1 if it's not 1 already
 
	- more commonly implemented
 
	- we can do this in the kernel (if no hardware support)
 
	- mark pages as read-only at first
 
	- set own dirty bit as needed on page faults & mark page read-write
 
	- some pages are naturally read-only
 
	
	- this can be shared between parent and child
 
 
	
	- child+parent share page table. parent is frozen until child execvp() or _exit(). child must not mess with RAM in any way that will mess up the parent
 
Distributed Systems + RPC: 
so far: modularity via virtualization
now: modularity via message passing:
 
implement message passing atop conventional virtual kernel
also do it by having multiple machines
+ flexibility
- performance
simple message-passing model
Remote Procedure Call:
- requester executes a procedure call.
 
- response = p(request) like a syscall in that body is executed elsewhere
 
Properties of RPC:
- caller & callee don't share address space
 
	
	- - noall by reference: call by value only
 
- caller & callee need not share machine architecture x86 caller, space callee
 
	- - no shipping machine code
 
	
caller args, callee results
marshalling- taking a structure and converting it to sequence of bytes (efficient, not bloated, easy to generate, easy to parse)
callee args, caller results
unmarshalling- reverse
what you want (as a programmer) is an API
Ex.
r = arctan(x,y)
double arctan(double, double);
50 lines of code
Programs can take API and generate stubs
Examples of RPC:
 
RPC failure modes:
- message can get lost
 
- "	        " duplicated
 
- "             " delivered out of order
 
- network might be down/slow
 
- server might be "        "
 
- messages can be corrupted (checksum + report error)
 
Solutions:
- message is lost:
 
- -> resend, keep trying until you get resp.
 
	
- -> return an error at most once RPC
 
exactly once RPC is not doable