Download presentation
Presentation is loading. Please wait.
Published byNoel Skinner Modified over 8 years ago
1
Web Server Architecture Client Main Thread for(j=0;j<nthread; pthread_create() while(1) newsock = accept() enQ(newsock) Connect() Thread Pool while(1) sock = deQ() recv() process send() close(sock) while(1) sock = deQ() recv() process send() close(sock) while(1) sock = deQ() recv() process send() close(sock) while(1) sock = deQ() recv() process send() close(sock) while(1) sock = deQ() recv() process send() close(sock) while(1) sock = deQ() recv() process send() close(sock) while(1) sock = deQ() read() process write() close(sock) Connection Queue
2
Cooperating Processes Operating systems allow for the creation and concurrent execution of multiple processes & threads eases program complexity increases efficiency Can they work together? How? Messages? What about shared memory? Operating systems allow for the creation and concurrent execution of multiple processes & threads eases program complexity increases efficiency Can they work together? How? Messages? What about shared memory?
3
Problems with concurrent execution Concurrent processes (or threads) often need to share data (maintained either in shared memory or files) and resources If there is no controlled access to shared data, some processes will obtain an inconsistent view of this data The action performed by concurrent processes will then depend on the order in which their execution is interleaved Consider two threads one doing x++ and the other doing x--. How many different values for x? Concurrent processes (or threads) often need to share data (maintained either in shared memory or files) and resources If there is no controlled access to shared data, some processes will obtain an inconsistent view of this data The action performed by concurrent processes will then depend on the order in which their execution is interleaved Consider two threads one doing x++ and the other doing x--. How many different values for x?
4
The Critical-Section Problem Consider a system: n processes {P 0, P 1, …, P n-1 } Each process has a critical section changing common values updating tables etc. Access to those variables must be safe mutually exclusive Consider a system: n processes {P 0, P 1, …, P n-1 } Each process has a critical section changing common values updating tables etc. Access to those variables must be safe mutually exclusive
5
The Critical-Section Problem A solution must satisfy 3 conditions: Mutual exclusion Progress Bounded waiting No assumptions can be made about speed Solutions execute some entry code and some exit code surrounding critical section. A solution must satisfy 3 conditions: Mutual exclusion Progress Bounded waiting No assumptions can be made about speed Solutions execute some entry code and some exit code surrounding critical section.
6
Critical Section Properties Mutual Exclusion At any time, at most one process can be in its critical section (CS) Progress Only processes that are not executing in their CS can participate in the decision of who will enter next in the CS. This selection cannot be postponed indefinitely Mutual Exclusion At any time, at most one process can be in its critical section (CS) Progress Only processes that are not executing in their CS can participate in the decision of who will enter next in the CS. This selection cannot be postponed indefinitely
7
Critical Section Properties Bounded Waiting After a process has made a request to enter it’s CS, there is a bound on the number of times that the other processes are allowed to enter their CS otherwise the process will suffer from starvation Of course there must also be no deadlock Bounded Waiting After a process has made a request to enter it’s CS, there is a bound on the number of times that the other processes are allowed to enter their CS otherwise the process will suffer from starvation Of course there must also be no deadlock
8
The Producer-Consumer Problem repeat … produce an item in nextp … while counter == n sleep() buffer[in] = nextp in = (in + 1) mod n counter = counter + 1 if(counter == 1) wakeup(consumer) repeat … while counter == 0 sleep() nextc = buffer[out] out = (out + 1) mod n counter = counter -1 if(counter == n) wakeup(producer) … consume the item in nextc … Are these correct? Always?
9
The Producer-Consumer Problem repeat … produce an item in nextp … while counter == n sleep() buffer[in] = nextp in = (in + 1) mod n counter = counter + 1 if(counter == 1) wakeup(consumer) repeat … while counter == 0 sleep() nextc = buffer[out] out = (out + 1) mod n counter = counter -1 if(counter == n) wakeup(producer) … consume the item in nextc … Are these correct? Always? Assume n=2, in=0, out=0, counter=0 Count er InOutProducerconsumerAction 000AwakeSleepInsert 110Awake Insert 200SleepAwake 101 Remove 000Awake Remove
10
The Producer-Consumer Problem repeat … produce an item in nextp … while counter == n sleep() buffer[in] = nextp in = (in + 1) mod n counter = counter + 1 if(counter == 1) wakeup(consumer) repeat … while counter == 0 sleep() nextc = buffer[out] out = (out + 1) mod n counter = counter -1 if(counter == n) wakeup(producer) … consume the item in nextc … Assume n=2, in=0, out=0, counter=0 Count er InOutProducerconsumerAction 000AwakeSleepInsert 110Awake Insert 200SleepAwake 101 Remove 000Awake Remove What if producer enters while, then consumer does wakeup before producer goes to sleep? Producer will never wake up and consumer will eventually empty queue and go to sleep - deadlock
11
The Producer-Consumer Problem repeat … produce an item in nextp … wait(full_sem) buffer[in] = nextp in = (in + 1) mod n counter = counter + 1 signal(empty) repeat … wait(empty_sem) nextc = buffer[out] out = (out + 1) mod n counter = counter -1 signal(full_sem) … consume the item in nextc …
12
What about multiple consumers? repeat … produce an item in nextp … wait(full_sem) buffer[in] = nextp in = (in + 1) mod n counter = counter + 1 signal(empty) repeat … wait(empty_sem) nextc = buffer[out] out = (out + 1) mod n counter = counter -1 signal(full_sem) … consume the item in nextc … CounterInOutProducerconsumerAction 000AwakeSleepInsert 110Awake Insert 200SleepAwake 101 Remove 000Awake Remove What about when consumer 1 wakes up, reads out=0, increments it to 1, but before it is written out, we context switch Consumer 2 wakes up, reads out=0, increments it to 1, writes 1 to out and consumes slot 0 before context switch. Consumer 1 is context switched in, writes 1 to out and consumes slot 0 again.
13
The Producer-Consumer Problem repeat … produce an item in nextp … wait(full_sem) wait(mutex) buffer[in] = nextp in = (in + 1) mod n counter = counter + 1 signal(mutex) signal(empty) repeat … wait(empty_sem) nextc = buffer[out] wait(mutex) out = (out + 1) mod n counter = counter -1 signal(mutex) signal(full_sem) … consume the item in nextc …
14
Semaphore Implementation How do we wait? spin? sleep? – How long? How do we wake up? Solution: Let process block itself by placing in waiting queue wait call places the process on the queue When a process is blocked, it must be woken up signal process must wake up next process on queue Semaphore struct semaphore { int value; Queueprocesses; }; How do we wait? spin? sleep? – How long? How do we wake up? Solution: Let process block itself by placing in waiting queue wait call places the process on the queue When a process is blocked, it must be woken up signal process must wake up next process on queue Semaphore struct semaphore { int value; Queueprocesses; };
15
Wait wait(Semaphore s) { s.value = s.value - 1; if (s.value < 0) { add this process to s.L block; } wait(Semaphore s) { s.value = s.value - 1; if (s.value < 0) { add this process to s.L block; }
16
signal(Semaphore s) { s.value = s.value + 1; if (s.value <= 0) { remove a process P from s.L wakeup(P); } signal(Semaphore s) { s.value = s.value + 1; if (s.value <= 0) { remove a process P from s.L wakeup(P); } Signal (or post)
17
Details Critical Semaphore operations must be atomic Uniprocessor simply inhibit interrupts (normal user can’t) Use TestAndSet instruction Multiprocessor hardware must provide special support or use software solutions Critical Semaphore operations must be atomic Uniprocessor simply inhibit interrupts (normal user can’t) Use TestAndSet instruction Multiprocessor hardware must provide special support or use software solutions
18
Bounded Buffer Solution without counter repeat produce an item in nextp wait(empty); wait(mutex); add nextp to the buffer signal(mutex); signal(full); until false repeat produce an item in nextp wait(empty); wait(mutex); add nextp to the buffer signal(mutex); signal(full); until false repeat wait(full); wait(mutex); remove an item from buffer place it in nextc signal(mutex); signal(empty); consume the item in nextc until false repeat wait(full); wait(mutex); remove an item from buffer place it in nextc signal(mutex); signal(empty); consume the item in nextc until false Shared semaphore: empty = n, full = 0, mutex = 1;
19
Posix Semaphores Counting semaphores sem_init - creates a unnamed semaphore and initializes it int sem_init(sem_t *sem, int pshared, unsigned int value); sem_open - creates a named semaphore and initializes it sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); sem_wait - performs a wait operation int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); sem_post - performs a signal operation int sem_post(sem_t *sem); Counting semaphores sem_init - creates a unnamed semaphore and initializes it int sem_init(sem_t *sem, int pshared, unsigned int value); sem_open - creates a named semaphore and initializes it sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value); sem_wait - performs a wait operation int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); sem_post - performs a signal operation int sem_post(sem_t *sem);
20
#include void *functionC(void *ptr); int counter = 0; sem_t sem; main() { int rc1, rc2; pthread_t thread1, thread2; sem_init(&sem, PTHREAD_PROCESS_PRIVATE, 1); // Now it is set to one, one person will be able to access at a time printf("Got semaphore %d\n",sem); /* Create independent threads each of which will execute functionC */ if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) ) { printf("Thread creation failed: %d\n", rc1); } if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) ) { printf("Thread creation failed: %d\n", rc2); } /* Wait till threads are complete before main continues. Unless we */ /* wait we run the risk of executing an exit which will terminate */ /* the process and all threads before the threads have completed. */ pthread_join( thread1, NULL); pthread_join( thread2, NULL); sem_close(&sem); exit(0); } void *functionC(void *ptr) { int tmp; sem_wait(&sem); tmp = counter; sleep(1); tmp++; counter = tmp; printf("Counter value: %d\n",counter); sem_post(&sem); } ~ This works for Linux
21
Bounded Buffer Solution repeat produce an item in nextp wait(empty); wait(producer_mutex); add nextp to the buffer only modify in signal(producer_mutex); signal(full); until false repeat wait(full); wait(consumer_mutex); remove an item from buffer place it in nextc only modify out signal(consumer_mutex); signal(empty); consume the item in nextc until false Shared semaphore: empty = n, full = 0, producer_mutex = 1, consumer_mutex = 1;
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.