-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paththreads.c
227 lines (187 loc) · 4.68 KB
/
threads.c
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
12/6/2017
Authors: Connor Lundberg, Jacob Ackerman, Jasmine Dacones
*/
#include "pcb.h"
unsigned int global_largest_MID;
/*
This was used in testing to make sure everything was working as it should.
*/
void printNull2 (Mutex mutex) {
printf("pcb1 is null: %d\n", (mutex->pcb1 == NULL));
if (mutex->pcb1 != NULL) {
printf("pcb1 values\n");
toStringPCB(mutex->pcb1, 0);
}
printf("pcb2 is null: %d\n", (mutex->pcb2 == NULL));
if (mutex->pcb2 != NULL) {
printf("pcb2 values\n");
toStringPCB(mutex->pcb2, 0);
}
printf("hasLock is null: %d\n", (mutex->hasLock == NULL));
if (mutex->hasLock != NULL) {
printf("hasLock values\n");
toStringPCB(mutex->hasLock, 0);
}
printf("blocked is null: %d\n", (mutex->blocked == NULL));
if (mutex->blocked != NULL) {
printf("blocked values\n");
toStringPCB(mutex->blocked, 0);
}
}
/*
Creates and initializes the value of the mutex.
*/
Mutex mutex_create () {
Mutex mutex = (Mutex) malloc (sizeof (struct MUTEX));
ConditionVariable cv = (ConditionVariable) malloc (sizeof (struct COND_VAR));
cond_var_init(cv);
mutex->condVar = cv;
mutex->isLocked = 0;
mutex->hasLock = NULL;
mutex->blocked = NULL;
mutex->pcb1 = NULL;
mutex->pcb2 = NULL;
mutex->mid = global_largest_MID;
global_largest_MID++;
return mutex;
}
/*
Initializes the value and increments to MID.
*/
void mutex_init (Mutex mutex) {
mutex->isLocked = 0;
mutex->hasLock = NULL;
mutex->blocked = NULL;
mutex->pcb1 = NULL;
mutex->pcb2 = NULL;
mutex->mid = global_largest_MID;
global_largest_MID++;
}
/*
Locks the given mutex. Sets the hasLocked PCB value to be the PCB given.
If the mutex is already locked and the calling pcb was the one that locks it,
a big printf is displayed to alert the user.
*/
int mutex_lock (Mutex mutex, PCB pcb) {
if (mutex) {
if (mutex->isLocked || mutex->hasLock == pcb) {
if(mutex->isLocked && mutex->hasLock == pcb)
{
printf("\r\n\r\n\t\tMUTEX IS ALREADY LOCKED!!!!!!!!!!\r\n\r\n");
}
return 0;
} else {
mutex->isLocked = 1;
mutex->hasLock = pcb;
return 1;
}
} else {
printf("\r\n\r\n\t\tMUTEX IS NULL. LOCK FAILED\r\n\r\n");
return 0;
}
}
/*
Attempts to lock the given mutex with the given PCB. If the lock has already
been taken, it will return false. Otherwise it will lock the mutex and return
true.
*/
int mutex_trylock (Mutex mutex, PCB pcb) {
int wasLocked = 0;
if (mutex) {
if (!mutex->isLocked) {
mutex->isLocked = 1;
wasLocked = 1;
mutex->hasLock = pcb;
}
} else {
printf("\r\n\r\n\t\tMUTEX IS NULL. TRYLOCK FAILED\r\n\r\n");
}
return wasLocked;
}
/*
Unlocks the given mutex. Sets the hasLocked PCB value back to NULL.
If the mutex is already unlocked a big printf is displayed to alert the user.
*/
int mutex_unlock (Mutex mutex, PCB pcb) {
if (mutex) {
if (!mutex->isLocked) {
printf("\r\n\r\n\t\tMUTEX IS ALREADY UNLOCKED\r\n\r\n");
return 0;
} else if (mutex->isLocked && mutex->hasLock == pcb) {
mutex->isLocked = 0;
mutex->hasLock = NULL;
return 1;
} else {
printf("\r\n\r\n\t\tMUTEX IS OWNED BY OTHER PROCESS\r\n\r\n");
return 2;
}
} else {
printf("\r\n\r\n\t\tMUTEX IS NULL. UNLOCK FAILED\r\n\r\n");
return 0;
}
}
/*
Prints the contents of the mutex.
*/
void toStringMutex (Mutex mutex) {
printf ("Mutex:\r\n");
printf("mid: %d, isLocked: %d\r\n", mutex->mid, mutex->isLocked);
printf("pcb1: ");
toStringPCB(mutex->pcb1, 0);
printf("lock pc: %d, unlock pc: %d\r\n\r\n", mutex->pcb1->lock_pc, mutex->pcb1->unlock_pc);
printf("pcb2: ");
toStringPCB(mutex->pcb2, 0);
printf("lock pc: %d, unlock pc: %d\r\n\r\n", mutex->pcb2->lock_pc, mutex->pcb2->unlock_pc);
}
/*
Destroys the given mutex.
*/
void mutex_destroy(Mutex mutex) {
if (mutex != NULL) {
if (mutex && mutex->condVar) {
cond_var_destroy(mutex->condVar);
}
free (mutex);
mutex = NULL;
} else {
printf("mutex was null\n");
}
}
/*
Creates the condition variable.
*/
ConditionVariable cond_var_create () {
ConditionVariable condVar = (ConditionVariable) malloc (sizeof(struct COND_VAR));
return condVar;
}
/*
Initializes the signal of a Condition Variable.
*/
void cond_var_init (ConditionVariable condVar) {
condVar->signal = 0;
}
/*
Displays the status of a Condition Variable's signal.
*/
void toStringConditionVariable (ConditionVariable condVar) {
printf("signal: %d\r\n", condVar->signal);
}
/*
Destroys the given Condition Variable
*/
void cond_var_destroy (ConditionVariable condVar) {
free(condVar);
}
/*
The Condition Variable is set to send a signal.
*/
void cond_var_signal (ConditionVariable condVar) {
condVar->signal = 1;
}
/*
The Condition Variable is set to wait.
*/
int cond_var_wait (ConditionVariable condVar) {
return condVar->signal;
}