/[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.11 - (show annotations)
Sun Jul 2 02:12:27 2006 UTC (18 years, 2 months ago) by joko
Branch: MAIN
Changes since 1.10: +37 -29 lines
File MIME type: text/plain
little command line argument parsing and cleanup

1 /* Betriebssystem & Middleware
2 *
3 * Betriebssystemarchitektur SS 2006
4 *
5 * Uebung 4.4
6 */
7
8 // $Id: bmp_fractal.c,v 1.10 2006/07/02 01:51:26 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 VERBOSE_HANDLE "stderr";
19
20 BOOL VERBOSE = FALSE;
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(stdout, "%s: %s\n", msg, lpMsgBuf);
55 LocalFree(lpMsgBuf);
56 }
57 else
58 {
59 fprintf(stdout, "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 fprintf(stdout, "----------------------------------------------\n");
131 fprintf(stdout, "thread_id: %i\n", thread_id);
132 fprintf(stdout, "arg.start_row: %i\n", args->start_row);
133 fprintf(stdout, "arg.number_of_rows: %i\n", args->number_of_rows);
134 fprintf(stdout, "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 //fprintf(stdout, "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 fprintf(stdout, "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 BOOL is_worker = FALSE;
179
180 // information for creating processes
181 STARTUPINFO si;
182 PROCESS_INFORMATION pi;
183 char szCmdline[1024];
184
185
186 VERBOSE = TRUE;
187
188 // "parse" command line arguments
189 if (argc >= 2) {
190 if (strcmp(argv[1], "--worker") == 0) {
191 is_worker = TRUE;
192 }
193 }
194
195 if (VERBOSE && use_processes) {
196 fprintf(stdout, "===================================================== ");
197 if (is_worker)
198 fprintf(stdout, "WORKER-PROCESS\n");
199 else
200 fprintf(stdout, "MASTER-PROCESS\n");
201 }
202
203 // create empty bmp-file (black background)
204 if (!is_worker)
205 write_blank_file("test.bmp");
206
207 if (!is_worker) {
208
209 /* open file for reading and writing */
210 hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
211 if (INVALID_HANDLE_VALUE == hFile) {
212 err = GetLastError();
213 printErrorAndExit("Error at CreateFile",err);
214 }
215
216 /* create the file mapping object */
217 hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, "bmp_fractal");
218 if (NULL == hMap) {
219 printErrorAndExit("Error at CreateFileMapping", GetLastError());
220 }
221
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) {
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 return 0;
268 }
269
270 /*
271 // turn bitmap into white canvas
272 for (offset = 0; offset < 500 * 500 * 3; offset++) {
273 *pDataBitmap = 255;
274 pDataBitmap++;
275 }
276 exit(0);
277 */
278
279 // allocate memory for bitmap
280 /*
281 if ((pDataBitmap = malloc(XSIZE * YSIZE * 3 * sizeof(pDataBitmap[0]))) == NULL)
282 perror("malloc"), exit(1);
283 */
284
285 // allocate memory for table of all worker handles
286 if ((worker_handles = malloc(workers * sizeof(worker_handles[0]))) == NULL)
287 perror("malloc"), exit(1);
288
289 // allocate memory for table of all worker arguments
290 if ((worker_args = malloc(workers * sizeof(worker_args[0]))) == NULL)
291 perror("malloc"), exit(1);
292
293
294 // calculate bitmap segment length for workers
295 worker_rows = YSIZE / workers;
296 if (VERBOSE)
297 fprintf(stdout, "rows for each worker: %i\n", worker_rows);
298
299 // start workers
300 for (worker_index = 0; worker_index < workers; worker_index++) {
301
302 // debugging: just run single thread
303 //if (worker_index == 1)
304 // continue;
305
306 // number of row to start for each worker
307 worker_startrow = worker_index * worker_rows;
308
309 // recalculate number of rows for last worker if (YSIZE mod workers) != 0
310 if (worker_index == workers - 1) {
311 worker_rows = YSIZE - worker_startrow;
312 if (VERBOSE)
313 fprintf(stdout, "rows for last worker: %i\n", worker_rows);
314 }
315
316 // assign each worker's arguments
317 worker_args[worker_index].start_row = worker_startrow;
318 worker_args[worker_index].number_of_rows = worker_rows;
319 worker_args[worker_index].pBitmap = pDataBitmap;
320
321 if (!use_processes) {
322
323 worker_handles[worker_index] = CreateThread(
324 NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes,
325 0, // SIZE_T dwStackSize,
326 &fractal_create_segment, // LPTHREAD_START_ROUTINE lpStartAddress,
327 &worker_args[worker_index], // LPVOID lpParameter,
328 0, // DWORD dwCreationFlags,
329 NULL // LPDWORD lpThreadId
330 );
331
332 if (!worker_handles[worker_index])
333 printErrorAndExit("CreateThread failed", GetLastError());
334
335 } else {
336
337 _snprintf(szCmdline, 1023, "%s %s %i %i", argv[0], "--worker", worker_startrow, worker_rows);
338 if (VERBOSE)
339 fprintf(stdout, "starting worker process: %s\n", szCmdline);
340 ZeroMemory( &si, sizeof(si) );
341 si.cb = sizeof(si);
342 ZeroMemory( &pi, sizeof(pi) );
343
344 if (!CreateProcess(
345 NULL, // No module name (use command line)
346 szCmdline, // Command line
347 NULL, // Process handle not inheritable
348 NULL, // Thread handle not inheritable
349 FALSE, // Set handle inheritance to FALSE
350 0, // No creation flags
351 NULL, // Use parent's environment block
352 NULL, // Use parent's starting directory
353 &si, // Pointer to STARTUPINFO structure
354 &pi // Pointer to PROCESS_INFORMATION structure
355 ))
356 printErrorAndExit("CreateProcess failed", GetLastError());
357
358 worker_handles[worker_index] = pi.hProcess;
359
360 }
361
362 }
363
364 // wait for all threads
365 if (VERBOSE)
366 fprintf(stdout, "waiting for workers to finish...\n");
367 if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED)
368 perror("WaitForMultipleObjects");
369
370 // debugging: just run single thread
371 //if (WaitForSingleObject(worker_handles[0], INFINITE) == WAIT_FAILED)
372 // perror("WaitForSingleObject");
373
374 // close all worker handles
375 for (worker_index = 0; worker_index < workers; worker_index++)
376 CloseHandle(worker_handles[worker_index]);
377
378 /* write the result into the file */
379 if (!FlushViewOfFile(pData, 0)) {
380 err = GetLastError();
381 printErrorAndExit("Error at UnmapViewOfFile", err);
382 }
383
384 /* remove the mapped file */
385 if (!UnmapViewOfFile(pData)) {
386 err = GetLastError();
387 printErrorAndExit("Error at UnmapViewOfFile", err);
388 exit(err);
389 }
390
391 /* cleanup handles */
392 if (!CloseHandle(hMap) || !CloseHandle(hFile) ) {
393 err = GetLastError();
394 printErrorAndExit("Error at CloseHandle", err);
395 }
396
397 free(worker_args);
398 free(worker_handles);
399
400 return 0;
401
402 }

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