# 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