-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproducer.c
278 lines (223 loc) · 6.85 KB
/
producer.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
/*
CSC139
Spring 2023
First Assignment
Varia, Himanshukumar
Section #1
OSs Tested on: such as Linux(putty).
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
// Size of shared memory block
// Pass this to ftruncate and mmap
#define SHM_SIZE 4096
// Global pointer to the shared memory block
// This should receive the return value of mmap
// Don't change this pointer in any function
void* gShmPtr;
// You won't necessarily need all the functions below
void Producer(int, int, int);
void InitShm(int, int);
void SetBufSize(int);
void SetItemCnt(int);
void SetIn(int);
void SetOut(int);
void SetHeaderVal(int, int);
int GetBufSize();
int GetItemCnt();
int GetIn();
int GetOut();
int GetHeaderVal(int);
void WriteAtBufIndex(int, int);
int ReadAtBufIndex(int);
int GetRand(int, int);
int main(int argc, char* argv[])
{
pid_t pid;
int bufSize; // Bounded buffer size
int itemCnt; // Number of items to be produced
int randSeed; // Seed for the random number generator
if(argc != 4){
printf("Invalid number of command-line arguments\n");
exit(1);
}
bufSize = atoi(argv[1]);
itemCnt = atoi(argv[2]);
randSeed = atoi(argv[3]);
// Write code to check the validity of the command-line arguments
if(bufSize > 512) {
printf("Buffer too large.\n");
exit(1);
}
else if(bufSize < 2) {
printf("Buffer too small.\n");
exit(1);
}
// Function that creates a shared memory segment and initializes its header
InitShm(bufSize, itemCnt);
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) { /* child process */
printf("Launching Consumer \n");
execlp("./consumer","consumer",NULL);
}
else { /* parent process */
/* parent will wait for the child to complete */
printf("Starting Producer\n");
// The function that actually implements the production
Producer(bufSize, itemCnt, randSeed);
printf("Producer done and waiting for consumer\n");
wait(NULL);
printf("Consumer Completed\n");
}
return 0;
}
void InitShm(int bufSize, int itemCnt)
{
int in = 0;
int out = 0;
const char *name = "OS_HW1_HimanshukumarVaria"; // Name of shared memory object to be passed to shm_open
int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); // Shared memory.
if(shm_fd < 0) {
printf("Error: Problem initilizing shared memory object.\n");
exit(1);
}
// Truncate memory to 4k, and make sure that's successful.
if(ftruncate(shm_fd, SHM_SIZE) < 0) { // Truncate memory object to 4k.
printf("Error: Failed to truncate memory object.\n");
exit(1);
}
gShmPtr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if(gShmPtr < 0 ) {
printf("Error: Failed to map virtual address space.\n");
exit(1);
}
// Write code here to set the values of the four integers in the header
// Just call the functions provided below, like this
// Write code here to set the values of the four integers in the header
SetIn(in);
SetOut(out);
SetBufSize(bufSize);
SetItemCnt(itemCnt);
}
void Producer(int bufSize, int itemCnt, int randSeed)
{
int in = 0;
int out = 0;
int val = 0;
srand(randSeed);
int i = 0; // Counter for while loop.
// Loop until all items in count have been created.
while(i < itemCnt) {
// If the buffer is not full.
while(((in+1) % bufSize) == out){
//Wait for a short period of time
usleep(1000);
}
val = GetRand(10, 2500); // Random integer between 10 and 2500
WriteAtBufIndex(in, val); // Write the given val at the given index in the bounded buffer
printf("Producing Item %d with value %d at Index %d\n", i, val, in); // Print out what's happening
in = (in + 1) % bufSize; // increase local variable in, mod with the buffer size.
SetIn(in); // Set header for in.
i++; // Increase loop counter.
}
// Write code here to produce itemCnt integer values in the range [10-2500]
// Use the functions provided below to get/set the values of shared variables "in" and "out"
// Use the provided function WriteAtBufIndex() to write into the bounded buffer
// Use the provided function GetRand() to generate a random number in the specified range
// **Extremely Important: Remember to set the value of any shared variable you change locally
// Use the following print statement to report the production of an item:
// printf("Producing Item %d with value %d at Index %d\n", i, val, in);
// where i is the item number, val is the item value, in is its index in the bounded buffer
printf("Producer Completed\n");
}
// Set the value of shared variable "bufSize"
void SetBufSize(int val)
{
SetHeaderVal(0, val);
}
// Set the value of shared variable "itemCnt"
void SetItemCnt(int val)
{
SetHeaderVal(1, val);
}
// Set the value of shared variable "in"
void SetIn(int val)
{
SetHeaderVal(2, val);
}
// Set the value of shared variable "out"
void SetOut(int val)
{
SetHeaderVal(3, val);
}
// Get the ith value in the header
int GetHeaderVal(int i)
{
int val;
void* ptr = gShmPtr + i*sizeof(int);
memcpy(&val, ptr, sizeof(int));
return val;
}
// Set the ith value in the header
void SetHeaderVal(int i, int val)
{
// Write the implementation
void* ptr = gShmPtr + i*sizeof(int);
memcpy(ptr, &val, sizeof(int));
}
// Get the value of shared variable "bufSize"
int GetBufSize()
{
return GetHeaderVal(0);
}
// Get the value of shared variable "itemCnt"
int GetItemCnt()
{
return GetHeaderVal(1);
}
// Get the value of shared variable "in"
int GetIn()
{
return GetHeaderVal(2);
}
// Get the value of shared variable "out"
int GetOut()
{
return GetHeaderVal(3);
}
// Write the given val at the given index in the bounded buffer
void WriteAtBufIndex(int indx, int val)
{
// Skip the four-integer header and go to the given index
void* ptr = gShmPtr + 4*sizeof(int) + indx*sizeof(int);
memcpy(ptr, &val, sizeof(int));
}
// Read the val at the given index in the bounded buffer
int ReadAtBufIndex(int indx)
{
// Write the implementation
int val;
// Skip the four-integer header and go to the given index
void* ptr = gShmPtr + 4*sizeof(int) + indx*sizeof(int);
memcpy(&val, ptr, sizeof(int));
return val;
}
// Get a random number in the range [x, y]
int GetRand(int x, int y)
{
int r = rand();
r = x + r % (y-x+1);
return r;
}