CS31 Weekly Lab: Week 12 and 13

pthreads, cpuinfo, top, debugging pthreads programs

Create a week12 subdirectory in your weeklylab subdirectory and copy over some files:

    cd cs31/weeklylab
    pwd
    mkdir week12
    ls
    cd week12
    pwd
    cp ~newhall/public/cs31/week12/* .
    ls
    Makefile  deadlock.c  hello.c  synch.c
Then type make to build the executable files.

example pthread program with a race condition
Let's look at the hello.c program together. It show an example of a simple pthreads program that:
  1. spawns some worker threads by calling pthread_create
  2. passes parameter values (thread logical identifier values) to each thread's main function via its void *args parameter.
  3. an example of how the thread main loop function can get is argument value(s) from it parameter
  4. calls to pthread_join to wait for all spawned threads to exit.
Let's try running it a few times with different numbers of threads.

This is also an example of a program with a race condition. Let's try to fix it using some pthread synchronization primitives.

example pthread synchronization primitives
The file synch.c contains some examples using pthreads mutex and barrier synchronization. It also shows an example of defining a struct type that can be used to pass several values to a threads main function via its single void *args parameter.

CPU information on machines

top (and htop) and threads
top and htop are Unix utilities that list information about processes and threads and how they are using resources like memory and CPU. If you run top with no command line options, then it displays per-process statistics. If you run top with -H, top will display statistics for individual threads (if you run the synch program for a large number of threads, you can see them show up in top):
top -H

Let's try out the example of configuring top on this page: using top and htop to change what top displays. Then we can try running a multi-threaded process and see what top shows us.

Let's run synch with a bunch of threads, and then top -H in another window to see what we can see.

debugging pthreads programs
Debugging threaded programs can be tricky because there are multiple streams of execution. In general, try to debug with as few threads as possible, and if you use printfs, print out a thread id and call fflush after. You can also put printf's in conditional statements to only have one of the threads print out information (or only some of the threads, or only some of the information, ...). For example, if each thread is passed a logical thread id value on start-up, and stores its value in a local variable named my_tid, then you could have logical thread 1 be the debug output printing thread to do something like:
if(my_tid == 1) {
   printf("Tid:%d: value of count is now %d my i is %d\n", my_tid,count,i); 
   fflush(stdout);
}

gdb and pthreads

We are not going to look at this together in lab, but if you want to try using gdb to debug your pthread code, here is some general information about it and an example you can try out: Debugging pthreads programs with gdb. It contains an example run of debugging the racecond program you copied over with this week's in-class code.

More detailed information about gdb and pthreads can be found here: gdb and pthreads