Concurrency in Operating Systems: A Comprehensive Guide, Schemes and Mind Maps of Operating Systems

OPERATING SYSTEMS: THREE EASY PIECES. By Arpaci-Dusseau and Arpaci-Dusseau. Chapter 2.3. MODERN OPERATING SYSTEMS (MOS). By Andrew Tanenbaum ...

Typology: Schemes and Mind Maps

2022/2023

Uploaded on 03/01/2023

jesus33
jesus33 🇺🇸

4.2

(16)

422 documents

1 / 30

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Operating Systems
Concurrency
ENCE 360
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e

Partial preview of the text

Download Concurrency in Operating Systems: A Comprehensive Guide and more Schemes and Mind Maps Operating Systems in PDF only on Docsity!

Operating Systems

Concurrency

ENCE 360

Outline

• Introduction

• Solutions

• Classic Problems

Chapter 26, 28, 31 OPERATING SYSTEMS: THREE EASY PIECES By Arpaci-Dusseau and Arpaci-Dusseau Chapter 2. MODERN OPERATING SYSTEMS (MOS) By Andrew Tanenbaum

The Heart of the Problem

Display information from object file - machine instructions:

objdump –-source thread-v [line 415] g_counter++; 400c38: 8b 05 6e 14 20 00 mov 0x201465,%eax # 6020ac <g_counter> 400c3e: 83 c0 01 add $0x1,%eax 400c41: 89 05 65 14 20 00 mov %eax,0x201465 # 6020ac <g_counter> Source code from “-g” flag Address Object code Assembly code Reference location

Let’s zoom in …

The Heart of the Problem (Zoom)

mov g_counter %eax add 1 %eax mov %eax g_counter mov 0x20146e(%rip),%eax add $0x1,%eax mov %eax,0x201465(%rip) Counter is 50. Thread T1 & T2, one processor. WCGW?

Not

“critical section” “race condition”

The Heart of the Solution

• Instead, provide synchronization primitives

 Programmer can use for atomicity (and more)

THE CRUX OF THE PROBLEM:

HOW TO PROVIDE SUPPORT FOR SYNCHRONIZATION?

What synchronization primitives should be provided? What support needed from hardware to build? How to make correct and efficient? How do programmers use them?

Useful Terms*

• Critical section – code that access shared

resource (e.g., variable or data structure)

• Race condition – arises when multiple

threads/processes simultaneously enter critical

section leading to non-deterministic outcome

• Indeterminant program – program with 1+ race

conditions, so output varies run to run

• Mutual exclusion – method to guarantee only 1

thread/process active in critical section at a time

  • That all good systems-programmers (you!) should know

Illustration of Critical Region

What basic mechanism can stop B from entering critical region when A in? Hint: just need to block access

How to Use a Lock

lock_t mutex; // globally-allocated ’mutex’ … lock(&mutex); x = x + 1; // critical region unlock(&mutex);

THE CRUX: HOW TO BUILD A LOCK?

How to build efficient lock? What hardware support is needed? What OS support? pthread_mutex_t lock; pthread_mutex_lock(&lock); x = x + 1; // or general CR pthread_mutex_unlock(&lock); See: “thread-v1.c”

Many Problems with Disabling

Interrupts in General

  • Privileged operations, so must trust user code - But may never unlock! (unintentional or
malicious)
  • Does not work for multiprocessors
    • Second processor may still access
shared resource
  • When interrupts off, subsequent ones may become lost - E.g., disk operations Disk Register s CPU Register s CPU Mem

Lock Solution, Take 2

int mutex; // 0 -> lock available, 1 -> held
void lock(int *mutex) {
while (*mutex == 1) // TEST flag
; // spin-wait (do nothing)
*mutex = 1; // now SET it!
void unlock(int *mutex) {
*mutex = 0;

This almost works … but not quite. Why not? Hint, has race condition - Can you spot it?

Synchronization Hardware –

Test and Set

Test-and-Set: returns and modifies atomically

int TestAndSet(int *mutex) {

int temp;

temp = *mutex;

*mutex = true;

return temp;

Done with hardware support. All modern computers since 1960’s e.g., x86 has compare-and-exchange Others: compare-and-swap, fetch- and-add, … all atomic

Lock Solution, Take 3

int mutex; // 0 -> lock available, 1 -> held void lock(int *mutex) { while (TestAndSet(mutex)) // 1 if held ; // spin-wait (do nothing) // once here, have lock! } void unlock(int *mutex) { *mutex = 0; } Note, no need to protect unlock() (Exercise: why not?) Now, what is major remaining shortcoming? Hint: code works, but could be more efficient

Synchronization Primitive - Semaphore

  • “Special” integer, provided by OS
  • Only accessible through two routines: sem_post() sem_wait()
  • Both routines are atomic int sem_wait(sem_t &s) { s = s - 1 if (s < 0) add process to queue and sleep } int sem_post(sem_t &s) { s = s + 1 if (s <= 0) remove process from queue and wake } Operational Model value of counter = number of procs that may pass before closed counter <= 0  gate closed! blocked process "waits" in Q counter < 0  number of processes waiting in Q

How to Use a Semaphore

semaphore mutex; // globally-allocated

wait(&mutex);

x = x + 1; // critical region

signal(&mutex);

Easy, peasy!

And available on most operating systems

Can use for general synchronization problems (next)