When programming with pthreads, you pass the thread a function to run when you create it. When this function is done, is the thread cleaned up automatically? Is it necessary to put pthread_join() in the calling function somewhere? Is pthread_join only useful when you want to wait for a thread to finish?

You should always kill the threads as the finish up the work. So you need to join the thread in order to stop it. Threads can provide significant overhead if left to run wild so make sure you clean up all threads in your exit handler.