/[cvs]/joko/Uni/BSArch/04/bmp_fractal.c
ViewVC logotype

Contents of /joko/Uni/BSArch/04/bmp_fractal.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Sun Jul 2 01:51:26 2006 UTC (18 years, 2 months ago) by joko
Branch: MAIN
Changes since 1.9: +115 -25 lines
File MIME type: text/plain
finally works with processes as workers

1 /* Betriebssystem & Middleware
2 *
3 * Betriebssystemarchitektur SS 2006
4 *
5 * Uebung 4.4
6 */
7
8 // $Id: bmp_fractal.c,v 1.9 2006/07/02 00:24:17 joko Exp $
9
10 #include <windows.h>
11 #include <stdio.h>
12 #include <errno.h>
13
14 #define XSIZE 500
15 #define YSIZE 500
16 #include "algorithm.h"
17
18 #define MASTER -1
19
20 BOOL VERBOSE = TRUE;
21
22
23 /* BMP Header */
24 unsigned char header[54]={0x42,0x4d, // signature BM
25 0xe6,0x71,0x0b,0x0, // filesize 750054
26 0x0,0x0,0x0,0x0, // reserved
27 0x36,0x0,0x0,0x0, // image offset 54
28 0x28,0x0,0x0,0x0, // size of header follows 40
29 0xf4,0x1,0x0,0x0, // with of image 500
30 0xf4,0x1,0x0,0x0, // height of image 500
31 0x1,0x0, // number of planes 1
32 0x18,0x0, // number of pixel 24
33 0x0,0x0,0x0,0x0, // compression
34 0xb0,0x71,0x0b,0x0, // size of image 750000
35 0x0,0x0,0x0,0x0, // xres
36 0x0,0x0,0x0,0x0, // yres
37 0x0,0x0,0x0,0x0, // number of colortables
38 0x0,0x0,0x0,0x0 // number of important colors
39 };
40
41
42 void printErrorAndExit(const char *msg, DWORD err) {
43 LPSTR lpMsgBuf;
44 if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
45 FORMAT_MESSAGE_FROM_SYSTEM |
46 FORMAT_MESSAGE_IGNORE_INSERTS,
47 NULL,
48 err,
49 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
50 (LPTSTR) &lpMsgBuf,
51 0,
52 NULL ))
53 {
54 fprintf(stderr,"%s : %s\n",msg,lpMsgBuf);
55 LocalFree(lpMsgBuf);
56 }
57 else
58 {
59 fprintf(stderr,"Error at FormatMesage: %d\n",err=GetLastError());
60 }
61 exit(err);
62 }
63
64
65 void write_blank_file(char *filename) {
66
67 FILE *fd;
68 int len, i, img_size;
69
70 // open file handle
71 fd = fopen(filename, "wb+");
72 if (NULL == fd) {
73 perror("open");
74 exit(1);
75 }
76
77 // write bmp header to file
78 len = fwrite(header, 1, sizeof(header), fd);
79
80 // error checking
81 if (-1 == len || len != sizeof(header)) {
82 perror("write");
83 exit(2);
84 }
85
86 // write three null-bytes for each pixel to file to create a black picture
87 img_size = XSIZE * YSIZE;
88 for (i = 0; i < img_size; i++) {
89 len = fwrite("\0\0\0", 1, 3, fd);
90 if (-1 == len || len != 3) {
91 perror("write");
92 exit(4);
93 }
94 }
95
96 // close file handle
97 fclose(fd);
98 }
99
100
101 // arguments for each thread
102 typedef struct _WorkerArguments {
103 int start_row;
104 int number_of_rows;
105 unsigned char * pBitmap;
106 } WORKERARGS, *PWORKERARGS;
107
108 // worker thread - main entry function
109 DWORD WINAPI fractal_create_segment (LPVOID lpParam) {
110
111 // thread stuff
112 int thread_id;
113 PWORKERARGS args;
114 unsigned char *pDataBitmapSegment;
115
116 // fractal calculation
117 int x, y;
118 char bgr[3];
119
120 thread_id = GetCurrentThreadId();
121
122 // get worker arguments
123 args = (PWORKERARGS)lpParam;
124
125 // calculate pointer to beginning of segment
126 pDataBitmapSegment = (unsigned char *)((INT_PTR)args->pBitmap + (YSIZE - (args->start_row + args->number_of_rows)) * 3 * XSIZE);
127
128 // debugging
129 if (VERBOSE) {
130 printf("----------------------------------------------\n");
131 printf("thread_id: %i\n", thread_id);
132 printf("arg.start_row: %i\n", args->start_row);
133 printf("arg.number_of_rows: %i\n", args->number_of_rows);
134 printf("segment_start: %p\n", pDataBitmapSegment);
135 }
136
137 // calculate fractal
138 for (y = (args->start_row + args->number_of_rows) - 1; y >= args->start_row; y--) {
139 //printf("calc: thread=%i; y=%i limits: %i,%i p: %p\n", thread_id, y, args->start_row, args->number_of_rows, pDataBitmapSegment);
140 for (x = 0; x < XSIZE; x++) {
141 getColorValuesAt(x * (2.0 / XSIZE) - 1.5, y * (2.0 / YSIZE) - 1.0, &bgr[2], &bgr[1], &bgr[0]);
142
143 // transfer color values to current pixel
144 pDataBitmapSegment[0] = bgr[0];
145 pDataBitmapSegment[1] = bgr[1];
146 pDataBitmapSegment[2] = bgr[2];
147
148 // move pointer to next pixel
149 pDataBitmapSegment += 3;
150
151 }
152 //no padding required because 1500%4 =0 ???
153 }
154
155 if (VERBOSE)
156 printf("thread finished: %i\n", thread_id);
157 return 0;
158
159 }
160
161
162 int main(int argc, char *argv[]) {
163
164 // MMF support
165 DWORD err;
166 HANDLE hMap, hFile;
167 LPVOID pData;
168 unsigned char *pDataBitmap;
169
170 // workers
171 int workers = 5;
172 int worker_index, worker_rows, worker_startrow;
173 HANDLE *worker_handles;
174 PWORKERARGS worker_args;
175
176 // threads or processes?
177 BOOL use_processes = TRUE;
178 int worker_id = MASTER;
179
180 // information for creating processes
181 STARTUPINFO si;
182 PROCESS_INFORMATION pi;
183 char szCmdline[1024];
184
185
186 // "parse" command line arguments
187 if (argc >= 2) {
188 worker_id = atoi(argv[1]);
189 }
190
191 if (VERBOSE) {
192 printf("==============================================================\n");
193 printf("worker-id: %i\n", worker_id);
194 }
195
196 // create empty bmp-file (black background)
197 if (worker_id == MASTER)
198 write_blank_file("test.bmp");
199
200 if (worker_id == MASTER) {
201
202 /* open file for reading and writing */
203 hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
204 if (INVALID_HANDLE_VALUE == hFile) {
205 err = GetLastError();
206 printErrorAndExit("Error at CreateFile",err);
207 }
208
209 /* create the file mapping object */
210 hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, "bmp_fractal");
211 if (NULL == hMap) {
212 printErrorAndExit("Error at CreateFileMapping", GetLastError());
213 }
214
215 } else {
216
217 // open existing mapping object
218 hMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, "bmp_fractal");
219 if (NULL == hMap)
220 printErrorAndExit("Error at OpenFileMapping", GetLastError());
221 }
222
223 /* map the whole file into the process context */
224 pData = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
225 if (NULL == pData) {
226 printErrorAndExit("Error at MapViewOfFile", GetLastError());
227 }
228
229
230 // calculate pointer to beginning of bitmap
231 pDataBitmap = (unsigned char *)((INT_PTR)pData + sizeof(header));
232
233 // debugging
234 if (VERBOSE) {
235 printf("pos. of file: %p\n", pData);
236 printf("pos. of bitmap: %p\n", pDataBitmap);
237 }
238
239
240 if (use_processes && worker_id != MASTER) {
241
242 if (VERBOSE)
243 printf("inside worker-process\n");
244
245 worker_index = worker_id;
246
247 worker_startrow = atoi(argv[2]);
248 worker_rows = atoi(argv[3]);
249
250 // allocate memory for one worker's arguments
251 if ((worker_args = malloc(sizeof(worker_args[0]))) == NULL)
252 perror("malloc"), exit(1);
253
254 // assign worker's arguments
255 worker_args[0].start_row = worker_startrow;
256 worker_args[0].number_of_rows = worker_rows;
257 worker_args[0].pBitmap = pDataBitmap;
258
259 fractal_create_segment(&worker_args[0]);
260
261 return 0;
262 }
263
264 /*
265 // turn bitmap into white canvas
266 for (offset = 0; offset < 500 * 500 * 3; offset++) {
267 *pDataBitmap = 255;
268 pDataBitmap++;
269 }
270 exit(0);
271 */
272
273 // allocate memory for bitmap
274 /*
275 if ((pDataBitmap = malloc(XSIZE * YSIZE * 3 * sizeof(pDataBitmap[0]))) == NULL)
276 perror("malloc"), exit(1);
277 */
278
279 // allocate memory for table of all worker handles
280 if ((worker_handles = malloc(workers * sizeof(worker_handles[0]))) == NULL)
281 perror("malloc"), exit(1);
282
283 // allocate memory for table of all worker arguments
284 if ((worker_args = malloc(workers * sizeof(worker_args[0]))) == NULL)
285 perror("malloc"), exit(1);
286
287
288 // calculate bitmap segment length for workers
289 worker_rows = YSIZE / workers;
290 if (VERBOSE)
291 printf("rows for each worker: %i\n", worker_rows);
292
293 // start workers
294 for (worker_index = 0; worker_index < workers; worker_index++) {
295
296 // debugging: just run single thread
297 //if (worker_index == 1)
298 // continue;
299
300 // number of row to start for each worker
301 worker_startrow = worker_index * worker_rows;
302
303 // recalculate number of rows for last worker if (YSIZE mod workers) != 0
304 if (worker_index == workers - 1) {
305 worker_rows = YSIZE - worker_startrow;
306 if (VERBOSE)
307 printf("rows for last worker: %i\n", worker_rows);
308 }
309
310 // assign each worker's arguments
311 worker_args[worker_index].start_row = worker_startrow;
312 worker_args[worker_index].number_of_rows = worker_rows;
313 worker_args[worker_index].pBitmap = pDataBitmap;
314
315 if (!use_processes) {
316
317 worker_handles[worker_index] = CreateThread(
318 NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes,
319 0, // SIZE_T dwStackSize,
320 &fractal_create_segment, // LPTHREAD_START_ROUTINE lpStartAddress,
321 &worker_args[worker_index], // LPVOID lpParameter,
322 0, // DWORD dwCreationFlags,
323 NULL // LPDWORD lpThreadId
324 );
325
326 if (!worker_handles[worker_index])
327 printErrorAndExit("CreateThread failed", GetLastError());
328
329 } else {
330
331 _snprintf(szCmdline, 1023, "%s %i %i %i", argv[0], worker_index + 1, worker_startrow, worker_rows);
332 ZeroMemory( &si, sizeof(si) );
333 si.cb = sizeof(si);
334 ZeroMemory( &pi, sizeof(pi) );
335
336 if (!CreateProcess(
337 NULL, // No module name (use command line)
338 szCmdline, // Command line
339 NULL, // Process handle not inheritable
340 NULL, // Thread handle not inheritable
341 FALSE, // Set handle inheritance to FALSE
342 0, // No creation flags
343 NULL, // Use parent's environment block
344 NULL, // Use parent's starting directory
345 &si, // Pointer to STARTUPINFO structure
346 &pi // Pointer to PROCESS_INFORMATION structure
347 ))
348 printErrorAndExit("CreateProcess failed", GetLastError());
349
350 worker_handles[worker_index] = pi.hProcess;
351
352 }
353
354 }
355
356 // wait for all threads
357 if (VERBOSE)
358 printf("waiting for workers to finish...\n");
359 if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED)
360 perror("WaitForMultipleObjects");
361
362 // debugging: just run single thread
363 //if (WaitForSingleObject(worker_handles[0], INFINITE) == WAIT_FAILED)
364 // perror("WaitForSingleObject");
365
366 // close all worker handles
367 for (worker_index = 0; worker_index < workers; worker_index++)
368 CloseHandle(worker_handles[worker_index]);
369
370 /* write the result into the file */
371 if (!FlushViewOfFile(pData, 0)) {
372 err = GetLastError();
373 printErrorAndExit("Error at UnmapViewOfFile", err);
374 }
375
376 /* remove the mapped file */
377 if (!UnmapViewOfFile(pData)) {
378 err = GetLastError();
379 printErrorAndExit("Error at UnmapViewOfFile", err);
380 exit(err);
381 }
382
383 /* cleanup handles */
384 if (!CloseHandle(hMap) || !CloseHandle(hFile) ) {
385 err = GetLastError();
386 printErrorAndExit("Error at CloseHandle", err);
387 }
388
389 free(worker_args);
390 free(worker_handles);
391
392 return 0;
393
394 }

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed