Part A: Both the above solution to the dining philosopher's problem and the solution in Figure 2.20 of the text are deadlock free. In addition, both allow two philosophers to eat at once. Tannenbaum's solution always allows two non-adjacent philosophers to eat, while the salt-shaker solution will sometimes allow only one philosopher to eat, because that philosopher's neighbor could take the second saltshaker.
The salt-shaker solution does prevent starvation so long as the semaphore waiting queues are fair (FIFO and random are both fair). Tannenbaum's solution appears not to solve the starvation problem -- two philosophers can take turns eating, preventing the philosopher between them from ever being able to eat.
Part B: Consider the following implementation of the think() operation for use under our example thread package:
/**** * dining philosophers * * ****/ #include#include "threads.h" void random_wait() { int i; do { thread_relinquish(); while (random() & 7); } #define eat random_wait #define think random_wait semaphore saltshaker; semaphore forks[5]; void philosopher( int i ) { for (;;) { think(); thread_wait( &salt_shaker ); thread_wait( &forks[i] ); thread_wait( &forks[(i+1)%5] ); eat(); thread_signal( &salt_shaker ); thread_signal( &forks[i] ); thread_signal( &forks[(i+1)%5] ); } } int main() { int i; srandom( getpid() ); /* makes runs somewhat nondeterministic */ thread_manager_init(); thread_semaphore_init( &salt_shaker, 2 ); for (i=0; i<5; i++) { thread_semaphore_init( &forks[i], 1 ); thread_launch( 4000, philosopher, i ); } thread_manager_start(); }
The MMU has t TLB entries, the main memory has space for f page frames, and the address space allows p pages, where t < f < p. Each TLB entry has three fields, a valid bit, a page number, and a frame number.
The MMU will request a page fault if no TLB entry contains a valid entry matching the page requested. If two valid TLB entries match, the MMU will behave nondeterministically.
Part A: What data structures are required to implement clock replacement under this hardware? Give as much detail as possible, given only the above information.
To implement clock replacement on this machine, we need:
Part B:
page_fault_trap_handler() get va, the virtual address that caused the trap extract p, the page number, from va if not page_table[p].valid then abort application program!!! else if page_table[p].state = on_disk -- we have a real page fault!!! -- find a page to replace clock_hand = clock_hand + 1 while frame_table[clock_hand].mark = marked frame_table[clock_hand].mark = unmarked p' = frame_table[clock_hand].page_number if page_table[p'].state = in_TLB TLB[page_table[p'].TLB_entry].valid = false page_table[p'].state = in_frame endif -- note, because of above, -- all unmarked pages are not in the TLB! endloop -- write that page out p' = frame_table[clock_hand].page_number write p' from frame selected by clock_hand to disk, at address page_table[p'].disk_address page_table[p'].state = on_disk -- read in the page we need read p into frame selected by clock_hand from disk, at address page_table[p].disk_address page_table[p'].state = in_frame page_table[p'].frame_number = clock_hand else if page_table[p].state = in_frame -- we have a TLB soft page fault!!! -- really stupid TLB replacement algorithm -- we should really hunt up an invalid TLB entry TLB_hand = TLB_hand + 1 if TLB[TLB_hand].valid = true then -- evict TLB entry page_table[TLB[TLB_hand].page_number].state = in_frame TLB[TLB_hand].valid = false endif -- make valid TLB entry TLB[TLB_hand].page_number = p TLB[TLB_hand].frame_number = page_table[p].frame_number TLB[TLB_hand].valid = true -- set the mark bit! frame_table[page_table[p].frame_number].mark = marked endif return