# 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



trzyma właściciela do promocji i do przywrócenia promocji

## Zadanie 2

```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

## Zadanie 4

## Zadanie 5


```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


```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


```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



```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;
}
```