-
Notifications
You must be signed in to change notification settings - Fork 0
/
hospital.c
348 lines (295 loc) · 10.2 KB
/
hospital.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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/*------------------------------------------------------------------
* CME3205 - Operating Systems Assignment 1
* Hospital Simulation Using Semaphores and Mutexes
*
*------------------------------------------------------------------
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdint.h>
#define NUM_DISEASES 10 //ten diseases
// Global Variables declaration
int REGISTRATION_SIZE = 10;
int RESTROOM_SIZE = 10;
int CAFE_NUMBER = 10;
int GP_NUMBER = 10;
int PHARMACY_NUMBER = 10;
int BLOOD_LAB_NUMBER = 10;
//NUMBER OF OR, SURGOENS AND NURSES AVAILABLE
int OR_NUMBER = 10;
int SURGEON_NUMBER = 30;
int NURSE_NUMBER = 30;
//NUMBER OF SURGEONS AND NURSES REQUIRED FOR AN OPERATION
int SURGEON_LIMIT = 5;
int NURSE_LIMIT = 5;
//WAITING TIME REQUIRED FOR ACTIONS(IN MILLISECONDS)
int WAIT_TIME = 100;
int REGISTRATION_TIME = 100;
int GP_TIME = 200;
int PHARMACY_TIME = 100;
int BLOOD_LAB_TIME = 200;
int SURGERY_TIME = 500;
int CAFE_TIME = 100;
int RESTROOM_TIME = 100;
//COSTS
int REGISTRATION_COST = 100; //fixed
int BLOOD_LAB_COST = 200; //fixed
int PHARMACY_COST = 200; //randomly generated
int SURGERY_OR_COST = 200; //fixed
int SURGERY_SERGEON_COST = 100; //fixed
int SURGERY_NURSE_COST = 50; //fixed
int CAFE_COST = 200; //randomly generated
//INCREASE RATES
int HUNGER_INCREASE_RATE = 10;
int RESTROOM_INCREASE_RATE = 10;
//NUMBER OF PATIENTS REQUIRING MEDICAL ATTENTION AND HOSPITAL WALLET
int PATIENT_NUMBER = 1000;
int HOSPITAL_WALLET = 0;
//PATIENT STRUCT
typedef struct Persons
{
int patientID;
pthread_t thread_id;
int disease;
int bill;
int getSurgery; //1 if yes, 0 if no
int getMedicine; //1 if yes, 0 if no
int getBloodTest; //1 if yes, 0 if no
int Hunger_Meter;
int Restroom_Meter;
} Patient;
sem_t semREGISTRATION, semGP, semBLOODLAB, semPHARMACY, semOR, semCAFE, semRESTROOM, semMUTEX;
char *Diseases[NUM_DISEASES] = {"Heart", "Lung", "Brain", "Eye", "Skin",
"Ear", "Bone", "Throat", "Kidney", "Liver"};
//FUNCTION PROTOTYPES
void *m_pateint();
void m_registration(Patient *);
void m_gp(Patient *);
void m_bloodlab(Patient *);
void m_pharmacy(Patient *);
void m_or(Patient *);
void raiseHungerRestroomMeter(Patient *);
void m_cafe(Patient *);
void m_restroom(Patient *);
void m_hunger_checker(Patient *);
void m_wait(Patient *);
void *m_pateint(void *p)
{
Patient *patient = (Patient *)p; //generate a patient
//assign disease to patient
patient->disease = rand() % 10;
//necessary general waiting before registration action
m_wait(patient);
//enter registration method
sem_wait(&semREGISTRATION);
m_registration(patient); //
sem_post(&semREGISTRATION);
//necessary general waiting before gp action
m_wait(patient);
//enter GP method
sem_wait(&semGP);
m_gp(patient);
sem_post(&semGP);
//necessary general waiting before bloodTest action
m_wait(patient);
//if patient needs bloodtest, enter bloodlab method
if (patient->getBloodTest)
{
sem_wait(&semBLOODLAB);
m_bloodlab(patient); // blood work needed, go to blood lab
sem_post(&semBLOODLAB);
}
//necessary general waiting before pharmacy action
m_wait(patient);
//if patient needs bloodtest, enter pharmacy method
if (patient->getMedicine)
{
sem_wait(&semPHARMACY);
m_pharmacy(patient); // drug needed, go to pharmacy
sem_post(&semPHARMACY);
}
//necessary general waiting before OR action
m_wait(patient);
//if patient needs surgery, enter OR method
if (patient->getSurgery)
{
sem_wait(&semOR);
m_or(patient); /* surgery needed, go to OR */
sem_post(&semOR);
}
printf("Hospital Wallet:%d\n", HOSPITAL_WALLET);
printf("Patient:%d's Bill:%d\n", patient->patientID, patient->bill);
/* ENTER critical region, keeping track of hospital bill */
sem_wait(&semMUTEX);
HOSPITAL_WALLET += patient->bill;
patient->bill = 0;
sem_post(&semMUTEX);
/* EXIT critical region, keeping track of hospital bill */
printf("Patient:%d pays bill. Updated Hospital Wallet:%d\n", patient->patientID, HOSPITAL_WALLET);
pthread_exit(NULL);
}
void m_registration(Patient *patient)
{
printf("Patient:%d registration.\n", patient->patientID);
patient->bill += REGISTRATION_COST;
sleep(REGISTRATION_TIME / 1000);
raiseHungerRestroomMeter(patient);
}
void m_gp(Patient *patient)
{
printf("---- GP examining Patient:%d ----> Diagnosis: %s\n", patient->patientID, Diseases[patient->disease]);
/* generate random number to choose a department, if 0 = pharmacy, 1 = blood or 3 = surgery */
int gotoDeptmnt;
gotoDeptmnt = rand() % 3; // gp sends patient to one of the 3 main departments
//waiting time for gp to finish examination
sleep(GP_TIME / 1000);
if (gotoDeptmnt == 0)
{
patient->getMedicine = 1;
printf("--------> GP sending Patient:%d to PHARMACY\n", patient->patientID);
}
else if (gotoDeptmnt == 1)
{
patient->getBloodTest = 1;
printf("--------> GP sending Patient:%d to BLOOD LAB\n", patient->patientID);
}
else
{
patient->getSurgery = 1;
printf("--------> GP sending Patient:%d to SURGERY\n", patient->patientID);
}
raiseHungerRestroomMeter(patient);
}
void m_bloodlab(Patient *patient)
{
printf("------------> Patient:%d arrived at Blood Lab Center.\n", patient->patientID);
patient->bill += BLOOD_LAB_COST;
sleep(BLOOD_LAB_TIME / 1000);
raiseHungerRestroomMeter(patient);
//necessary general waiting before gp action
m_wait(patient);
//send patient to GP after blood work for follow up
sem_wait(&semGP);
printf("--------> Patient:%d going back to GP for follow-up.\n", patient->patientID);
m_gp(patient);
sem_post(&semGP);
}
void m_pharmacy(Patient *patient)
{
printf("------------> Patient:%d arrived at Pharmacy\n", patient->patientID);
patient->bill += rand() % PHARMACY_COST;
sleep(PHARMACY_TIME / 1000);
raiseHungerRestroomMeter(patient);
}
void m_or(Patient *patient)
{
int Sselected = (rand() % (SURGEON_LIMIT + 1 - 1)) + 1; //surgeon limit between 1 and 5
int Nselected = (rand() % (NURSE_LIMIT + 1 - 1)) + 1; //surgeon limit between 1 and 5
if (Sselected <= SURGEON_NUMBER && Nselected <= NURSE_NUMBER && OR_NUMBER > 0)
{
//---------ENTER critical region, keeping available doctors, nurses and ORs
sem_wait(&semMUTEX);
SURGEON_NUMBER -= Sselected;
NURSE_NUMBER -= Nselected;
OR_NUMBER--;
sem_post(&semMUTEX);
//--------- EXIT critical region, keeping available doctors, nurses and ORs
printf("** ** Available: %d Surgeons | %d Nurses | %d ORs ** **\n------------ Patient:%d undergoing surgery. (%d Surgeons and %d nurses selected.\n",
SURGEON_NUMBER + Sselected, NURSE_NUMBER + Nselected, OR_NUMBER + 1, patient->patientID, Sselected, Nselected);
patient->bill += SURGERY_OR_COST + (SURGERY_SERGEON_COST * Sselected) + (SURGERY_NURSE_COST * Nselected);
sleep(SURGERY_TIME / 1000);
patient->getSurgery = 0;
printf("---------- <---- Surgery complete: Sending Patient:%d to GP for follow-up\n", patient->patientID);
/* ENTER critical region, keeping available doctors, nurses and ORs */
sem_wait(&semMUTEX);
SURGEON_NUMBER += Sselected;
NURSE_NUMBER += Nselected;
OR_NUMBER++;
sem_post(&semMUTEX);
/* EXIT critical region, keeping available doctors, nurses and ORs */
//necessary general waiting before GP action
m_wait(patient);
//send patient to GP after surgery
sem_wait(&semGP);
m_gp(patient);
sem_post(&semGP);
}
else
{
printf("Not enough personnel and ORs available");
}
}
void m_cafe(Patient *patient)
{
printf("Patient:%d is going to CAFETERIA.\n", patient->patientID);
patient->bill += rand() % CAFE_COST;
sleep(CAFE_TIME / 1000); //cafe wait time
}
void m_restroom(Patient *patient)
{
printf("Patient:%d is going to RESTROOM.\n", patient->patientID);
sleep(RESTROOM_TIME / 1000); //restroom waiting time
}
//raise hunger and rest
void raiseHungerRestroomMeter(Patient *patient)
{
patient->Hunger_Meter += (rand() % (HUNGER_INCREASE_RATE - 1 + 1)) + 1;
patient->Restroom_Meter += (rand() % (RESTROOM_INCREASE_RATE - 1 + 1)) + 1;
}
void m_hunger_checker(Patient *patient)
{
if (patient->Hunger_Meter >= 100)
{
sem_wait(&semCAFE);
m_cafe(patient); //hungry, so go to cafe
sem_post(&semCAFE);
patient->Hunger_Meter = 0;
}
if (patient->Restroom_Meter >= 100)
{
sem_wait(&semRESTROOM);
m_restroom(patient); //go to restroom
sem_post(&semRESTROOM);
patient->Restroom_Meter = 0;
}
}
//a function to perform general waiting time
void m_wait(Patient *patient)
{
sleep((rand() % WAIT_TIME) / 1000);
raiseHungerRestroomMeter(patient);
m_hunger_checker(patient);
}
int main(int argc, char *argv[])
{
srand(time(NULL)); //to generate random number to access disease array
/* Initializng all the semaphores */
sem_init(&semREGISTRATION, 0, REGISTRATION_SIZE);
sem_init(&semGP, 0, GP_NUMBER);
sem_init(&semBLOODLAB, 0, BLOOD_LAB_NUMBER);
sem_init(&semPHARMACY, 0, PHARMACY_NUMBER);
sem_init(&semOR, 0, OR_NUMBER);
sem_init(&semCAFE, 0, CAFE_NUMBER);
sem_init(&semRESTROOM, 0, RESTROOM_SIZE);
sem_init(&semMUTEX, 0, 1); //mutex
// Allocate memory for each patients private property
Patient *patients = (Patient *)calloc(PATIENT_NUMBER, sizeof(*patients));
//Create one thread for each patient
int i;
for (i = 0; i < PATIENT_NUMBER; i++)
{
patients[i].patientID = i + 1;
pthread_create(&patients[i].thread_id, NULL, &m_pateint, &patients[i]); //create thread for every patient
}
// join threads so that finished threads don't cause main to exit
for (i = 0; i < PATIENT_NUMBER; i++)
pthread_join(patients[i].thread_id, NULL);
// free allocated memory
free(patients);
return 0;
}