150 likes | 159 Views
This project involves modifying a single-threaded web server to make it multithreaded using a thread pool and implementing preemption for thread scheduling. It includes handling connections, utilizing a queue, protecting global variables, and using condition variables for thread synchronization.
E N D
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? • 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 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 } …. }
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 Mac or other non-x86 architecture!
What we give you: • sthread_preempt.h (implemented in .c): /* 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);
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? NON-threadsafe soln threadsafe soln /*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; } 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; }
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 • Theoratically • 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