/[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.12 - (show annotations)
Sun Jul 2 09:27:14 2006 UTC (18 years, 2 months ago) by joko
Branch: MAIN
Changes since 1.11: +20 -16 lines
File MIME type: text/plain
some cleanup

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

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