6.824 Lecture 3: Threads Pthread interface standard interface, not unlike the one described in the paper, but programming language independent. we use it in the labs Interface threads create join mutex lock unlock (must typically be performed by the thread that did the acquire) condition variables wait signal wakes up one thread is it the right one? only use it if there is only one thread waiting broadcast wakes up all threads waiting put waiting condition in a loop around wait if only one should proceed e.g., if multiple clients are waiting on a lock from the lock server other stuff which we don't use. Paper does a nice job how to teaching to program with threads, in particular for programmers who write multithreaded servers---that is you. Worth to reread the paper as you get more experience. How to use the interface. Let's start from the RPC code; send a packet chan.cc note the testing code for reordering, duplication, etc. tcpchan created on the fly uses fifo to coordinate between thread invoking rpc and thread sending the packet on a TCP channel why a separate thread for sending? fifo.h construction initializes mutex and condition variable what does the mutex m protect? what is the purpose of the condication variable c? why does the cond_wait call include m as an argument? why the while loop around the cond_wait call? Invariants one way to think about lock is that they protect an invariant. when the lock is not held, some invariant is true when the lock is acquire, the invariant is true when the lock is released, the invariant be better true again invariant for deq()? is the variant invalid in the deq/enq? Recursive/reentrant locks generally bad idea, because it doesn't obey the invariant view. better have a deadlock and/or fix code. Deadlock enumerate locks, acquire them in fix order will show in yfs when using the lock server Locking granularity one lock for the whole RPC library one lock for all instances of fifo? danger of many locks---deadlock and races Breaking of abstractions let say you want to terminate a thread that is waiting in the fifo what are your options? pthread_cancel -> cleanup handlers every n sec test a die flag fifo needs to know that threads may send signals or want to die. when locks are involved, the caller often must be aware of the internals move item from one queue to another, without showing intermediate state Could we make the YFS code cleaner; closer to the examples in C# in the paper? Yes, scoped locks. int main(int ac, char **av) { scoped_pthread_lock _spl(&mu); // I acquired mu.. if (foo > 0) return foo--; // _spl.~scoped_pthread_lock releases mu return foo++; // _spl.~scoped_pthread_lock releases mu } Interactions betweens threads and RPC can one hold locks across an RPC call? should one? can one make an RPC in a handler? what is the risk of this kind of a code in a handler? for (iterator i = beginlist(); !eol(); i++) { unlock(&l) call(client[i], ...) lock(&l) }