fuck non-posix semaphores
anyways, finished my latest assignment.
Took A LOT OF work to solve and there might be a rare deadlock still in there.
p3.c - main program
Code
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/ipc.h>
4 #include <sys/shm.h>
5 #include <sys/types.h>
6 #include <sys/sem.h>
7 #include <unistd.h>
8 #include <signal.h>
9 #include <wait.h>
10 #include <math.h>
11 #include "helpers.h"
12
13 int main (int argc, char *argv[]) {
14
15 int opt, tmp, size, i, m, total, status, pid, times;
16
17 int *matrix;
18
19 const int SEMFLG = IPC_CREAT | IPC_EXCL | 0666;
20
21 times = opt = tmp = size = i = m = 0;
22
23 //setup our info struct in shared memory
24
25 infoID = shmget(IPC_PRIVATE, sizeof(info), IPC_CREAT | IPC_EXCL | 0777);
26 if (infoID == -1) {
27 perror(argv[0]);
28 exit(1);
29 }
30
31 inf = (info *)shmat(infoID, 0, 0);
32
33 inf->points = 5;
34 inf->time = 5;
35
36 while ((opt = getopt (argc, argv, "hp:t:")) != -1) {
37 switch(opt) {
38 case 'h':
39 printf("Proper usage: p3 [-t:] [-p:] \n");
40 printf("Please check the README file for more specific details.\n");
41 exit(0);
42 case 'p':
43 inf->points = atoi(optarg);
44 break;
45 case 't':
46 inf->time = atoi(optarg);
47 break;
48 default:
49 break;
50 }
51 }
52
53 //setup our signal handler for SIGINT
54
55 signal(SIGINT, handler);
56
57 //set up some constants in the parent
58
59 inf->h = 1.0 / (double)inf->points;
60
61 inf->r = 0.45;
62
63 //initialize some shared struct values
64
65 inf->rows = inf->time + 1;
66 inf->cols = inf->points + 1;
67
68 size = inf->rows * inf->cols;
69
70 //setup the shared matrix
71
72 inf->matrixID = shmget(IPC_PRIVATE, size*sizeof(int), IPC_CREAT | IPC_EXCL | 0777);
73
74 matrix = (int *)shmat(inf->matrixID, 0, 0);
75
76 //initialize the shared matrix
77
78 matrixSetUp(size);
79
80 inf->nsem = inf->points - 1;
81
82 cpids = (int *)malloc(inf->nsem * sizeof(int));
83
84 //Set up the two semaphores
85
86 semopInit(SEMFLG);
87
88 //Clean out log file for use, or create if it doesn't exist
89
90 FILE *f = fopen("Log", "w");
91 fclose(f);
92
93 //Spawn our children and send them to the solution function
94
95 for (i = 1; i < inf->points; i++) {
96 total++;
97 cpids[i-1] = fork();
98 if (cpids[i-1] == 0) {
99 childProcess(i);
100 }
101 }
102
103 //Parent quietly awaits their demise
104
105 while (total > 0) {
106 pid = wait(&status);
107 total--;
108 }
109
110 //Print out the resultant matrix
111
112 printMatrix(size);
113
114 //Clean up any allocated resources (shared memory, semaphores, mallocs etc)
115
116 cleanup();
117
118 return 0;
119 }
helpers.c - help functions (finally put them in a sep. file)
Code
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/ipc.h>
4 #include <sys/shm.h>
5 #include <sys/sem.h>
6 #include <unistd.h>
7 #include <math.h>
8 #include <time.h>
9 #include "helpers.h"
10
11 //Function to handle interrupt signals in case of hangups
12
13 void handler(int sig) {
14 printf("Signal %d received: terminating p3...\n", sig);
15
16 cleanup();
17 exit(0);
18 }
19
20 //Function to clean up various memory segments
21
22 void cleanup() {
23
24 free(cpids);
25 free(semWait);
26 free(semSignal);
27 free(semZero);
28
29 shmctl(inf->matrixID, IPC_RMID, 0);
30
31 semctl(inf->mutex, 0, IPC_RMID, arg);
32
33 semctl(inf->semSet, 0, IPC_RMID, arg);
34
35 shmdt( (void *) inf);
36 shmctl(infoID, IPC_RMID, 0);
37 }
38
39 //Function to initialize the bottom row of our finite difference matrix
40
41 void matrixSetUp(int size) {
42 int i;
43
44 info *inf = (info *)shmat(infoID, 0, 0);
45
46 int *matrix = (int *)shmat(inf->matrixID,0,0);
47
48 for (i = 0; i < size; i++) {
49 matrix[i] = 0;
50 }
51
52 for (i = 0; i < inf->cols; i++) {
53 matrix[((inf->rows -1) * inf->cols) + i] = (int)(100.0 * sin(M_PI * ((double)i * inf->h)));
54 }
55 }
56
57 //Function to initialize semaphore stuff
58
59 void semopInit(int SEMFLG) {
60
61 ushort *array;
62 int i;
63
64 info *inf = (info *)shmat(infoID, 0,0);
65
66 if ((inf->mutex = semget(IPC_PRIVATE, 1, SEMFLG)) == -1) {
67 perror("p3");
68 cleanup();
69 exit(1);
70 }
71
72 if ((inf->semSet = semget(IPC_PRIVATE, inf->nsem, SEMFLG)) == -1) {
73 perror("p3");
74 cleanup();
75 exit(1);
76 }
77
78 semWait = (struct sembuf *)malloc(inf->nsem * sizeof(struct sembuf));
79 semSignal = (struct sembuf *)malloc(inf->nsem * sizeof(struct sembuf));
80 semZero = (struct sembuf *)malloc(inf->nsem * sizeof(struct sembuf));
81
82 for (i = 0; i < inf->nsem; i++) {
83
84 semWait[i].sem_num = i;
85 semWait[i].sem_op = -1;
86 semWait[i].sem_flg = 0;
87
88 semSignal[i].sem_num = i;
89 semSignal[i].sem_op = 1;
90 semSignal[i].sem_flg = 0;
91
92 semZero[i].sem_num = i;
93 semZero[i].sem_op = 0;
94 semZero[i].sem_flg = 0;
95 }
96
97 arg.val = 1;
98 semctl(inf->mutex, 0, SETVAL, arg);
99
100 array=(ushort *)malloc(inf->nsem * sizeof(ushort));
101
102 for (i = 0; i < inf->nsem; i++) {
103 if (i == 0 || i == inf->nsem - 1) {
104 array[i] = 1;
105 }
106 else {
107 array[i] = 2;
108 }
109 }
110
111 arg.array = array;
112
113 semctl(inf->semSet, 0, SETALL, arg);
114 }
115
116 //Function to print out the matrix
117
118 void printMatrix(int size) {
119 int i;
120
121 info *inf = (info *)shmat(infoID, 0, 0);
122
123 int *matrix = (int *)shmat(inf->matrixID, 0, 0);
124
125 printf("\n");
126
127 for (i = 0; i < size; i++) {
128 if (i % inf->cols == 0 && i != 0) {
129 printf("\n");
130 }
131 printf("%-5d", matrix[i]);
132 }
133
134 printf("\n\n");
135 }
136
137 //Function for each child to work in
138
139 void childProcess(int id) {
140
141 double sum, leftGuy, me, rightGuy;
142 int i;
143 union semunm arg;
144 time_t currentTime;
145
146 FILE *f;
147
148 info *inf = (info *)shmat(infoID, 0, 0);
149
150 int *matrix = (int *)shmat(inf->matrixID, 0, 0);
151
152 srand(time(NULL) + 100 * id);
153
154 /*
155 Main loop: Each process
156 resets their semval, while
157 also sending signals to their
158 neighbors. Then, each process
159 waits for their own signal to
160 become 0 before proceeding with
161 calculation.
162 */
163
164 for (i = 1; i < inf->rows; i++) {
165
166 if (id == 1) {
167 arg.val = 1;
168 semctl(inf->semSet, id-1, SETVAL, arg);
169 semop(inf->semSet, &semWait[1], 1);
170 semop(inf->semSet, &semZero[id-1], 1);
171 } else if (id == inf->nsem) {
172 arg.val = 1;
173 semctl(inf->semSet, id-1, SETVAL, arg);
174 semop(inf->semSet, &semWait[id-2], 1);
175 semop(inf->semSet, &semZero[id-1], 1);
176 } else {
177 arg.val = 2;
178 semctl(inf->semSet, id-1, SETVAL, arg);
179 semop(inf->semSet, &semWait[id-2], 1);
180 semop(inf->semSet, &semWait[id], 1);
181 semop(inf->semSet, &semZero[id-1], 1);
182 }
183
184 leftGuy = inf->r * (double)matrix[(inf->rows - i) * inf->cols + id - 1];
185 me = (1.0 - (2.0 * inf->r)) * (double)matrix[(inf->rows - i) * inf->cols + id];
186 rightGuy = inf->r * (double)matrix[(inf->rows - i) * inf->cols + id + 1];
187 sum = leftGuy + me + rightGuy;
188 matrix[(inf->rows - i - 1) * inf->cols + id] = (int)sum;
189
190 //attempt to enter critical section
191 time(¤tTime);
192 semop(inf->mutex, &semWait[0], 1);
193
194 f = fopen("Log", "a+");
195 fprintf(f, "Child %d has gained the mutex semaphore!\n", (int)getpid());
196 fprintf(f, "Child %d began to wait for mutex at %s\n", (int)getpid(), ctime(¤tTime));
197 sleep(rand() % 3);
198
199 //Signal back the mutex after done
200 semop(inf->mutex, &semSignal[0], 1);
201
202 }
203
204 //one last signal after they exit the loop
205
206 printf("Child %d done: his neighbors are:\n", (int)getpid());
207 if (id == 1) {
208 printf("right neighbor: %d\n", semctl(inf->semSet, 1, GETVAL));
209 } else if (id == inf->nsem) {
210 printf("left neighbor: %d\n", semctl(inf->semSet, id-2, GETVAL));
211 } else {
212 printf("left neighbor: %d\n", semctl(inf->semSet, id-2, GETVAL));
213 printf("right neighbor: %d\n", semctl(inf->semSet, id, GETVAL));
214 }
215
216 if (id == 1 && semctl(inf->semSet, 1, GETVAL) >= 1) {
217 semop(inf->semSet, &semWait[1], 1);
218 } else if (id == inf->nsem && semctl(inf->semSet, id-2, GETVAL) >= 1) {
219 semop(inf->semSet, &semWait[id-2], 1);
220 } else {
221 if (semctl(inf->semSet, id-2, GETVAL) >= 1) {
222 semop(inf->semSet, &semWait[id-2], 1);
223 }
224 if (semctl(inf->semSet, id, GETVAL) >= 1) {
225 semop(inf->semSet, &semWait[id], 1);
226 }
227 }
228
229 exit(0);
230 }
my .h:
Code
1 typedef struct info {
2 int matrixID;
3 int semID;
4 int semID_two;
5 int semSet;
6 int mutex;
7 int nsem;
8 int time;
9 int points;
10 int cols;
11 int rows;
12 double h;
13 double r;
14 } info;
15
16 union semunm {
17 int val;
18 struct semid_ds *buf;
19 ushort *array;
20 struct seminfo *__buf;
21 } arg;
22
23 struct sembuf *semWait;
24 struct sembuf *semSignal;
25 struct sembuf *semZero;
26
27 info *inf;
28 int *cpids;
29
30 int infoID;
31
32 void handler(int sig);
33
34 void cleanup();
35
36 void matrixSetUp(int size);
37
38 void semopInit(int SEMFLG);
39
40 void printMatrix(int size);
41
42 void childProcess(int id);