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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (hide 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 joko 1.1 /* Betriebssystem & Middleware
2     *
3     * Betriebssystemarchitektur SS 2006
4     *
5     * Uebung 4.4
6     */
7 joko 1.3
8 joko 1.11 // $Id: bmp_fractal.c,v 1.10 2006/07/02 01:51:26 joko Exp $
9 joko 1.3
10     #include <windows.h>
11 joko 1.1 #include <stdio.h>
12     #include <errno.h>
13    
14     #define XSIZE 500
15     #define YSIZE 500
16     #include "algorithm.h"
17    
18 joko 1.11 #define VERBOSE_HANDLE "stderr";
19 joko 1.10
20 joko 1.11 BOOL VERBOSE = FALSE;
21 joko 1.9
22 joko 1.3
23 joko 1.2 /* BMP Header */
24 joko 1.1 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 joko 1.3
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 joko 1.11 fprintf(stdout, "%s: %s\n", msg, lpMsgBuf);
55 joko 1.3 LocalFree(lpMsgBuf);
56     }
57     else
58     {
59 joko 1.11 fprintf(stdout, "Error at FormatMesage: %d\n",err=GetLastError());
60 joko 1.3 }
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 joko 1.1 }
94 joko 1.3 }
95    
96     // close file handle
97     fclose(fd);
98     }
99    
100    
101 joko 1.6 // arguments for each thread
102     typedef struct _WorkerArguments {
103 joko 1.7 int start_row;
104     int number_of_rows;
105 joko 1.6 unsigned char * pBitmap;
106     } WORKERARGS, *PWORKERARGS;
107    
108     // worker thread - main entry function
109 joko 1.10 DWORD WINAPI fractal_create_segment (LPVOID lpParam) {
110 joko 1.6
111     // thread stuff
112     int thread_id;
113     PWORKERARGS args;
114 joko 1.7 unsigned char *pDataBitmapSegment;
115 joko 1.6
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 joko 1.7
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 joko 1.9
128     // debugging
129     if (VERBOSE) {
130 joko 1.11 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 joko 1.9 }
136 joko 1.6
137     // calculate fractal
138     for (y = (args->start_row + args->number_of_rows) - 1; y >= args->start_row; y--) {
139 joko 1.11 //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 joko 1.6 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 joko 1.7 pDataBitmapSegment[0] = bgr[0];
145     pDataBitmapSegment[1] = bgr[1];
146     pDataBitmapSegment[2] = bgr[2];
147 joko 1.6
148     // move pointer to next pixel
149 joko 1.7 pDataBitmapSegment += 3;
150 joko 1.6
151     }
152 joko 1.9 //no padding required because 1500%4 =0 ???
153 joko 1.6 }
154    
155 joko 1.9 if (VERBOSE)
156 joko 1.11 fprintf(stdout, "thread finished: %i\n", thread_id);
157 joko 1.6 return 0;
158    
159     }
160    
161    
162 joko 1.3 int main(int argc, char *argv[]) {
163    
164 joko 1.4 // MMF support
165     DWORD err;
166 joko 1.3 HANDLE hMap, hFile;
167     LPVOID pData;
168 joko 1.9 unsigned char *pDataBitmap;
169 joko 1.4
170 joko 1.5 // workers
171 joko 1.10 int workers = 5;
172 joko 1.7 int worker_index, worker_rows, worker_startrow;
173 joko 1.6 HANDLE *worker_handles;
174     PWORKERARGS worker_args;
175    
176 joko 1.10 // threads or processes?
177     BOOL use_processes = TRUE;
178 joko 1.11 BOOL is_worker = FALSE;
179 joko 1.10
180     // information for creating processes
181     STARTUPINFO si;
182     PROCESS_INFORMATION pi;
183     char szCmdline[1024];
184    
185    
186 joko 1.11 VERBOSE = TRUE;
187    
188 joko 1.10 // "parse" command line arguments
189     if (argc >= 2) {
190 joko 1.11 if (strcmp(argv[1], "--worker") == 0) {
191     is_worker = TRUE;
192     }
193 joko 1.10 }
194    
195 joko 1.11 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 joko 1.10 }
202 joko 1.3
203 joko 1.4 // create empty bmp-file (black background)
204 joko 1.11 if (!is_worker)
205 joko 1.10 write_blank_file("test.bmp");
206 joko 1.3
207 joko 1.11 if (!is_worker) {
208 joko 1.10
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 joko 1.3
216 joko 1.10 /* 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 joko 1.3 }
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 joko 1.9 if (VERBOSE) {
242 joko 1.11 fprintf(stdout, "pos. of file: %p\n", pData);
243     fprintf(stdout, "pos. of bitmap: %p\n", pDataBitmap);
244 joko 1.9 }
245 joko 1.3
246 joko 1.10
247 joko 1.11 if (use_processes && is_worker) {
248 joko 1.10
249     if (VERBOSE)
250 joko 1.11 fprintf(stdout, "inside worker-process\n");
251 joko 1.10
252 joko 1.11 // get segment information from command line
253 joko 1.10 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 joko 1.3 /*
271 joko 1.9 // turn bitmap into white canvas
272 joko 1.3 for (offset = 0; offset < 500 * 500 * 3; offset++) {
273 joko 1.9 *pDataBitmap = 255;
274     pDataBitmap++;
275 joko 1.3 }
276 joko 1.9 exit(0);
277 joko 1.3 */
278    
279 joko 1.9 // allocate memory for bitmap
280     /*
281     if ((pDataBitmap = malloc(XSIZE * YSIZE * 3 * sizeof(pDataBitmap[0]))) == NULL)
282     perror("malloc"), exit(1);
283     */
284    
285 joko 1.6 // allocate memory for table of all worker handles
286 joko 1.9 if ((worker_handles = malloc(workers * sizeof(worker_handles[0]))) == NULL)
287 joko 1.6 perror("malloc"), exit(1);
288    
289     // allocate memory for table of all worker arguments
290 joko 1.9 if ((worker_args = malloc(workers * sizeof(worker_args[0]))) == NULL)
291 joko 1.6 perror("malloc"), exit(1);
292 joko 1.8
293 joko 1.6
294 joko 1.10 // calculate bitmap segment length for workers
295 joko 1.5 worker_rows = YSIZE / workers;
296 joko 1.9 if (VERBOSE)
297 joko 1.11 fprintf(stdout, "rows for each worker: %i\n", worker_rows);
298 joko 1.10
299     // start workers
300 joko 1.5 for (worker_index = 0; worker_index < workers; worker_index++) {
301    
302 joko 1.9 // debugging: just run single thread
303 joko 1.7 //if (worker_index == 1)
304     // continue;
305    
306 joko 1.5 // 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 joko 1.9 if (VERBOSE)
313 joko 1.11 fprintf(stdout, "rows for last worker: %i\n", worker_rows);
314 joko 1.5 }
315 joko 1.6
316 joko 1.10 // assign each worker's arguments
317 joko 1.6 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 joko 1.10 if (!use_processes) {
322 joko 1.6
323 joko 1.10 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 joko 1.11 _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 joko 1.10 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 joko 1.5 }
363    
364 joko 1.6 // wait for all threads
365 joko 1.9 if (VERBOSE)
366 joko 1.11 fprintf(stdout, "waiting for workers to finish...\n");
367 joko 1.6 if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED)
368     perror("WaitForMultipleObjects");
369 joko 1.7
370 joko 1.9 // debugging: just run single thread
371 joko 1.7 //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 joko 1.3 /* 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 joko 1.1
397 joko 1.9 free(worker_args);
398     free(worker_handles);
399 joko 1.8
400     return 0;
401    
402 joko 1.1 }

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