---
# System prepended metadata

title: Lista 13
tags: [SO]

---

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

## Zadanie 1

Odwrócenie priorytetów - wątek o niskim priorytecie trzyma zamek, a wątek z wysokim priorytetem czeka. Wątek o niskim priorytecie nie może zwolnić zamka, ponieważ z powodu niskiego priorytetu nie dostanie czasu procesora.

Dziedziczenie priorytetów - tymczasowe podniesienie priorytetu procesu zajmującego zasób do najwyższego priorytetu procesu oczekującego na ten zasób.

Mutex pamięta właściciela, aby inny proces nie zwolnił go.


**W jaki sposób należy rozszerzyć implementację operacji «mutex_lock» i «mutex_unlock», żeby nie dopuścić do odwrócenia priorytetów?**

Aby rozszerzyć implementację operacji "mutex_lock" i "mutex_unlock" w celu uniknięcia odwrócenia priorytetów należy zastosować metodę dziedziczenia priorytetów.
W trakcie operacji "mutex_lock", przed udostępnieniem zasobu, należy sprawdzić czy proces, który próbuje uzyskać dostęp do zasobu ma wyższy priorytet niż proces, który już go posiada. Jeśli proces ma niższy priorytet, jest blokowany, a jeśli proces ma wyższy priorytet, jego priorytet jest dziedziczony przez proces, który już posiada zasób.
W trakcie operacji "mutex_unlock" należy przywrócić pierwotny priorytet procesu, który zasób posiadał przed jego udostępnieniem.
To rozwiązanie zapewni, że proces o niższym priorytecie nie będzie blokował procesu o wyższym priorytecie, co pozwoli uniknąć problemu odwrócenia priorytetów.

**Czy semafory są odporne na problem odwrócenia priorytetów?**
Nie.


## Zadanie 2



## Zadanie 3



## Zadanie 4



## Zadanie 5



## Zadanie 6

```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. */
  volatile int portions;
  sem_t counter;
  sem_t empty;
  sem_t full;
} *shared = NULL;

static void savage(void) {
  for (;;) {
    /* TODO Take a meal or wait for it to be prepared. */
    Sem_wait(&shared->counter);  
    if (shared->portions == 0) {
      Sem_post(&shared->empty);
      Sem_wait(&shared->full);
    }
    shared->portions -= 1;
    outc('S');
    Sem_post(&shared->counter);
    /* Sleep and digest. */
    usleep(rand() % 1000 + 1000);
  }

  exit(EXIT_SUCCESS);
}

static void cook(void) {
  for (;;) {
    /* TODO Cook is asleep as long as there are meals.
     * If woken up they cook exactly M meals. */
    Sem_wait(&shared->empty);
    shared->portions = M;
    outc('\n');
    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. */
  shared->portions = 0;
  Sem_init(&shared->counter, 1, 1);
  Sem_init(&shared->empty, 1, 0);
  Sem_init(&shared->full, 1, 0);

  for (int i = 0; i < N; i++)
    if (Fork() == 0)
      savage();

  cook();

  return EXIT_SUCCESS;
}

```

## Zadanie 7

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

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

typedef struct {
    /* TODO: Use this structure to store barrier internal state. */
    int n;
    int count;
    sem_t sem1;
    sem_t sem2;
} barrier_t;

static barrier_t *barrier_init(int n) {
    printf("BARIER int %d\n", n);
    if (n < 1)
        app_error("barrier_init requires n > 0");

    barrier_t *b = Mmap(NULL, sizeof(barrier_t), PROT_READ | PROT_WRITE,
                        MAP_ANON | MAP_SHARED, -1, 0);

    /* TODO: Initialize barrier internal state. */
    b->count = 0;
    b->n = n;
    Sem_init(&b->sem1, 0, 1);
    Sem_init(&b->sem2, 0, 1);
    return b;
}

static void barrier_wait(barrier_t *b) {
    /* TODO: Provide wait procedure implementation here. */
    // Sem_wait(&b->sem1);
    // b->count++;
    // // printf("%d\n", b->count);
    // if(b->count <= b->n){
    //     b->count = 0;
    //     for(int i = 1; i < b->n; i++)
    //         Sem_post(&b->sem2);
    //     Sem_post(&b->sem1);
    // } else{
    //     Sem_post(&b->sem1);
    //     Sem_wait(&b->sem2);
    // }

    Sem_wait(&b->sem1);
    b->count++;
    if(b->n == b->count) {
        b->count = 0;
        Sem_post(&b->sem2);
    }

    Sem_post(&b->sem1);
    Sem_wait(&b->sem2);
    Sem_post(&b->sem2);
}

static void barrier_destroy(barrier_t *b) {
    /* TODO: Provide destroy procedure implementation here. */
    Sem_post(&b->sem2);
}

#define K 100
#define N 50
#define P 100

static noreturn void horse(barrier_t *b) {
    int n = rand() % K + K;

    outc('+');

    for (int i = 0; i < n; i++) {
        barrier_wait(b);
        usleep(rand() % 2000 + 1000);
    }

    outc('-');

    exit(EXIT_SUCCESS);
}

/* 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) {
    barrier_t *b = barrier_init(N);

    int horses = 0;

    for (;;) {
        do {
            if (Fork() == 0) {
                srand(getpid());
                horse(b);
            }
            horses++;
        } while (horses < P);

        Wait(NULL);
        horses--;
    }

    barrier_destroy(b);

    return EXIT_SUCCESS;
}

```

## Zadanie 8


https://prod.liveshare.vsengsaas.visualstudio.com/join?FA455D849E5A28774BFCA6F881423C9B9917