---
# System prepended metadata

title: SO - Lista 13
tags: [SO]

---

# SO - Lista 13
###### tags: `SO`


## Zadanie 1

![](https://i.imgur.com/B945tKr.png)

1. Odwrócenie priorytetów - Wątek o niskim priorytecie zakłada blokadę na sekcję krytyczną. Następnie zostaje wywłaszczony, przez co żaden inny wątek o wyższym priorytecie nie może kontynuować działania (Wątki o wyższym priorytecie czekają na zakończenie programu o niższym priorytecie)

2. Dziedziczenie priorytetów - Metoda rozwiązywania problemu odwróconych priorytetów, polegająca na tymczasowym zwiększeniu priorytetu wątku będącego w sekcji krytycznej, by ten mógł zdjąć blokadę.

    ![](https://i.imgur.com/mqOfBnR.png)

3. Dlaczego mutex pamięta właściciela? - Żeby wiedzieć kto założył blokadę i kogo trzeba wypromować

4. Operacja mutex_lock w przypadku założonej blokady odczytuje właściciela mutexa i zwiększa jego priorytet. Mutex_unlock po ściągnięciu blokady ustawia swój priorytet na domyślną wartość.

5. NIE!

## Zadanie 2

![](https://i.imgur.com/w1pjige.png)

```c=
typedef struct Sem {
    pthread_mutex_t mutex;
    pthread_cond_t waiters;
    int value;
} Sem_t;
```

## Zadanie 3

![](https://i.imgur.com/CGMjP7n.png)

## Zadanie 4

![](https://i.imgur.com/BrvYsyS.png)

```python=
mutex = semaphore(1) # implementuje sekcję krytyczną
block = semaphore(0) # oczekiwanie na opuszczenie zasobu
active = 0 # liczba użytkowników zasobu
waiting = 0 # liczba użytkowników oczekujących na zasób
must_wait = False # czy kolejni użytkownicy muszą czekać?
```

```python=
def acquire():
    mutex.wait()
    if must_wait: # czy while coś zmieni?
        waiting += 1
        mutex.post()
        block.wait()
        mutex.wait()
        waiting -= 1
    active += 1
    must_wait = (active == 3)
    mutex.post()
    
def release():
    mutex.wait()
    active -= 1
    if active == 0:
        n = min(waiting, 3);
        while n > 0:
            block.post()
            n -= 1
        must_wait = False
    mutex.post()
```
1. 
    1. 3 procesy biorą zasób
    2. Kolejne 3 blokują się (linijka 6)
    3. Wychodzą procesy trzymajace zasob
    4. Ostatni z nich zwalnia blokady zalozone na procesy
    5. Po nim przychodzi nowy proces (active=1)
    6. Trzy zablokowane wczesniej procesy kolejno korzystaja z zasobu (active=)

2. (W wersji z while)
    1. 3 procesy korzystają z zasobu
    2. 3 procesy w kolejce są blokowane przez block.wait()
    3. Zostaje wykonany release()
    4. Must_wait = 0
    5. 4 proces z kolejki pierwszy woła mutex.wait()
    6. Zabiera zasób
    7. 2 kolejne procesy też wchodzą do zasobów
    8. 3 proces z kolejki kręci się w pętli
    9. KONIEC!

## Zadanie 5

![](https://i.imgur.com/EBUdcs1.png)

```c=
#include "csapp.h"

static __unused void outc(char c) {
  Write(STDOUT_FILENO, &c, 1);
}

static void randsleep(void) {
  usleep(rand() % 5000 + 5000);
}

#define N 50

static pthread_t td[N];
static sem_t forks[N];
/* TODO: If you need extra shared state, define it here. */
static sem_t counter;

void *philosopher(void *id) {
  int right = (intptr_t)id;
  int left = right == 0 ? N - 1 : right - 1;

  for (;;) {
    /* Think */
    randsleep();

    /* TODO: Take forks (without deadlock & starvation) */
    // N=5
    Sem_wait(&counter);
    Sem_wait(&forks[right]);
    Sem_wait(&forks[left]);
    printf("Eating using %d and %d\n", left, right);
    /* Eat */
    randsleep();
    printf("Finished using %d and %d\n", left, right);
    /* TODO: Put forks (without deadlock & starvation) */
    Sem_post(&forks[left]);
    Sem_post(&forks[right]);
    Sem_post(&counter);
  }

  return NULL;
}

int main(void) {
  /* TODO: If you need extra shared state, initialize it here. */
  Sem_init(&counter, 0, N-1);

  for (int i = 0; i < N; i++)
    Sem_init(&forks[i], 0, 1);

  for (int i = 0; i < N; i++)
    Pthread_create(&td[i], NULL, philosopher, (void *)(intptr_t)i);

  for (int i = 0; i < N; i++)
    Pthread_join(td[i], NULL);
  
  return EXIT_SUCCESS;
}
```

## Zadanie 6

![](https://i.imgur.com/0NVObMI.png)

```c=
#include "csapp.h"

static __unused void outc(char c) {
  Write(STDOUT_FILENO, &c, 1);
}

#define N 100
#define M 100

static struct {
  /* TODO: Put semaphores and shared variables here. */
    int food;
    sem_t empty;
    sem_t full;
    sem_t mutex;
} *shared = NULL;


static void savage(void) {
    for (;;) {
    /* TODO Take a meal or wait for it to be prepared. */
    Sem_wait(&shared->mutex);
    if (shared->food == 0){
        Sem_post(&shared->empty);
        Sem_wait(&shared->full);
    }
    shared->food--;
    printf("[%d] eating %d left\n", getpid(), shared->food);
    Sem_post(&shared->mutex);
    /* Sleep and digest. */
    usleep(rand() % 1000 + 1000);
  }

  exit(EXIT_SUCCESS);
}

static void cook(void) {
  for (;;) {
    Sem_wait(&shared->empty);
    shared->food = M;
    printf("[%d] cooking\n", getpid());
    Sem_post(&shared->full);
  }
}

/* Do not bother cleaning up after this process. Let's assume that controlling
 * terminal sends SIGINT to the process group on CTRL+C. */
int main(void) {
    shared = Mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
                -1, 0);

    /* TODO: Initialize semaphores and other shared state. */
    Sem_init(&shared->mutex, 1, 1);
    Sem_init(&shared->empty, 1, 0);
    Sem_init(&shared->full, 1, 0);
    shared->food = M;
    
    for (int i = 0; i < N; i++)
        if (Fork() == 0)
            savage();

    cook();

    return EXIT_SUCCESS;
}
```

## Zadanie 7

![](https://i.imgur.com/PDzU0jG.png)

## Zadanie 8

![](https://i.imgur.com/CZuydjq.png)