-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdongles.c
More file actions
102 lines (92 loc) · 3.64 KB
/
Copy pathdongles.c
File metadata and controls
102 lines (92 loc) · 3.64 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* dongles.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: dporhomo <dporhomo@student.42prague.com +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/06/08 18:42:33 by dporhomo #+# #+# */
/* Updated: 2026/06/15 13:20:13 by dporhomo ### ########.fr */
/* */
/* ************************************************************************** */
/* Grabs and drops dongles */
#include "codexion.h"
/* if waiting is due to cooldown, timestamp is set to wake up the pthread.
if waiting is due to priority, cond_wait is set */
void wait_for_dongles(t_coder *coder)
{
long long max_ready;
struct timespec ts;
max_ready = coder->prog->dongle_ready_time[coder->left_dongle];
if (coder->prog->dongle_ready_time[coder->right_dongle] > max_ready)
max_ready = coder->prog->dongle_ready_time[coder->right_dongle];
if (max_ready > get_current_time())
{
ts = ms_to_timespec(max_ready);
pthread_cond_timedwait(&coder->prog->coder_cond[coder->id - 1],
&coder->prog->arbitrator, &ts);
}
else
pthread_cond_wait(&coder->prog->coder_cond[coder->id - 1],
&coder->prog->arbitrator);
}
/* Sets dongle_ready_time to infinite, turns mutex locks, locks dongles
Ensures every single coder always locks the lower-numbered mutex
before the higher-numbered mutex. This breaks the circle and prevents
the OS (and ThreadSanitizer) from detecting
an "AB-BA Lock Inversion" deadlock. */
void lock_dongles(t_coder *coder)
{
int first;
int second;
first = coder->left_dongle;
second = coder->right_dongle;
if (first > second)
{
first = coder->right_dongle;
second = coder->left_dongle;
}
coder->prog->dongle_ready_time[coder->left_dongle] = LLONG_MAX;
coder->prog->dongle_ready_time[coder->right_dongle] = LLONG_MAX;
pthread_mutex_unlock(&coder->prog->arbitrator);
pthread_mutex_lock(&coder->prog->dongles[first]);
print_status(coder, "has taken a dongle");
pthread_mutex_lock(&coder->prog->dongles[second]);
print_status(coder, "has taken a dongle");
}
/* Coder grabs and locks dongles */
int grab_dongles(t_coder *coder)
{
t_request req;
req.coder_id = coder->id;
req.req_time = get_current_time();
req.deadline = coder->last_compile + coder->prog->t_burnout;
pthread_mutex_lock(&coder->prog->arbitrator);
pq_push(&coder->prog->pq, req);
while (!can_compile(coder) && read_sim_active(coder->prog))
wait_for_dongles(coder);
pq_remove_coder(&coder->prog->pq, coder->id);
if (!read_sim_active(coder->prog))
{
pthread_mutex_unlock(&coder->prog->arbitrator);
return (0);
}
lock_dongles(coder);
return (1);
}
/* Unlocks dongles, sets dongle_ready_time, cond_signal */
void drop_dongles(t_coder *coder)
{
int i;
long long ready;
pthread_mutex_lock(&coder->prog->arbitrator);
pthread_mutex_unlock(&coder->prog->dongles[coder->left_dongle]);
pthread_mutex_unlock(&coder->prog->dongles[coder->right_dongle]);
ready = get_current_time() + coder->prog->cooldown;
coder->prog->dongle_ready_time[coder->left_dongle] = ready;
coder->prog->dongle_ready_time[coder->right_dongle] = ready;
i = -1;
while (++i < coder->prog->num_coders)
pthread_cond_signal(&coder->prog->coder_cond[i]);
pthread_mutex_unlock(&coder->prog->arbitrator);
}