Home CS439

CS439: Principles of Computer Systems

Homework 3, Part 1

Due: 8:45a Friday, February 13, 2015

Part 1 of the homeworks must be submitted electronically. Please refer to the homework turnin instructions.

  1. When executing system or library calls from multi-threaded code, it is important to know which calls are re-entrant and which are not.
    • What is the meaning of re-entrant?
    • How does a re-entrant call behave differently from a call that is not re-entrant?
    • Why is this an important consideration for multi-threaded code?
  2. In the code below, indicate where each variable is stored (e.g., stack, heap, static data segment), and whether that variable would be shared by the threads in a multi-threaded program. If applicable, indicate where the space that variable points to is allocated.

    int i;      
    char * j;   
    void foo(int a){
       int b;            
       static float c;   
       /*do stuff*/
    int main(int argc, char**argv){
       int * m;   
       int g;     
       double z;  
       j = malloc(MAXBUF*sizeof(char));
       createThread(0, foo(), 2);
       createThread(1, foo(), 4);
       /*do stuff*/
  3. Consider a uniprocessor kernel that user programs can trap into using system calls. The kernel receive and handles interrupts from I/O devices. Would there be any need for critical sections within that kernel?
  4. System Calls vs. Procedure Calls: How much more expensive is a system call than a procedure call? Write a simple test program to compare the cost of a simple procedure call to a simple system call ("getuid()" is a good candidate on UNIX; see the man page.) (Note: be careful to prevent the optimizing compiler from "optimizing out" your procedure calls. Do not compile with optimization on.)
    • Explain the difference (if any) between the time required by your simple procedure call and simple system call by discussing what work each call must do (be specific). [Note: Do not provide the source code for your program, just the results].

    Hint: You should use system calls such as gethrtime() or gettimeofday() for time measurements. Design your code such that the measurement overhead is negligible. Also, be aware that timer values in some systems have limited resolution (e.g., millisecond resolution).

  5. A standardized C language threads programming interface has been developed for UNIX systems, IEEE POSIX 1003.1c. Thread implementations that adhere to this standard are known as POSIX threads, or Pthreads. Using Pthreads, write a C program that creates three new threads and assigns each of them a number. Each thread should print the numbers 1-10, one per line, with its number beginning the line, so that the beginning output from thread 1 would look like the following:
    1: 1
    1: 2
    1: 3
    The original thread should wait for the new threads to finish and then print a statement notifying the user that the application is finished.

    Explain the output. Turn in your code, output, and explanation.

    Hint: man 7 pthreads provides an overview of pthreads and should help you get started. Notice that to compile code that uses pthreads you need to include the -pthread flag.