Auburn University http://www.eng.auburn.edu/~xqin COMP 3500 Introduction to Operating Systems Project 3 – Synchronization Cats and Mice: Implementation.

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

Operating Systems: Monitors 1 Monitors (C.A.R. Hoare) higher level construct than semaphores a package of grouped procedures, variables and data i.e. object.
Ch 7 B.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
CSCC69: Operating Systems
Chapter 6: Process Synchronization
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
1 Semaphores and Monitors CIS450 Winter 2003 Professor Jinhua Guo.
1 CS318 Project #3 Preemptive Kernel. 2 Continuing from Project 2 Project 2 involved: Context Switch Stack Manipulation Saving State Moving between threads,
CS470 Lab 4 TA Notes. Objective Simulate the activities of a producer and consumer – Page 326 Use thread synchronization to solve the producer-consumer.
Semaphores, mutexes and condition variables. semaphores Two types – Binary – 0 or 1 – Counting 0 to n Wait – decrements > 0 forces a wait Post or signal.
Semaphores CSCI 444/544 Operating Systems Fall 2008.
Jonathan Walpole Computer Science Portland State University
Jonathan Walpole Computer Science Portland State University
More Synchronisation Last time: bounded buffer, readers-writers, dining philosophers Today: sleeping barber, monitors.
CS510 Concurrent Systems Introduction to Concurrency.
Midterm 1 – Wednesday, June 4  Chapters 1-3: understand material as it relates to concepts covered  Chapter 4 - Processes: 4.1 Process Concept 4.2 Process.
4061 Session 21 (4/3). Today Thread Synchronization –Condition Variables –Monitors –Read-Write Locks.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
Silberschatz, Galvin and Gagne  Operating System Concepts Chapter 7: Process Synchronization Background The Critical-Section Problem Synchronization.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Synchronization.
1 CMSC421: Principles of Operating Systems Nilanjan Banerjee Principles of Operating Systems Acknowledgments: Some of the slides are adapted from Prof.
Lab assignment 1: Synchronization
1 Condition Variables CS 241 Prof. Brighten Godfrey March 16, 2012 University of Illinois.
13/03/07Week 21 CENG334 Introduction to Operating Systems Erol Sahin Dept of Computer Eng. Middle East Technical University Ankara, TURKEY URL:
Threads and Singleton. Threads  The JVM allows multiple “threads of execution”  Essentially separate programs running concurrently in one memory space.
CS252: Systems Programming Ninghui Li Based on Slides by Prof. Gustavo Rodriguez-Rivera Topic 13: Condition Variable, Read/Write Lock, and Deadlock.
IT 344: Operating Systems Winter 2008 Module 7 Semaphores and Monitors
1 Previous Lecture Overview  semaphores provide the first high-level synchronization abstraction that is possible to implement efficiently in OS. This.
CSC 360 Instructor: Kui Wu More on Process Synchronization Semaphore, Monitor, Condition Variables.
CS510 Concurrent Systems Jonathan Walpole. Introduction to Concurrency.
Mutual Exclusion -- Addendum. Mutual Exclusion in Critical Sections.
1 COMP 3500 Introduction to Operating Systems Project 3 – Synchronization Overview Dr. Xiao Qin Auburn University
Chapter 6 Synchronization Dr. Yingwu Zhu. The Problem with Concurrent Execution Concurrent processes (& threads) often access shared data and resources.
Operating Systems NWEN 301 Lecture 6 More Concurrency.
Case Study: Pthread Synchronization Dr. Yingwu Zhu.
Deadlock and Starvation
Auburn University COMP 3500 Introduction to Operating Systems Project 3 – Synchronization Cats and Mice Dr. Xiao Qin.
CS703 – Advanced Operating Systems
Chapter 5: Process Synchronization – Part 3
Auburn University COMP 3500 Introduction to Operating Systems Synchronization: Part 4 Classical Synchronization Problems.
Background on the need for Synchronization
Chapter 5: Process Synchronization – Part II
Deadlock and Starvation
The Singleton Pattern SE-2811 Dr. Mark L. Hornick.
January 29, 2004 Adrienne Noble
Auburn University COMP 3500 Introduction to Operating Systems Project 3 – Synchronization Condition Variables Dr. Xiao.
CS533 Concepts of Operating Systems Class 3
Semaphores and Condition Variables
Monitors, Condition Variables, and Readers-Writers
CS510 Operating System Foundations
Dr. Xiao Qin Auburn University
Jonathan Walpole Computer Science Portland State University
Condition Variables and Producer/Consumer
Condition Variables and Producer/Consumer
Semaphore Originally called P() and V() wait (S) { while S <= 0
Too Much Milk With Locks
Too Much Milk With Locks
Synchronization Hank Levy 1.
UNIVERSITY of WISCONSIN-MADISON Computer Sciences Department
Chapter 30 Condition Variables
CS533 Concepts of Operating Systems Class 3
Monitor Giving credit where it is due:
CSE 451: Operating Systems Autumn Lecture 7 Semaphores and Monitors
Synchronization Hank Levy 1.
CSE 153 Design of Operating Systems Winter 19
CS333 Intro to Operating Systems
CSE 451 Section 1/27/2000.
EECE.4810/EECE.5730 Operating Systems
Don Porter Portions courtesy Emmett Witchel
Presentation transcript:

Auburn University http://www.eng.auburn.edu/~xqin COMP 3500 Introduction to Operating Systems Project 3 – Synchronization Cats and Mice: Implementation Dr. Xiao Qin Auburn University http://www.eng.auburn.edu/~xqin xqin@auburn.edu

Review: Semaphores and Variables volatile bool all_dishes_available = true; semaphore done = 0; semaphore mutex = 1; semaphore dish_mutex = 1; semaphore cats_queue = 0; volatile int cats_wait_count = 0; volatile bool no_cat_eat = true; /*first cat*/ semaphore mice_queue = 0; volatile int mice_wait_count = 0; volatile bool no_mouse_eat = true; The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

First Cat and No Mouse wait(mutex); if (all_dishes_available == true) { all_dishes_availalbe = false; signal(cats_queue); /* let first cat in */ } cats_wait_count++; signal(mutex); wait(cats_queue); /*first cat in, other wait*/ if (no_cat_eat == true) {/*no_cat_eat:global*/ no_cat_eat = false; first_cat_eat = true;/*first_cat_eat:local*/ else first_cat_eat = false; The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

How does the first cat control the kitchen? if (first_cat_eat == true) { wait(mutex); if (cat_wait_count > 1) { another_cat_eat = true; signal(cats_queue); /*let another cat in*/ } signal(mutex); kprintf(“Cat in the kitchen.\n”); /*cat name*/ The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

All cats (first cat and non-first cat) in the kitchen. wait(dish_mutex); /*protect shared variables*/ if (dish1_busy == false) { dish1_busy = true; mydish = 1; } else { assert(dish2_busy == false); dish2_busy = true; mydish = 2; signal(dish_mutex); kprint(“Cat eating.\n”); /* cat name */ clocksleep(1); /* enjoys food */ kprint(“Finish eating.\n”); /* done. */ The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

All cats (first cat and non-first cat) release dishes. wait(dish_mutex); /*protect shared variables*/ if (mydish == 1) /* release dish 1 */ dish1_busy = false; else /* release dish 2 */ dish2_busy = false; signal(dish_mutex); wait(mutex); /*protect shared variables*/ cat_wait_count--; /*reduced before leaving*/ signal(mutex); The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

First cat is leaving the kitchen. if (first_cat_eat == true) { /* first cat */ if (another_cat_eat == true) wait(done); /* wait for another cat */ kprintf(“First cat is leaving.\n”); no_cat_eat = true; /*let next cat control*/ /* Switch to mice if any is waiting */ /* (1) Wake up mice */ /* (2) Wake up cat */ /* (3) set all_dishes_available to true */ The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

How to wake up waiting mice or cats? /* Switch to mice if any is waiting */ wait(mutex); /* protect shared variables */ if (mice_wait_count > 0) /* mice waiting */ signal(mice_queue); /* let mice eat */ else if (cats_wait_count > 0) signal(cats_queue); /* let cat eat */ else all_dishes_availalbe = true; signal(mutex); } /* end of first_cat_eat */ else { /* non-first cat is leaving */ kprintf(“Non-first cat is leaving\n”); signal(done); /* inform the first cat */ } The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times. C does not support bool #define true 1 #define false 0 typedef char bool;

Semaphore in OS/161 /* kern/include/synch.h */ struct semaphore { char *name; volatile int count; }; struct semaphore* sem_create(const char *name, int initial_count); void sem_destroy(struct semaphore *); void P(struct semaphore *); void V(struct semaphore *); /* Implemented in kern/thread/synch.c */ The Semaphore mechanism has been implemented in OS/161. Use the source code of semaphore as a good example for the implementation of locks and condition variables.

Semaphore: Sample Usage /* Declare a semaphore */ static semaphore *sample_sm; /* Initialize the semaphore */ sample_sm = sem_create(“sample semaphore", 0); if (sample_sm == NULL) { panic(”sample_sm: Out of memory.\n"); } /* Destroy the semaphore in the end */ sem_destroy(sample_sm); sample_sm = NULL; P(done); /* Wait for “done” */ V(done); /* Signal “done” */ /* static can limit the scope of global variable to only the file it is declared in */ "static" can be used to limit the scope of global variable to only the file it is declared in.

Locks in OS/161 /* kern/include/synch.h */ struct lock { char *name; /* add what you need here. How? */ }; struct lock *lock_create(const char *name); void lock_acquire(struct lock *); void lock_release(struct lock *); int lock_do_i_hold(struct lock *); void lock_destroy(struct lock *); struct thread *volatile holder; struct lock { char *name; // add what you need here // (don't forget to mark things volatile as needed) };

Lock: Sample Usage /* Declare a lock */ Static struct lock *sample_mutex; /* Initialize the lock */ sample_mutex = lock_create(”sample mutex"); if (sample_mutex == NULL) panic(”sample_mutex: Out of memory.\n"); /* Destroy the lock in the end */ lock_destroy(sample_mutex); sample_mutex = NULL; lock_acquire(sample_mutex); /* Acquire */ lock_release(sample_mutex); /* Release */

Implementing lock_acquire() void lock_acquire(struct lock *lock) { turn off interrupts; /*see P(*sem) in next slide*/ if (lock_do_i_hold(lock)) /* check deadlock */ panic("lock %s at %p: Deadlock.\n", lock->name, lock); /* wait the lock to become free */ while (lock’s holder != NULL) { sleep this thread; /*see P(*sem) in next slide*/ } /* this thread is holding the lock */ lock’s holder is set to curthread; turn on interrupts to the previous level;

How to sleep the current thread? void P(struct semaphore *sem) { int spl; assert(sem != NULL); spl = splhigh(); while (sem->count==0) { thread_sleep(sem); } assert(sem->count>0); sem->count--; splx(spl); Check input argument Turn off interrupts ‘sem’ is a mark or indicator Turn on interrupts

How to wakeup a thread? void V(struct semaphore *sem) { int spl; assert(sem != NULL); spl = splhigh(); sem->count++; assert(sem->count>0); thread_wakeup(sem); splx(spl); } Check input argument Turn off interrupts ‘sem’ is a mark or indicator Turn on interrupts

How to implement lock_do_i_hold? int lock_do_i_hold(struct lock *lock) { int spl, same; use assert() to input argument lock; Turn off interrupts; if (lock->holder is the same as this thread) set same to 1; /* true */ else set same to 0; /* false */ Turn on interrupts to previous level; /* 1 means lock is held by this thread */ return same; } Is lock held by this thread? lock != NULL This thread = curthread

Condition Variables: Data Structure Wait until a variable meets a particular condition There is no actual variable in the CV /* kern/include/synch.h */ struct cv { char *name; // add what you need here }; There is little information on condition variables in the textbook

Condition Variables: Functions struct cv *cv_create(const char *name); void cv_destroy(struct cv *); /* Release lock, put thread to sleep until cv is signaled; when thread wakes up again, re-acquire lock before returning */ void cv_wait(struct cv *cv, struct lock *lock); /* If any threads are waiting on cv, wake up one of them. Caller must hold lock, which must be the same as the lock used in the wait call */ void cv_signal(struct cv *cv, struct lock *lock); /* Same as signal, except wake up all waiting threads */ void cv_broadcast(struct cv *cv, struct lock *lock); References: http://web.stanford.edu/class/cs140/cgi-bin/lecture.php?topic=locks Operations: cv_wait - Release the supplied lock, go to sleep, and, after waking up again, re-acquire the lock. cv_signal - Wake up one thread that's sleeping on this CV. cv_broadcast - Wake up all threads sleeping on this CV.

Producer/Consumer Implementation with Locks char buffer[SIZE]; int count = 0, head = 0, tail = 0; static struct lock *mutex; mutex = lock_create(“mutex for cv”); void producer(char c) { lock_acquire(mutex); count++; buffer[head] = c; head++; if (head == SIZE) { head = 0; } lock_release(mutex); char consumer() { char c; lock_acquire(mutex); count--; c = buffer[tail]; tail++; if (tail == SIZE) { tail = 0; } lock_release(mutex); return c; Let’s consider the producer/consumer sample to show how to use condition variables We start this example with locks. 3. No need to use static here; just a demonstration

How to handle the empty/full cases using locks? void producer(char c) { lock_acquire(mutex); while (count == SIZE) { lock_release(mutex); } count++; buffer[head] = c; head++; if (head == SIZE) head = 0; char consumer() { char c; lock_acquire(mutex); while (count == 0) { lock_release(mutex); } count--; c = buffer[tail]; tail++; if (tail == SIZE) { tail = 0; return c; Which lock_acqure and lock_release are a pair? Which lock_acqure() and lock_release() are a pair?

How to implement cv_wait()? void cv_wait(struct cv *cv, struct lock *lock) { use assert to check input cv and lock; turn off interrupts; release the lock; /* thread_sleep() using cv or lock? */ sleep the thread until someone signals cv; acquire the lock; turn on interrupts to the previous level; } cv shouldn’t be NULL lock shouldn’t be NULL

How to implement cv_signal()? void cv_signal(struct cv *cv, struct lock *lock) { use assert to check cv and lock; turn off interrupts; /* !lock_do_i_hold(lock) */ if (this thread does not hold lock) panic("cv_signal error: cv %s at %p, lock %s at %p.\n", cv->name, cv, lock->name, lock); /* see also how to wakeup a thread Slide 15 */ wakeup one thread using indicator “cv”; turn on interrupts to the previous level; } cv shouldn’t be NULL lock shouldn’t be NULL

Condition Variables: Sample Usage /* Declare a cv */ static struct cv *sample_cv; /* Initialize the cv */ sample_cv = cv_create(”sample cv"); if (sample_cv == NULL) panic(”sample_cv: Out of memory.\n"); /* Destroy the cv in the end */ cv_destroy(sample_cv); sample_cv = NULL; cv_wait(sample_cv, sample_lock); /* Wait */ cv_signal(sample_cv, sample_lock); /*Signal*/

Producer/Consumer How to use condition variables in OS/161? char buffer[SIZE]; int count = 0, head = 0, tail = 0; static struct lock *mutex; static struct cv *notEmpty; static struct cv *notFull; mutex = lock_create(“mutex for cv”); if (mutex == NULL) panic(”mutex: Out of memory.\n"); notEmpty = cv_create(“Buffer not empty”); notFull = cv_create(“Buffer not full”); if (notEmpty == NULL || notFull == NULL) panic(”CV: Out of memory.\n"); Which lock_acqure and lock_release are a pair?

Producer: how to use condition variables in OS/161? void producer(char c) { lock_acquire(mutex); while (count == SIZE) { cv_wait(notFull, mutex); } count++; buffer[head] = c; head++; if (head == SIZE) { head = 0; cv_signal(notEmpty, mutex); lock_release(mutex);

Consumer: how to use condition variables in OS/161? char consumer() { char c; lock_acquire(mutex); while (count == 0) { cv_wait(notEmpty, mutex); } count--; c = buffer[tail]; tail++; if (tail == SIZE) { tail = 0; cv_signal(notFull, mutex); lock_release(mutex); return c;