280 likes | 386 Views
CSE451 Section 3: Winter 2k7. Welcome to the world of concurrency! Kurtis Heimerl(kheimerl@cs) Aaron Kimball (ak@cs). Threads & synchronization. A rite of passage All undergrad OS courses do The most fun part Will feel like being a GURU The craziest part
E N D
CSE451 Section 3:Winter 2k7 Welcome to the world of concurrency! Kurtis Heimerl(kheimerl@cs) Aaron Kimball (ak@cs)
Threads & synchronization • A rite of passage • All undergrad OS courses do • The most fun part • Will feel like being a GURU • The craziest part • Will be sick of synchronization • Start early & read thoroughly • Grab a big picture first! • Discuss your design with • Fellow students • TAs
User-level threads: to do • First submission(Feb 2nd 10:00am) • user-level thread manager • common synchronization primitives • simple synchronization problem • Second submission(Feb 14 10:00am) • Preemption • Multithreaded web server to test your thread package • Analyze your design and report test results
Dependency Part 1: Thread manager Part 2: Synchronization primitives Part 4: Preemption Part 3: Synchronization problem Part 6: Report Part 5: Multithreaded web server pthread compatible You can work concurrently!
Simplethreads code structure test/*.c Web server (web/sioux.c) Other apps include/sthread.h You write this lib/sthread_user.c lib/sthread_user.h lib/sthread_queue.h lib/sthread_ctx.h lib/sthread_preempt.h lib/sthread_queue.c lib/sthread_ctx.c lib/sthread_preempt.c lib/sthread_switch.S sthread_switch_i386.h sthread_switch_powerpc.h From Section 3 – Winter 2006
Sthread: thread interface • void sthread_init(void) • Initialize thread system(or manager) • sthread_t sthread_create(sthread_start_func_t start_routine,void *arg,int joinable) • Spawn a new thread • The new thread runs start_routine with given arg • void sthread_exit(void *ret) • Exit caller thread with ret as exit value • ret is actually return value of start_routine • void sthread_yield(void) • Yield execution of caller thread • void *sthread_join(sthread_t t) • Join thread t which is created as joinable • Return value is the return value of start_routine of t • Refer sthread.h
Synchronization • Problem: Controlling access from threads to limited resources. • Solutions?
Synchronization • Problem: Controlling access from threads to limited resources. • Solutions? • Disable Interrupts (hardware) • Atomic Instructions (hardware) • Semaphores (OS) • Condition Variables (OS) • Monitors (PL) • We will be implementing the OS level primitives with the support of the hardware level primitives.
Disabling/Enabling Interrupts Thread A: disable_interrupts() critical_section() enable_interrupts() Thread B: disable_interrupts() critical_section() enable_interrupts() • Prevents context-switches during execution of CS • Sometimes necessary • E.g. to prevent further interrupts during interrupt handling • Problems?
Hardware support • Atomic instructions: • Test and set • Swap • Compare-exchange (x86) • Load-linked store conditional (MIPS, Alpha, PowerPC) • Use these to implement higher-level primitives • E.g. test-and-set on x86 (given to you for part 5) is written using compare-exchange. • compare_exchange(lock_t *x,int y,int z): if(*x == y) *x = z; return y;else return *x; • test_and_set(lock_t *l) { return compare_exchange(l,0,1); }
Sthread: mutex interface • sthread_mutex_t sthread_mutex_init() • Create a new-unlocked mutex • void sthread_mutex_free(sthread_mutex_t lock) • Release resources held by given mutex • void sthread_mutex_lock(sthread_mutex_t lock) • Returned thread is guaranteed to acquire lock • void sthread_mutex_unlock(sthread_mutex_t lock) • Release lock • Refer sthread.h
Sthread: condition variable • sthread_cond_t sthread_cond_init() • Create a new condition variable • void sthread_cond_free(sthread_cond_t cond) • Release resources held by given condition variable • void sthread_cond_signal(sthread_cond_t cond) • Wake-up one waiting thread if there is any • void sthread_cond_broadcast(sthread_cond_t cond) • Wake-up all waiting threads • void sthread_cond_wait(sthread_cond_t cond, sthread_mutex_t lock) • Wait for given condition variable • Returning thread is guaranteed to hold the lock • Refer sthread.h
Sample multithreaded program int main(int argc, char **argv) { int i; sthread_init(); if (sthread_create(thread_start, (void*)i) == NULL) { printf("sthread_create failed\n"); exit(1); } sthread_yield(); //yield main thread to our new thread printf("back in main\n"); return 0; } void *thread_start(void *arg) { printf("In thread_start, arg = %d\n", (int)arg); return 0; } • Output? (assume no preemption)
Managing contexts (given) • Thread context = thread stack + stack pointer • sthread_new_ctx(func_to_run) • Gives a new thread context that can be switched to • sthread_free_ctx(some_old_ctx) • Deletes the supplied context • sthread_switch(oldctx, newctx) • Puts current context into oldctx • Takes newctx and makes it current
From Section 3 – Winter 2006 How sthread_switch works Thread 1 TCB … SP Thread 2 TCB … SP Xsthread_switch: pusha movl %esp,(%eax) movl %edx,%esp popa ret Thread 2 registers CPU ESP Thread 1 running Thread 2 ready Thread 1 regs Want to switch to thread 2…
From Section 3 – Winter 2006 Push old context Thread 1 TCB … SP Thread 2 TCB … SP Xsthread_switch: pusha movl %esp,(%eax) movl %edx,%esp popa ret Thread 1 registers Thread 2 registers CPU ESP Thread 1 running Thread 2 ready Thread 1 regs
From Section 3 – Winter 2006 Save old stack pointer Thread 1 TCB … SP Thread 2 TCB … SP Xsthread_switch: pusha movl %esp,(%eax) movl %edx,%esp popa ret Thread 1 registers Thread 2 registers CPU ESP Thread 1 running Thread 2 ready Thread 1 regs
From Section 3 – Winter 2006 Change stack pointers Thread 1 TCB … SP Thread 2 TCB … SP Xsthread_switch: pusha movl %esp,(%eax) movl %edx,%esp popa ret Thread 1 registers Thread 2 registers CPU ESP Thread 1 ready Thread 2 running Thread 1 regs
From Section 3 – Winter 2006 Pop off new context Thread 1 TCB … SP Thread 2 TCB … SP Xsthread_switch: pusha movl %esp,(%eax) movl %edx,%esp popa ret Thread 1 registers CPU ESP Thread 1 ready Thread 2 running Thread 2 regs
From Section 3 – Winter 2006 Done; return Thread 1 TCB … SP Thread 2 TCB … SP Xsthread_switch: pusha movl %esp,(%eax) movl %edx,%esp popa ret Thread 1 registers • What got switched? • SP • PC (how?) • Other registers CPU ESP Thread 1 ready Thread 2 running Thread 2 regs
From Section 3 – Winter 2006 Adjusting the PC Thread 1 TCB … SP Thread 2 TCB … SP • ret pops off the new return address! Thread 1 registers ra=0x400 ra=0x800 CPU ESP Thread 1 (stopped): switch(t1,t2); 0x400: printf(“test 1”); Thread 2 running: switch(t2,...); 0x800: printf(“test 2”); PC
Join! Exciting new construct! • Wait until another thread terminates and get its return value • Convenient way to synchronize threads • Assumption • A joinable thread is guaranteed to be joined by another thread (not threads!) • Join can be called only one time at any time in the life-cycle of a joinable thread • Behavior of multiple calls of join on a single joinable thread is undefined
Think about • How do you start a new thread? • How do you pass an argument to the start function? • How do you deal the main(or initial) thread? • When & how do you reclaim resources of a terminated thread? • Where does sthread_switch() return? • Who should call sthread_switch() and when? • What should be in struct _sthread(TCB)? • How do you identify current thread? • How do you block a thread? • What should be in struct _sthread_mutex? • What should be in struct _sthread_cond?
Hints • Read project descriptions & given codes • There are many hints already • pthread manual pages may be helpful • Design first • Answer questions in previous slides • Write your algorithms and verify them • Program • Don’t forget to comment your code! • Test, test, test, … • Write your own test programs • Pick the right tree • This project is not a lot of code. If you’re writing a lot of code, you’re probably confused. • Keep in mind, we might have different definitions of “a lot of code” • This is an easy project to do, but a really f’n hard project to do right.
CVS • Make your project concurrent just like your programs • Refer any CSE303 course material • http://www.cs.washington.edu/education/courses/cse303/05au/syllabus/11-14-files/ • http://www.cs.washington.edu/education/courses/cse303/06wi/lec19.pdf
Scenario • Your team has two members • dumb • dumber • UNIX group of your team is cse451x • dumber is going to maintain the repository • The name of repository is cse451x
Import source code • Copy simplethreads-1.30.tar.gz • Type following % tar zxf simplethreads-1.30.tar.gz % cd simplethreads-1.30 % cvs –d $USER@attu:/projects/.instr/CurrentQtr/cse451/cse451x import –m “initial skeleton code” simplethreads SIMPLETHREADS SIMPLETHREADS_1_30 % cd .. % rm –rf simplethreads-1.30 • Now you can check out using simplethreads as a module name
Set CVSROOT & CVS_RSH • You want to access the repository remotely! • Bash • export CVS_RSH=ssh • export CVSROOT=$USER@attu:/projects/.instr/CurrentQtr/cse451/cse451x • Csh/tcsh • setenv CVS_RSH ssh • setenv CVSROOT $USER@attu:/projects/.instr/CurrentQtr/cse451/cse451x • To check your shell, % echo $SHELL