· 8 years ago · Dec 17, 2017, 04:16 PM
1
2//Including system libraries
3#include <stdio.h>
4#include <stdlib.h>
5#include <stdbool.h>
6#include <time.h>
7#include <termios.h>
8#include <unistd.h>
9#include <fcntl.h>
10
11//Including user libraries
12#include "constants.h"
13#include "output.h"
14#include "master.h"
15#include "synchronizer.h"
16#include "worker.h"
17//Custom structure
18// Type defs
19
20
21//Global variables
22int table_of_pixels[SIZE_X][SIZE_Y]; //Will store the states of the pixels
23int temporary_table[SIZE_X][SIZE_Y]; //Will be used to store state n+1
24pid_t parent_pid;
25
26//Returns 1 if the user pressed a key and 0 otherwise
27int kbhit(void);
28
29// copies positions from user input (+ color) into shared memory
30void copy_pos(pos *input_pos, pos *shared_mem_pos, int nb_squares);
31
32//TODO: add in check validity if the square gets out of screen boundaries
33
34static bool checkValidity(int x, int y, pos *pos_table, int maxCurrentIte)
35{
36 for(int i = 0; i < maxCurrentIte; i++)
37 if((pos_table[i].x == x && pos_table[i].y == y)
38 || (hasIntersec(pos_table[i].x, pos_table[i].y, x, y)))
39
40 return false;
41
42 return true;
43}
44
45static void print_positions(pos* posTable, int nb_squares)
46{
47 for(int i = 0; i < nb_squares; ++i)
48 printf("Index : %d - positions (x = %d ; y = %d) \n", i, posTable[i].x, posTable[i].y);
49}
50
51void sigquit_handler (int sig);
52
53void sigquit_handler (int sig) {
54 if (sig == SIGQUIT) {
55 pid_t pid = getpid();
56 if (pid != parent_pid) _exit(0);
57 }
58}
59
60static void remove_shm(int shmid)
61{
62 shmctl(shmid, IPC_RMID, 0);
63 printf("Shared memory segment marked for deletion\n");
64}
65
66static void clean(Sync_ptr s, Sync_ptr s2, pos *p, velocities* v, int shmid, int pid) {
67 kill(0, SIGQUIT);
68
69 remove_shm(shmid);
70 free(v);
71 v=NULL;
72 free(p);
73 clean_sync(s);
74 clean_sync(s2);
75}
76 /***** Main function *****/
77// Should handle ./main nb_square(int) random/manual (if manual) x1 y1 v1_x v1_y x2 y2 v2_x v2_y and so on , all attached
78int main(int argc, char** argv) {
79 signal(SIGQUIT, sigquit_handler);
80 parent_pid = getpid();
81
82 int i, j, k, posX, posY;
83 int nb_square = 0;
84 bool random = false;
85 pos *input_pos_table = NULL; // what the user or the random generates
86 pos *pos_table = NULL; // what will be in the shared memory and manipulated by processes
87 velocities *velocities_table = NULL; // contains velocities for each square
88 // Isn't 'in the shared memory as asked by the teacher
89
90// No defensive programmation for the command line expressions
91 switch(argc)
92 {
93 case 1: perror("Number of squares missing \n"); exit(1);
94 case 2: perror("Missing the key word random or manual"); exit(1);
95 default:
96 nb_square = atoi(argv[1]);
97 input_pos_table = malloc(nb_square*sizeof(pos)); //To store position of squares
98 velocities_table = malloc(nb_square*sizeof(velocities)); // To store velocities of square
99 if(strcmp(argv[2], "random") == 0) // user asks for random generation
100 {
101 random = true;
102 srand(time(NULL));
103 break;
104 }
105 else
106 {
107 for(int i = 0; i < nb_square; i++) // manual - get 4 numbers for each square (nb_square loops)
108 {
109 input_pos_table[i].x = atoi(argv[3 + (i*4)]);// get the x pos
110 input_pos_table[i].y = atoi(argv[3 + (i*4) + 1]); // get the y pos
111 input_pos_table[i].color = i+1;
112 if(checkValidity(input_pos_table[i].x, input_pos_table[i].y, input_pos_table, i) == false) // check if it doesn't intersect previously inserted squares
113 {
114 perror("You can't put squares that intersect each other \n");
115 exit(1);
116 }
117 velocities_table[i].v_x = atoi(argv[3 + (i*4) + 2]); // get v_x
118 velocities_table[i].v_y = atoi(argv[3 + (i*4) + 3]); // get v_y
119 if(velocities_table[i].v_x < -1 || velocities_table[i].v_x > 1 || velocities_table[i].v_y < -1 || velocities_table[i].v_y > 1) // check if not out of range [-1,1]
120 {
121 perror("You can't have a velocity outside the range [-1,1] \n");
122 exit(1);
123 }
124 }
125 }
126 }// end switch
127
128 printf("Nb Squares = %d \n", nb_square); // DEBUG:
129
130
131 if(random == true) // if the users asked for random positions
132 {
133 for(int s = 0; s < nb_square; ++s)
134 {
135 do
136 {
137 posX = rand() % (SIZE_X-SQUARE_WIDTH); // randomize between screen boudaries
138 posY = rand() % (SIZE_Y-SQUARE_WIDTH);
139 }
140 while(!checkValidity(posX, posY, input_pos_table, s));
141
142 input_pos_table[s].x = posX;
143 input_pos_table[s].y = posY;
144 input_pos_table[s].color = s+1;
145 velocities_table[s].v_x = (rand() % 3) -1; // randomize velocities between [-1, 1]
146 velocities_table[s].v_y = (rand() % 3) -1;
147 }
148 }
149 //Filling the table with zeroes
150 for(i = 0; i < SIZE_X; ++i)
151 {
152 for(j = 0; j < SIZE_Y; ++j)
153 {
154 table_of_pixels[i][j] = 0;
155 temporary_table[i][j] = 0;
156 }
157 }
158
159 for(int k = 0; k < nb_square; ++k) // DEBUG
160 {
161 printf("Index %d, pos: x = %d , y = %d \n", k, input_pos_table[k].x , input_pos_table[k].y);
162 printf("Index %d, v_x = %d , v_y = %d \n", k, velocities_table[k].v_x , velocities_table[k].v_y);
163 }
164
165 for(i = 0; i < nb_square; i++)
166 {
167 for(j = 0; j < SQUARE_WIDTH; j++)
168 {
169 for(k = 0; k < SQUARE_WIDTH; k++)
170 {
171 table_of_pixels[input_pos_table[i].x+j][input_pos_table[i].y+k] = input_pos_table[i].color;
172 }
173 }
174 }
175
176 //Initializes SDL and the colours
177 init_output();
178 update_output(table_of_pixels);
179 printf("initialized\n");
180
181 sleep(5);
182 /* PUT THE PROCESS MAKING IN MAIN SO THAT THE MAIN CAN KILL PROCESSES , THE MASTER INCLUDED */
183
184 /* Variables */
185
186 pid_t pid;
187 key_t key_mem;
188 int shmid;
189
190 /* INIT VARIABLES FOR SHARED MEMORY */
191
192 key_mem = ftok(".", 'm');
193
194 /* Open the shared memory segment - create if necessary */
195 if((shmid = shmget(key_mem, sizeof(pos) * nb_square, IPC_CREAT|IPC_EXCL|0666)) == -1)
196 {
197 printf("Shared memory segment exists - opening as client\n");
198
199 /* Segment probably already exists - try as a client */
200 if((shmid = shmget(key_mem, sizeof(pos) * nb_square, 0)) == -1)
201 {
202 perror("shmget");
203 exit(1);
204 }
205 }
206 else
207 {
208 printf("Creating new shared memory segment\n");
209 }
210
211 /* Attach (map) the shared memory segment into the current process */
212 if((pos_table = (pos *)shmat(shmid, 0, 0)) == (pos *)-1)
213 {
214 perror("shmat");
215 exit(1);
216 }
217
218 // Put user or random squares position(x,y) in shared memory block
219 copy_pos(input_pos_table, pos_table, nb_square);
220
221 // Print the positions
222 print_positions(pos_table, nb_square);
223
224 /* Makes processes */
225
226 Sync_ptr s = NULL;
227 Sync_ptr s2 = NULL;
228 s = sync_init(s, nb_square);
229 s2 = sync_init(s2, nb_square);
230
231
232 int id = 0;
233 for (int i = 0; i <= nb_square; i++) { // (nb_square -1) workers + 1 master = nb_square loops
234 pid = fork();
235
236 if(pid < 0)
237 {
238 perror("Process creation failed");
239 exit(1);
240 }
241 if(pid == 0)
242 {
243 //This is a son
244 if(i < nb_square) //(nb_square -1 ) workers
245 worker(id, pos_table, s, s2, velocities_table[id].v_x, velocities_table[id].v_y, nb_square); //TODO complete
246 else
247 {
248 master_begin(nb_square, pos_table, table_of_pixels, velocities_table, s, s2); // last process created is the master
249 i = nb_square;
250 }
251 }
252 else
253 {
254 //This is the father
255 id++;
256 }
257 }
258
259 sleep(5); // put a sleep because the keyboard thing isn't working
260 printf("make cleaning\n");
261
262 clean(s, s2, input_pos_table, velocities_table, shmid, pid);
263 printf("Killing them ALL: (pid:%d) \n", pid);
264
265 printf("Child killed \n");
266 printf("Parent killed ? \n");
267
268 //Get the user to press a key at the end of the iterations
269 printf("Caio \n");
270
271 kill(0, SIGKILL);
272 return 1;
273}
274
275
276//Returns 1 if the user pressed a key, and 0 otherwise
277int kbhit(void)
278{
279 struct termios oldt, newt;
280 int ch;
281 int oldf;
282
283 //Changing the flags to make getchar() a non blocking operation
284 tcgetattr(STDIN_FILENO, &oldt);
285 newt = oldt;
286 newt.c_lflag &= ~(ICANON | ECHO);
287 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
288 oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
289 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
290
291 //Try to read of character (non-blocking)
292 ch = getchar();
293
294 //Resetting the flags to their old values
295 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
296 fcntl(STDIN_FILENO, F_SETFL, oldf);
297
298 //If we did manage to read something
299 if(ch != EOF)
300 {
301 //Put back the character on the input stream
302 ungetc(ch, stdin);
303 return 1;
304 }
305
306 return 0;
307}
308
309void copy_pos(pos *input_pos, pos *shared_mem_pos, int nb_squares)
310{
311 for(int i = 0; i < nb_squares; ++i)
312 {
313 shared_mem_pos[i].x = input_pos[i].x;
314 shared_mem_pos[i].y = input_pos[i].y;
315 shared_mem_pos[i].color = input_pos[i].color;
316 }
317}