Question |
Max |
Grade |
T/F |
20pts |
|
1-7 |
30 pts |
|
8. |
10 pts. |
|
9. |
10 pts. |
|
10. |
10pts. |
|
11. |
10pts. |
|
12. |
10pts. |
|
Total: |
100pts. |
____ Most of the CPU time is spent in user mode.
____ a.out is an executable file format used in early versions of Windows.
____ The backing-store of the Text segment is swap space.
____ The stack of one thread could potentially be modified by another
thread.
____ Premature frees are a serious problem in short lived programs.
____ A page size has to be a power of 2.
____ The page table register is always updated during a context switch.
____ By default, when a thread calls mutex_lock for the same lock twice,
the second mutex_lock call will be ignored.
____ All pages in physical memory that are replaced are written back
to the disk.
____ The call realloc( NULL, 100) will cause a SEGV.
____ calloc( 8, 1 ) allocates 8 bytes initialized with 1s.
____ BEST FIT is faster than FIRST FIT.
____ Copy on write is used during fork().
____ An object returned by malloc could have an address like 0x100280.
____ The order of mutex_unlock()'s could lead to deadlocks.
____ Most processes in a system are in wait state.
____ Non-accessed pages are prefered for replacement instead of modified
pages.
____ A free list that has two blocks of 20 and 80 bytes has a fragmentation
of 80%.
____ A call to fork() by a process that has two POSIX threads will create
a child process with two threads.
____ During starvation a thread waits for a resource or mutex lock that
may never be available.
2. (4 pts) A parent process P1 calls fork() and creates a child process
P2. Explain step by step what the OS will do when a page is modified
by process P1.
3. (4 pts) Explain how the clock algorithm for page replacement works.
Explain how it is improved using also the modify bit.
4. (4 pts) Give one example of a premature free?
Give one example of a memory leak
5. (4 pts) Assume that we the allocator described in project 7 is used
with the following code:
int * a = (int *) malloc( sizeof(int) ); int * b = (int *) malloc( sizeof(int)); b[ 0 ] = 3; a[ 1 ] = 5; printf( "b=%d\n", b[0] ); free( b );
What is the value printed?
Explain what is going to happen during the free()
call.
6. (5 pts) The following three threads have access to six databases.
Each database has its own mutex lock.
Could the following threads enter in a deadlock? If that is the case
draw the graph that shows the loop that represents this deadlock, and draw
in the right side the code that could prevent the deadlock. Give specific
mutex numbers when drawing the graphs
If the threads cannot enter into a deadlock, give an alteration of the
the mutex_lock call sequence that may lead to a deadlock and draw a graph
with the loop that represents this deadlock.
thread1()7. (5 pts) Add the necessary code to the insert() and removeFirst() functions to make them synchronized. removeFirst() will have to wait if the list is empty. insert() will have to wait if there are already 10 elements in the list. Use condition variables. Add also the variables you need.
{
for ( int i = 0; i < 10000; i++ ) {
for ( int j = 0; j < 2; j++ ) {
for ( int k = 0; k < 2; k++ ) {
mutex_lock( &mutex[ j ]);
mutex_lock( &mutex[ k ]);
// Call some code
mutex_unlock( &mutex[ j ]);
mutex_unlock( &mutex[ k ]);
}
}
}
}
thread2()
{
for ( int i = 0; i < 10000; i++ ) {
for ( int j = 0; j < 2; j++ ) {
for ( int k = 0; k < 2; k++ ) {
mutex_lock( &mutex[ j ]);
mutex_lock( &mutex[ k ]);
// Call some codemutex_unlock( &mutex[ j ]);
mutex_unlock( &mutex[ k ]);}
}}
}
struct List {
int val;
int next;
};struct List * head = NULL;
// More variables
void insert( int val )
{
List tmp = new List;
tmp->val = val;
tmp->next = head;
head = tmp;
}
Struct List * removeFirst()
{
List tmp = head;
head = tmp->next;
}
8. (10 pts) IMPORTANT:
Use condition variables in this problem. Complete the class
MReadNWriteLock that is a generalization of the read/write locks but
that limits the number of readers to M and the number of writers to N.
This kind of locks allows at most M readers or N writers but not both.
For example, if at least one thread is holding the lock in write mode, reader
threads will have to wait but not writer threads. If at least one thread is
holding the lock in read mode, writer threads 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. It is possible to have up
to N writer threads. If thread N+1 tries to write, it will block until another
writer thread unlocks the lock. |
class MReadNWriteLock { /* Add other fields here */ public: MReadNWriteLock ::MReadNWriteLock ( int m ) } void } void } void } void } |
9. ( 10 pts.) From your malloc implementation write the
code that maps the block size to the corresponding free list index. Return
the corresponding list index even if the list is empty. |
int sizeToFreeListIndex( int sizeRequested ) { // Return the index of the corresponding free list from the sizeRequested. // sizeRequested is the size passed to malloc() } |
10. (10 pts.) From your implementation in
project 7, write the code for free(ptr) that determines if the left object
is free and coalesces it with the object being freed if possible. |
void free( char * ptr ) { . . . . // Determine if left object is freed and coalesce with the freed object if possible. } |
11. ( 10 pts.) Write a procedure that executes the function
|
int grepFilter1GrepFilter2( char * filter1, char * file1, char * filter2, char * file2 ) { }
|
12. (10 pts.) IMPORTANT:Use condition
variables and mutex locks for synchronization in this problem. Implement
a name table class using an array of TableEntry struct's. The constructor
NameTable(max) will allocate space for a table with n entries. The function
add(var,val) will block until there is space in the table, then it will search
for an entry in the table that is unused ( _var and _val are NULL) and it
will add the var and val strings in that entry. Duplicated
values are allowed. The function lookupAndRemove(var) will lookup the string var in the table, will clean up the entry from the table, and it will return the corresponding value. If the variable does not exist, lookupAndRemove(var) will wait until that variable is added with the add() function. Add the condition variables and mutexes that are necessary and the code that implements the behavior described. |
struct TableEntry { char * _var; char * _val; // Other variables here class NameTable { // Array of TableEntry entries // Other variables here public:
class NameTable { // Array of TableEntry entries // Other variables here public:
void add(char *var, char *val) {
} char * lookupAndRemove(char * var) {
} };
|