# Lista 13 ###### tags: `SO2022` ## Deklaracja :::spoiler | Zadanie | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |-----------|---|---|---|---|---|---|---|---| |Deklaracja |:heavy_check_mark:|:heavy_check_mark:|||:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| ::: ## Zadanie 1 Opisz leszczu ![](https://i.imgur.com/cBau33V.png) ![](https://i.imgur.com/6ek3iKb.png) ![](https://i.imgur.com/M9aMWph.png) trzyma właściciela do promocji i do przywrócenia promocji ![](https://i.imgur.com/u4wZdiz.png) ## Zadanie 2 ![](https://i.imgur.com/4f4nBcl.png) ```c= typedef struct Sem { pthread_mutex_t mutex; pthread_cond_t waiters; int value; } Sem_t; void sem_init(Sem_t* s, int value) { assert(value >= 0); s->value = value; assert(pthread_mutex_init(&s->mutex, NULL) == 0); assert(pthread_cond_init(&s->waiters, NULL) == 0); } void sem_post(Sem_t* s) { pthread_mutex_lock(&s->mutex); s->value++; pthread_cond_signal(*s->waiters); pthread_mutex_unlock(&s->mutex); } void sem_wait(Sem_t* s) { pthread_mutex_lock(&s->mutex); while (s->value <= 0) { pthread_cond_wait(&s->waiters, &s->mutex); } s->value--; pthread_mutex_unlock(&s->mutex); } ``` ## Zadanie 3 ![](https://i.imgur.com/6faUUda.png) ## Zadanie 4 ![](https://i.imgur.com/ynVTdFn.png) ## Zadanie 5 ![](https://i.imgur.com/OCmGqrk.png) ![](https://i.imgur.com/xHhprA6.png) ```c= #include "csapp.h" static __unused void outc(char c) { Write(STDOUT_FILENO, &c, 1); } static void randsleep(void) { usleep(rand() % 5000 + 5000); // usleep(2); } #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 waiter; 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) */ Sem_wait(&waiter); printf("%ld Wait Right\n", (intptr_t)id); Sem_wait(&forks[right]); printf("%ld Wait Left\n", (intptr_t)id); Sem_wait(&forks[left]); /* Eat */ randsleep(); /* TODO: Put forks (without deadlock & starvation) */ Sem_post(&forks[left]); Sem_post(&forks[right]); Sem_post(&waiter); } return NULL; } int main(void) { /* TODO: If you need extra shared state, initialize it here. */ Sem_init(&waiter, 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/hI4ukX3.png) ![](https://i.imgur.com/XM9HEAQ.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. */ sem_t full_pot; sem_t empty_pot; sem_t put_in_bowl; size_t stew; } *shared = NULL; static void savage(void) { for (;;) { /* TODO Take a meal or wait for it to be prepared. */ Sem_wait(&shared->put_in_bowl); if(!shared->stew){ printf("%d empty pot",getpid()); Sem_post(&shared->empty_pot); Sem_wait(&shared->full_pot); } shared->stew--; printf("%d eat, stew: %ld\n",getpid(),shared->stew); Sem_post(&shared->put_in_bowl); /* 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_pot); printf("[cook] Prepare gulash\n"); shared->stew = M; Sem_post(&shared->full_pot); } } /* 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->full_pot, 1,0); Sem_init(&shared->empty_pot, 1,0); Sem_init(&shared->put_in_bowl,1,1); shared->stew = M; for (int i = 0; i < N; i++) if (Fork() == 0) savage(); cook(); return EXIT_SUCCESS; } ``` ## Zadanie 7 ![](https://i.imgur.com/8emi2Qv.png) ![](https://i.imgur.com/vUJPHbL.png) ```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. */ sem_t sem_act; sem_t barrier2; sem_t barrier1; size_t actual; size_t size; } barrier_t; static barrier_t *barrier_init(int 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->size = n; b->actual = 0; sem_init(&b->sem_act, 1, 1); sem_init(&b->barrier2, 1, 0); sem_init(&b->barrier1, 1, n); return b; } static void barrier_wait(barrier_t *b) { /* TODO: Provide wait procedure implementation here. */ // Etap 1 Wpuść N Koni sem_wait(&b->barrier1); // Policz Konie sem_wait(&b->sem_act); b->actual++; int act = b->actual; sem_post(&b->sem_act); // Wystartuj etap 2 if(act == b->size) { for(int i = 0; i < b->size; i++) sem_post(&b->barrier2); } // Etap 2 Wypuść N Koni sem_wait(&b->barrier2); sem_wait(&b->sem_act); b->actual--; act = b->actual; sem_post(&b->sem_act); if(act == 0) { for(int i = 0; i < b->size; i++) sem_post(&b->barrier1); } } static void barrier_destroy(barrier_t *b) { /* TODO: Provide destroy procedure implementation here. */ } #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://i.imgur.com/5a1yNCB.png) ![](https://i.imgur.com/IrUUdTS.png) ![](https://i.imgur.com/PqBB27z.png) ```c= #include "csapp.h" static __unused void outc(char c) { Write(STDOUT_FILENO, &c, 1); } static __thread unsigned seed; static sem_t tobacco; static sem_t matches; static sem_t paper; static sem_t doneSmoking; /* TODO: If you need any extra global variables, then define them here. */ static bool isTobacco; static bool isMatches; static bool isPaper; static sem_t tobacco_s; static sem_t matches_s; static sem_t paper_s; static sem_t pusher; static void *agent(void *arg) { seed = pthread_self(); while (true) { Sem_wait(&doneSmoking); int choice = rand_r(&seed) % 3; if (choice == 0) { Sem_post(&tobacco); Sem_post(&paper); } else if (choice == 1) { Sem_post(&tobacco); Sem_post(&matches); } else { Sem_post(&paper); Sem_post(&matches); } } return NULL; } /* TODO: If you need extra threads, then define their main procedures here. */ static void *pusher_t(void *arg) { while (true) { sem_wait(&tobacco); // printf("Get T\n"); sem_wait(&pusher); if (isPaper) { isPaper = false; sem_post(&matches_s); } else if (isMatches) { isMatches = false; sem_post(&paper_s); } else { isTobacco = true; } // printf("T= T: %d M: %d P: %d\n", isTobacco, isMatches, isPaper); sem_post(&pusher); } return NULL; } static void *pusher_m(void *arg) { while (true) { sem_wait(&matches); // printf("Get M\n"); sem_wait(&pusher); if (isPaper) { isPaper = false; sem_post(&tobacco_s); } else if (isTobacco) { isTobacco = false; sem_post(&paper_s); } else { isMatches = true; } // printf("M= T: %d M: %d P: %d\n", isTobacco, isMatches, isPaper); sem_post(&pusher); } return NULL; } static void *pusher_p(void *arg) { while (true) { sem_wait(&paper); // printf("Get P\n"); sem_wait(&pusher); if (isTobacco) { isTobacco = false; sem_post(&matches_s); } else if (isMatches) { isMatches = false; sem_post(&tobacco_s); } else { isPaper = true; } // printf("P= T: %d M: %d P: %d\n", isTobacco, isMatches, isPaper); sem_post(&pusher); } return NULL; } static void randsleep(void) { usleep(rand_r(&seed) % 1000 + 1000); } static void make_and_smoke(char smoker) { randsleep(); Sem_post(&doneSmoking); outc(smoker); randsleep(); } static void *smokerWithMatches(void *arg) { seed = pthread_self(); while (true) { /* TODO: wait for paper and tobacco */ sem_wait(&matches_s); make_and_smoke('M'); } return NULL; } static void *smokerWithTobacco(void *arg) { seed = pthread_self(); while (true) { /* TODO: wait for paper and matches */ sem_wait(&tobacco_s); make_and_smoke('T'); } return NULL; } static void *smokerWithPaper(void *arg) { seed = pthread_self(); while (true) { /* TODO: wait for tobacco and matches */ sem_wait(&paper_s); make_and_smoke('P'); } return NULL; } int main(void) { Sem_init(&tobacco, 0, 0); Sem_init(&matches, 0, 0); Sem_init(&paper, 0, 0); Sem_init(&doneSmoking, 0, 1); /* TODO: Initialize your global variables here. */ isTobacco = false; isMatches = false; isPaper = false; Sem_init(&tobacco_s, 0, 0); Sem_init(&matches_s, 0, 0); Sem_init(&paper_s, 0, 0); Sem_init(&pusher, 0, 1); pthread_t pusherT, pusherM, pusherP; Pthread_create(&pusherT, NULL, pusher_t, NULL); Pthread_create(&pusherM, NULL, pusher_m, NULL); Pthread_create(&pusherP, NULL, pusher_p, NULL); pthread_t agentThread; Pthread_create(&agentThread, NULL, agent, NULL); pthread_t smokerPaperThread, smokerMatchesThread, smokerTobaccoThread; Pthread_create(&smokerPaperThread, NULL, smokerWithPaper, NULL); Pthread_create(&smokerMatchesThread, NULL, smokerWithMatches, NULL); Pthread_create(&smokerTobaccoThread, NULL, smokerWithTobacco, NULL); Pthread_join(agentThread, NULL); Pthread_join(smokerPaperThread, NULL); Pthread_join(smokerMatchesThread, NULL); Pthread_join(smokerTobaccoThread, NULL); Pthread_join(pusherT, NULL); Pthread_join(pusherM, NULL); Pthread_join(pusherP, NULL); return 0; } ```