180 likes | 347 Views
CSE451 – Section 5. Winter 2k7 Kurtis Heimerl (kheimerl@) Aaron Kimball (ak@). Project 2, part 4 - web server. web/sioux.c – singlethreaded web server Read in command line args, run the web server loop web/sioux_run.c – the webserver loop Open a socket to listen for connections ( listen )
E N D
CSE451 – Section 5 Winter 2k7 Kurtis Heimerl (kheimerl@) Aaron Kimball (ak@)
Project 2, part 4 - web server • web/sioux.c – singlethreaded web server • Read in command line args, run the web server loop • web/sioux_run.c – the webserver loop • Open a socket to listen for connections (listen) • Wait for a connection (accept) • Handle it • Parse the HTTP request • Find and read the requested file (www root is ./docs) • Send the file back • Close the connection • web/web_queue.c – an empty file for your use
A peek at the code… • In web/sioux.c is main: In web/sioux_run.c: int main(int argc, char **argv) { int port; const char *host; const char *docroot; sthread_init(); /* Get the configuration information */ host = web_gethostname(); port = web_getport(); docroot = web_getdocroot(); /* Tell the user where to look for server */ web_printurl(host, port); /* Handle requests forever */ web_runloop(host, port, docroot); return 0; } void web_runloop(const char *host, int port, const char *docroot) { int listen_socket, next_conn; listen_socket = web_setup_socket(port); while ((next_conn = web_next_connection(listen_socket)) >= 0) { web_handle_connection(next_conn, docroot); } close(listen_socket); }
What you need to do • Make the web server multithreaded • Create a thread pool • A bunch of threads waiting for work • Number of threads = command-line arg • Wait for a connection • Find an available thread to handle connection • Current request waits if all threads busy • Once a thread grabs onto connection, it uses the same processing code as before.
What to change? void web_runloop(const char *host, int port, const char *docroot) { int listen_socket, next_conn; listen_socket = web_setup_socket(port); //create a queue of waiting connections //create a bunch of threads to handle connections while ((next_conn = web_next_connection(listen_socket)) >= 0) { //add connection to queue //wake-up a thread to handle connection //yield to awoken thread } …. } • You’ll need a queue (web_queue.c) • What about critical sections? • What shared/global data structures are there? • How do I protect them? • Cond-vars are good ways to “wake-up” a thread…hint hint
Hints • Each connection is identified by a socket returned by accept • Which is just an int • Simple management of connections among threads • Threads should sleep while waiting for a new connection • Condition variables are perfect for this • Don’t forget to protect any global variables • Use part 2 mutexes, CVs • Develop + test with pthreads initially • Mostly modify sioux_run.c and/or your own files • Stick to the sthread.h interface!
Part 5 - Preemption • Requires a relatively small amount of code, but tough to get 100% right • What you have to do: • Add code that will run every time a timer interrupt is generated • Add synchronization to your part 1 and part 2 implementations so that everything works with preemptive thread scheduling • What we give you: • Timer interrupts • Primitives to turn interrupts on and off • Synch primitives atomic_test_and_set, atomic_clear • WARNING: The code that we have provided to support preemption works correctly only on the x86 architecture! Do not attempt this portion of the assignment on a non-x86 architecture!
What we give you: /* start preemption - func will be called every period microseconds */ void sthread_preemption_init(sthread_ctx_start_func_t func, int period); /* Turns inturrupts ON and off * Returns the last state of the inturrupts * LOW = inturrupts ON * HIGH = inturrupts OFF */ int splx(int splval); /* * atomic_test_and_set - using the native compare and exchange on the * Intel x86. * * Example usage: * * lock_t lock; * while(atomic_test_and_set(&lock)) { } // spin * _critical section_ * atomic_clear(&lock); */ int atomic_test_and_set(lock_t *l); void atomic_clear(lock_t *l); • sthread_preempt.h (implemented in .c):
What to do? • Add a call to sthread_preemption_init as the last line in your sthread_user_init() function. • init specifies a function that is called on each timer interrupt (done for you!) • This func should cause thread scheduler to switch to a different thread • Hard part: add synchronization to thread management routines • Where are the critical sections from part 1 and 2?
Preemption + Critical Sections • Safest way: disable interrupts before critical sections • Example: • Where is the critical section? Why? threadsafe soln NON-threadsafe soln sthread_t sthread_user_next() { sthread_t next; int old = splx(HIGH); next = sthread_dequeue(ready_q); splx(old); if (next == NULL) exit(0); return next; } /*returns the next thread on the ready queue*/ sthread_t sthread_user_next() { sthread_t next; next = sthread_dequeue(ready_q); if (next == NULL) exit(0); return next; }
Part 6 – Report • Design discussion & functionality • Make it short • Results • Run a few experiments with the new webserver • Use given web benchmark: /cse451/projects/webclient • Present results in a graphical easy-to-understand form. • Explain • Are the results what you expected? • Try to justify any discrepancies you see • Answer a few of our questions
Real-time scheduling • Tasks usually accompany deadlines • You can’t naively hop from task to task • What happens when you violate deadline? • Get penalty • Real-time system • Hard real-time system • Once you miss the deadline, system fails • Soft real-time system • The quality of your task degrades • However, soft/hard boundaries can be changed by requirement
Real-time tasks • Periodic task • Must be completed within periodic deadline • Regular task • Aperiodic task • Must be completed within a specific deadline • Example real-time task & deadline • Hard – periodic • Giving insulin to glycosuria patient • Hard – aperiodic • Course project, breaking your car before collision • Soft – periodic • Decoding multi-media stream (MPEG) • Soft – aperiodic • Course project: if you don’t care about your grade
Real-time scheduling • Earliest Deadline First • Greedy approach • What you do to survive throughout quarter • Guarantees to schedule up to 100% CPU utilization • Theoretically • Preemptive vs. non-preemptive EDF • Rate monotonic • Static priorities • shorter period/deadline gets higher priority • Deadline is exactly the same as period • No resource sharing between other processes • Guarantees to schedule up to n(2^(1/2)-1) utilization • N = number of processes • U is about 82% when n=2. About 69% when n=inf. • Used in real-time operating systems
Scheduling • Assume following tasks • P1: takes 1 unit time. Period is 10 • P2: takes 4 unit time. Period is 9 • P3: takes 3 unit time. Period is 13 • Utilization • 1/10 + 4/9 + 3/13 = 0.7753 • Can EDF schedule them? • Yes • Can rate monotonic schedule them? • The limit for 3 processes = 0.779763 • Yes
Starvation • Pathfinder @ 1997 • Mission on Mars • VxWorks: realtime OS supports preemptive priority thread scheduling • Information bus • data path between components • Synchronized by using mutex • Priority • Bus Management > COMMunication > Meteorological Data Gathering • BM task: Use information bus. Run frequently • COMM task: Long running time • MDG: Run not very often. Use information bus • Result • System reset • Data loss • Why? How can we solve this?
Deadlock • What is it? • Why does it happen? • What are the strategies to resolve it?
Deadlock prevention • Linux kernel documentation contains a lot of rules about locking • find . –name “*[lL]ock*” • grep deadlock * • Why? Because there are 5000 locks in 2003 • Lots of them specifying explicit rules about acquiring locks The rules are: 1. To scan the vmlist (look but don't touch) you must hold themmap_sem with read bias, i.e. down_read(&mm->mmap_sem) 2. To modify the vmlist you need to hold the mmap_sem with read&write bias, i.e. down_write(&mm->mmap_sem) *AND* you need to take the page_table_lock. 3. The swapper takes _just_ the page_table_lock, this is done because the mmap_sem can be an extremely long lived lockand the swapper just cannot sleep on that. 4. The exception to this rule is expand_stack, which justtakes the read lock and the page_table_lock, this is okbecause it doesn't really modify fields anybody relies on. 5. You must be able to guarantee that while holding page_table_lockor page_table_lock of mm A, you will not try to get either lockfor mm B. -- From vm/locking 1. The symbolic link name, if any (/var/lock/LCK..modem) 2. The "tty" name (/var/lock/LCK..ttyS2) 3. The alternate device name (/var/lock/LCK..cua2) -- From devices.txt • Let’s have a look at file system