Homework 7

22C:116, Spring 2002

Due Monday Apr 8, 2002, in class

Douglas W. Jones

Assume the usual general instructions!

  1. Background Consider the example thread package found in:
    http://homepage.cs.uiowa.edu/~dwjones/opsys/threads/
    The classic way to make a symmetric shared-memory multiprocessor-based user-level thread package running under UNIX compatable systems is to have the program fork n-ways, where each of the n processes that are created by this n-way fork attempt to run any ready thread. All data associated with threads is stored in a heap shared by the n processes.

    This relies on the underlying operating system to run each process on a separate CPU, and in effect, it creates an n-cpu virtual multiprocessor to run the user's threads -- independently of the number of physical processors on the underlying system.

    Sharable segments in UNIX appropriate for this use are created by a call to shmget(IPC_PRIVATE) and they are attached to the address space of the process by shmat(). Prior to termination, a process may call shmdt() to detatch a shared segment, and shmctl(IPC_RMID) should be used prior to termination of the multithreaded application to delete the shared segment. If the shared segment is attached prior to the fork operation, it will remain attached to all child processes.

    Assume someone has written mutual exclusion primitives called spin_lock(vp) and spin_unlock(vp); these take pointers to spinlocks (vp in the examples) as parameters and have the obvious semantics.

    Part A: Which of the functions in the example thread package should perform the shmget(), shmat(), and fork() kernel calls? The thread_manager_init() and thread_manager_start() functions, but which kernel calls go in which function, and why?

    Part B: Can the built-in heap manager of the C programming environment, malloc(), be used to manage the shared heap, or must the thread package include a new heap manager for this purpose?

    Part C: Several key static variables are used in the implementation of the thread manager, among them, current and readylist. Must one or both of these be shared by all n of the processes used to run threads? Must one or both of these be private? If some of these must be shared, what changes to the thread package must be made in order to share it. (The solution you adopt for shared variables is likely to be equally applicable to shared static variables of the application.)

    Part D: How would you change the thread package to make it work in this environment. For this part, focus on thread_relinquish(), the functions it calls, and the data structures they manipulate, in order to find where new spin-locks must be installed and where the lock and unlock operations on these should be put. (If you can give the correct short answer to this, I trust that you would be able to finish the project).

    Part E: In the original thread package, there was no need for idle threads. There is a need for idle threads in this new package! How many need to be launched and what code should they run?