CS354 Fall 2000

Final Exam

Name:

Part 1. Answer True/False (T/F) (1 point each)

____ Spin-locks need kernel support.
____ Semaphores should be initialized with numbers greater than 0.
____ The number of page tables in a computer is equal to the number of CPUs.
____ All threads in a process share the same page table.
____ In segment-swap entire processes are swapped in and out from disk.
____ The page-table register is updated every time there is a context switch from one thread to another.
____ Page sizes are always a power of two.
____ In demand paging a virtual address is divided into page number and page offset.
____ A physical page that is replaced is always written back to the backing store.
____ All virtual memory is backed by swap space.
____ The flag PTHREAD_SCOPE_PROCESS is used to create a kernel thread.
____ a.out is an executable format used on Windows.
____ truss is a command to transfer files in UNIX systems.
____ The data section of a program is memory mapped readable, writable and executable.
____ Most of the processes in a computer are in ready state.
____ There is at most one running process in the computer.
____ Most of the CPU time is spent in kernel mode.
____ TLBs speed up the translation from physical to virtual addresses.
____ A small time quantum will cause a program to take more time.
____ The arguments of a system call are checked in user space.
____ In non-preemptive scheduling a program may have a context switch at any time.
____ A program that runs with preemptive scheduling runs faster than one in non-preemptive scheduling.
____ Most of the processes' CPU bursts are completed before the time quantum expires.
____ There is only one page-table register in every computer.
____ Programs that run with SJF have a smaller response time than FCFS.
____ read() is a system call but close() is not.
____ A pipe that is used to communicate a parent and a child process could be created by the child.
____ pthread_create() by default creates user-level threads.
____ In the bounded buffer problem solution using semaphores, the readBuffer() procedure waits on a semaphore that is initialized to the number of buffers available.
____ cond_wait() unlocks the mutex lock that is passed as a parameter.

Part 2. Short Questions (4 pts)

1. What are the advantages and disadvantages of using threads vs. processes.
 
 
 
 
 
 

2. Why it is important to make small the critical sections that mutex locks protect?
 
 
 
 
 
 
 
 

3. Describe the problems involved using malloc and free.
 
 
 
 
 
 
 
 

4. Write the code of the test_and_set operation, and the code of the spin_lock()/spin_unlock().
 
 
 
 
 
 
 
 

5. Write the steps for servicing a page-fault.
 
 
 
 
 
 
 

6. Explain how fork() benefits from using copy-on-write.
 
 
 
 
 
 

7. Explain how execvp() benefits from using virtual memory by memory mapping the text segment.
 
 
 
 
 
 

8. The following three threads have access to five databases. Each database has its own mutex lock. a) Give an example of how these three threads can enter into a deadlock and b) explain how this can be prevented.
 

thread1()
{
    while (1) {
      mutex_lock( &mutex_db5);
      mutex_lock( &mutex_db2);
      mutex_lock( &mutex_db4);

      // Access db5, db2, db4

      mutex_unlock( &mutex_db5);
      mutex_unlock( &mutex_db2);
      mutex_unlock( &mutex_db4);
    }
}
 

thread2()
{
    while (1) {
      mutex_lock( &mutex_db1);
      mutex_lock( &mutex_db6);
      mutex_lock( &mutex_db5);

      // Access db1, db6, db5
 

      mutex_unlock( &mutex_db1);
      mutex_unlock( &mutex_db6);
      mutex_unlock( &mutex_db5);
    }
}
 

thread3()
{
    while (1) {
      mutex_lock( &mutex_db4);
      mutex_lock( &mutex_db7);
      mutex_lock( &mutex_db1);

      // Access db4, db7, db1

      mutex_unlock( &mutex_db4);
      mutex_unlock( &mutex_db7);
      mutex_unlock( &mutex_db1);
    }
}
 
 
 
 

9. Assume the following 2-level page table. Translate the VM address 0x00801578 to its corresponding physical address. Assume a page size of 4KB and that the first 10 bits of the VM address index the level 1 page table, the next 10 bits index the second level and the bits left are the page offset, similar to what was discussed in class. Assume a 32-bit word size. The third column in the level 2 page tables are physical page addresses.(5 pts)

VM Address 0x00801578 is _______________ in Physical Memory
 

Level 1
0 0x38000
1 0x36000
2 0x32000
3 0x40000
Level 2
At 0x38000 0 0x42000 
1 0x50000
2 0x70000

 
Level 2
At 0x32000 0 0x56000
1 0x58000
2 0x72000

 
Level 2
At 0x36000 0x5a000
1 0x5c000
2 0x62000
Level 2
At 0x40000 0x89000
1 0x82000
2 0x86000

 
 
 
 
 

10. The following procedure insert()adds an item to the list pointed by head. If insert() is used by two threads, a) give one sequence of steps that can corrupt the list. You may use the labels (1) to (4) at the left of each instruction to describe your solution. b) Add  the mutex_lock/mutex_unlock() calls to the code to solve the list corruption such that they cover the minimum number of steps that form the critical section.
 
 

struct List {
  int val;
  int next;
};

struct List * head = NULL;

void insert( int val )
{
  (1)List tmp = new List;
 

  (2)tmp->val = val;
 

  (3)tmp->next = head;
 

  (4)head = tmp;
 

}

Part 3 Long Questions. (10 points each)

11. The bounded buffer problem that we covered in class has been used for  writing and reading only one buffer at a time. Generalize the bounded buffer to implement the procedures writemany( int wsize, char * wdata) and readmany( int rsize, char * rdata), where writemany will write wsize bytes from wdata to common_buffer and will block if there is no space available in  common_buffer. readmany will read rsize bytes from common_buffer and will block until there is enough data available. writemany/readmany will always write/read consecutive bytes. Feel free to define as many variables as you want. Use semaphores for synchronization. Multiple writer/reader threads may call writemany/readmany.

const int MAX_BUFF_SIZE=256;

char common_buffer[ MAX_BUFF_SIZE]

void writemany( int wsize, char * wdata){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

}
 
 

void readmany( int rsize, char * rdata) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

}
 

12. Write the code for RPCClient::threadServer() from project 2. Try to be as precise as possible.
 


int 
RPCServer::threadServer( RPCServer * s )
{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

}
 


 

13. Complete the class MReadNWriteLock that implements  a generalization of read/write locks. These locks either allow at most M readers or at most N writers but not both. For example, if one thread is holding the lock in write mode, reader threads will have to wait. If one thread is holding the lock in read mode, writer threads will have to wait. It is possible to have up to N writers holding the lock in write mode. If writer thread N+1 tries to write, it will have to wait. It is possible to have up to M reader threads. If thread M+1 tries to read, it will block until another reader thread unlocks the lock. Use condition variables.
 


class MReadNWriteLock {
  /* Add other fields here */
 
 
 
 
 

public:
  MReadNWriteLock( int m, int n );
  readLock();
  writeLock();
  readUnlock();
  writeUnlock();
};

MReadNWriteLock ::MReadNWriteLock ( int m, int n )
{
 
 
 
 
 
 
 

}

MReadNWriteLock ::readLock()
{
 
 
 
 
 
 

}

MReadNWriteLock ::writeLock()
{
 
 
 
 
 
 
 

}

MReadNWriteLock ::readUnlock()
{
 
 
 
 
 
 

}

MReadNWriteLock ::writeUnlock()
{
 
 
 
 
 
 
 

}