# 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