Midterm Exam

CS354 Spring 2000

Name:


1. (4 pts.) What is a real-time system, a hard real-time system, and a soft real-time system?
 
 
 
 
 

2. (4 pts.) What are the differences between kernel and user mode?
 
 
 
 
 

3. (4 pts.) Why modern CPU's have kernel and user mode?
 
 
 
 
 

4. (4 pts.) Why system calls use software interrupts?
 
 
 
 
 

5. (4 pts.) What are the steps for servicing an interrupt?

 


6. (4 pts.) How many program counters and sets of registers are stored in a single process table entry?
 
 
 
 
 
 

7. (4 pts.) In which state processes are most of the time and in what kind of programs this is not true?
 
 
 
 
 
 

8. (4 pts.) What are the advantages and disadvantages of using threads vs. using processes?
 

 


9. (4 pts.) What factors have to be considered when choosing the length of a quantum time?
 
 
 
 
 

10. (4 pts.) What are the advantages and disadvantages of using spinlocks vs. disable/enable interrupts?
 
 
 
 
 

11. (6 pts.) Write down the code for spinlock() and spinunlock() and explain briefly how it works.
 
 
 
 
 
 
 
 
 
 
 
 
 
 

12. (6 pts.) Assume that a computer executes the following jobs:
 

Process Time needed for completion (ms)
P1 40
P2 5
P3 30

Compute the average waiting time if the following scheduling algorithms are used:

FCFS:

 
SJF:
 
 
 

Round Robin (Quantum=10ms):
 

 

 
13. (6 pts.) Mark the "C" expressions that are quivalent to a[i]. The type of a[i] is not necessarily char.
Expression Mark
a + i  
*(a + i)  
*(a[0] + i)  
*(&a[0] + i)  
*(&a[i])  
&a[i]  
*((char *) &a[0] + i )  
*((char *)&a[0] + i * sizeof(a[0]))  

 
 
 

14. (6 pts.) Write a procedure arrayMapper() , that calls the function func in all the n elements of the array a. The size of each element in the array a is elementSize. The address of the array element is passed to func every time func is called.
typedef void (*FuncPtr)(void * arg);

void arrayMapper( void * a, FuncPtr func, int n, int elementSize)
{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

}


 
15. (6 pts.) The following code implements a concurrent stack. The push() and pop() calls can be called simultaneously by different threads. The push() call blocks until space is available in the stack. The pop() call blocks until data is available in the stack. Insert the necessary semaphore calls to implement this behavior.  Remember to initialize the semaphores in main().

int stackPointer; 
int stack[ MaxStack ]; 
 
 

void push( int a ) 

 

    stack[ stackPointer ] = a; 
    stackPointer++; 
 
 

int pop() 

 

    stackPointer--; 
    int tmp = stack[ stackPointer ]; 
 
 

    return tmp; 
}

main()
{
 
 
 

}


 
16. (6 pts.) The following program consists of two threads: a client thread and a server thread. First the client thread reads the numbers a and b, wakes up the server thread, and then blocks until c is ready. When the server thread wakes up, it adds a and b, assigns the result to c, wakes up the client thread, and then goes to sleep. When the client wakes up, prints the value of c and starts all over again. Complete the following code and insert semaphore calls where necessary.  Remember to initialize the semaphores in main().

 
 

client_thread() 

    while (1) { 
 

        a = input(); 
        b = input(); 
 

        print c; 
 

    } 

server_thread() 

    while (1) { 
 

        c = a + b; 
 

    }
}

main()
{
 
 
 

}
 


 
17. (6 pts.) Complete the procedure redirectStdin( fileName ) to redirect the standard input from file fileName. The procedure will return -1 if any error occurrs or 0 if it succeeds. Look at main() to see how redirectStdin( ) is used. NOTE: ERROR CHECKING IS IMPORTANT. Also notice that the procedure is called redirectStdin and not redirectStdout.
int redirectStdin( char * fileName )
{
 
 
 
 
 
 
 
 
 
 

}

main()
{
    if ( redirectStdin( "myfile" ) < 0 ) {
        perror( "redirectStdout" );
        exit( -1 );
    }

    int n = scanf( "%d", &i );
    if ( n == 1 ) {
        print( "Read i=%d from myfile\n");
    }
    else {
        printf("Error reading i from myfile\n");
    }
}
 


 
 
18. (6 pts.) Complete the procedure redirectStdinFromPipe( command, arg1) that creates a pipe, redirects stdin from the pipe, forks a child process that redirects its output to the pipe, and then executes a command with argument arg1. redirectStdinFromPipe() will return -1 if an error occurrs or 0 if it succeeds.  Look at main() to see how redirectStdinFromPipe( ) is used. NOTE: ERROR CHECKING IS IMPORTANT. Also see that the procedure is called redirectStdinFromPipe and not redirectStdoutToPipe.
int
redirectStdinFromPipe( char * command, char * arg1)
{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

}

int
main()
{
    // The output of "ls /" can be read from stdin
    if ( redirectStdinFromPipe( "ls", "/" ) {
      perror("redirectStdinFromPipe");
      exit(-1);
    }

    /* Put the output of ls in a buffer */
    const int bufferSize = 1024;
    char  buffer[bufferSize];
    read( 1, buffer, bufferSize );
}

 


 
 
19. (6 pts.) Write the instructions necessary to eliminate zombie processes. Your code should print "Child exited" when a child exits.

 
 
 
 
 

int
main()
{
 
 
 
 
 
 
 
 

}

 


 
 
20. (6 pts.) Write the code for the function strcpy().
char * strcpy( char * dest, char * src )
{
 
 
 
 
 
 
 
 
 
 

}