-
Notifications
You must be signed in to change notification settings - Fork 0
/
skier.h
88 lines (81 loc) · 2.26 KB
/
skier.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#ifndef SKIER_H
#define SKIER_H
#include "print.h"
#include "config.h"
#include "bus.h"
enum skier_state
{
sk_start,
sk_breakfast,
sk_waiting,
sk_boarding,
sk_aboard,
sk_exiting,
sk_done
};
typedef enum skier_state sk_state;
struct skier
{
unsigned int id;
unsigned bus_stop : 4;
enum skier_state state;
};
typedef struct skier skier;
void sk_init(skier *ski, unsigned int id, unsigned char stop)
{
ski->id = id;
ski->state = sk_start;
ski->bus_stop = stop & 0xf;
}
// wait for specific mutexes
void sk_change(skier *ski)
{
switch (ski->state)
{
case sk_start:
print("L %d: started\n", ski->id);
ski->state = sk_breakfast;
break;
case sk_breakfast:
usleep(rand() % cfg.ski_wait); // should be safe since I initialised srand()
ski->state = sk_waiting;
break;
case sk_waiting:
print("L %d: arrived to %d\n", ski->id, (int)(ski->bus_stop) + 1);
bs_inc(skibus, (int)(ski->bus_stop));
ski->state = sk_boarding;
break;
case sk_boarding: // sk boarding needs to first assure that it has boarding permission on that specific stop
sem_wait(&(skibus->boarding_sem)[(int)(ski->bus_stop)]);
if (bs_free(skibus) == 0){ // inform skier no space is left and to give up the flag
sem_post(&(skibus->boarding_sem)[(int)(ski->bus_stop)]);
break;
}
bs_board(skibus);
print("L %d: boarding\n", ski->id);
bs_dec(skibus, ski->bus_stop);
if (bs_free(skibus) == 0 || bs_get(skibus, (ski->bus_stop)) == 0){ // inform bus to depart
bs_depart(skibus);
}
sem_post(&(skibus->boarding_sem)[(int)(ski->bus_stop)]);
ski->state = sk_aboard;
break;
case sk_aboard:
sem_wait(&(skibus->boarding_sem)[cfg.stops - 1]);
ski->state = sk_exiting;
break;
case sk_exiting:
bs_exit(skibus);
print("L %d: going to ski\n", ski->id);
ski->state = sk_done;
sem_post(&(skibus->boarding_sem)[cfg.stops - 1]);
if (bs_aboard(skibus) == 0) // inform bus to depart
bs_depart(skibus);
break;
default:
break;
}
if (ski->state != sk_done)
sk_change(ski);
}
#endif