Sistemas Operativos 3MIEEC

Problem Set #4: POSIX Threads (Part 1)


Questions

  1. Consider the multi-threaded Web server presented in the last lecture. In principle, it would be possible to make a similar implementation using processes rather than threads. What is the advantage of using threads rather than processes?
  2. In the lecture slides I wrote:
    Simplifying, whereas a process abstracts a program execution, a thread abstracts the execution of a function
    Explain this statement, taking into account the POSIX threads API.
  3. According to pthread_create()'s prototype, the prototype of the function to be executed by the newly created thread is:
    void *fun(void *arg)
    1. Why is the type of both the argument and the return value of this function void *?
    2. How can one obtain the value returned by this function?
    3. Explain why a thread should not return the address of an automatic variable declared in fun?
    4. In Unix/Linux, when a process terminates, the value it returns can be received by the parent process only? Does the POSIX API have similar restrictions?

Problems

Note To compile thread-based programs you must use the -pthread compiler option. This ensures linking with the libpthread library and with the thread-safe functions of the C library.

IMP. Follow an incremental code development approach. If you write all the code in a single go and only then compile it, you risk spending the following 15 minutes eliminating the compilation errors and the remaining class debugging it. Instead, you should add code step by step, compiling it and testing it, after each step.

  1. Write a multi-threaded program that gets two integers from the command line and creates 4 threads, each of which computes the result of one arithmetic operation on those two integers different from the arithmetic operation computed by the other threads.

    1. In a first version, the threads shall get the operands via global variables and shall print on the stdout a string displaying the operation in infix notation and the result of that operation.
    2. Write a new version in which the operands are passed as arguments to the threads. (Use an array for two of the threads, and a struct for the other two.)
    3. Write yet a new version, in which each thread returns the result of the operation via global variables. The output to the stdout is done by the main thread, rather than the thread that computes the result.
    4. Write the last version, in which each thread returns the result of the operation via the return value of its function. The output to the stdout is done by the main thread, rather than the thread that computes the result.
  2. Write a program whose main thread creates 3 other threads. Each ot these threads (different from the main thread) shall write its pid and tid and terminate returning an integer number between 1 and 3 and different from the value returned by the other threads. The main thread shall print in the standard out its pid and the value returned by each of the other threads.
    1. What is the relation between the pids of the different threads of a single program? And between its tids?
    2. What happens if the main thread does not wait for the remainder? Try it.
    3. IMP. Do not forget to develop your code gradually. E.g.:

      1. create the threads without arguments, and test it
      2. wait for the threads in a simple way (without obtaining return values), and test it
      3. pass arguments to the threads and test it
      4. return values from the threads and test it

  3. Write a new version of the previous program in which the number of threads, n, is passed as a command line argument. Each thread, different from the main one, shall write its tid and terminate returning an integer between 1 and n different from the value returned by the remaining threads.

    Hint: Use strtol to convert the command line argument to an integer.

    Test your program with different values for n.

  4. Write a multi-threaded program to initialize an integer array.

    Your program shall accept 2 integer arguments: the number of array elements and the number of threads that will initialize the array, in that order.

    The main thread shall process the command line arguments and create the threads that will initialize the array. After the initialization of the array, the main thread shall print all array elements.

    The array shall be divided in parts of approximately the same size, and each of these parts shall be initialized by a different thread. Array element i shall be initialized with the integer value i.

    Hint: Identify the information that each thread needs to process its sub-array and define a data structure that the main thread shall pass as an argument to the remainder threads.