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:
- spawns some worker threads by calling pthread_create
- passes parameter values (thread logical identifier values) to each
thread's main function via its void *args parameter.
- an example of how the thread main loop function can get is argument
value(s) from it parameter
- 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