/[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.10 - (hide 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 joko 1.1 /* Betriebssystem & Middleware
2     *
3     * Betriebssystemarchitektur SS 2006
4     *
5     * Uebung 4.4
6     */
7 joko 1.3
8 joko 1.10 // $Id: bmp_fractal.c,v 1.9 2006/07/02 00:24:17 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.10 #define MASTER -1
19    
20     BOOL VERBOSE = TRUE;
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     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 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     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 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.7 //printf("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     printf("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     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 joko 1.3
196 joko 1.4 // create empty bmp-file (black background)
197 joko 1.10 if (worker_id == MASTER)
198     write_blank_file("test.bmp");
199 joko 1.3
200 joko 1.10 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 joko 1.3
209 joko 1.10 /* 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 joko 1.3 }
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 joko 1.9 if (VERBOSE) {
235     printf("pos. of file: %p\n", pData);
236     printf("pos. of bitmap: %p\n", pDataBitmap);
237     }
238 joko 1.3
239 joko 1.10
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 joko 1.3 /*
265 joko 1.9 // turn bitmap into white canvas
266 joko 1.3 for (offset = 0; offset < 500 * 500 * 3; offset++) {
267 joko 1.9 *pDataBitmap = 255;
268     pDataBitmap++;
269 joko 1.3 }
270 joko 1.9 exit(0);
271 joko 1.3 */
272    
273 joko 1.9 // allocate memory for bitmap
274     /*
275     if ((pDataBitmap = malloc(XSIZE * YSIZE * 3 * sizeof(pDataBitmap[0]))) == NULL)
276     perror("malloc"), exit(1);
277     */
278    
279 joko 1.6 // allocate memory for table of all worker handles
280 joko 1.9 if ((worker_handles = malloc(workers * sizeof(worker_handles[0]))) == NULL)
281 joko 1.6 perror("malloc"), exit(1);
282    
283     // allocate memory for table of all worker arguments
284 joko 1.9 if ((worker_args = malloc(workers * sizeof(worker_args[0]))) == NULL)
285 joko 1.6 perror("malloc"), exit(1);
286 joko 1.8
287 joko 1.6
288 joko 1.10 // calculate bitmap segment length for workers
289 joko 1.5 worker_rows = YSIZE / workers;
290 joko 1.9 if (VERBOSE)
291     printf("rows for each worker: %i\n", worker_rows);
292 joko 1.10
293     // start workers
294 joko 1.5 for (worker_index = 0; worker_index < workers; worker_index++) {
295    
296 joko 1.9 // debugging: just run single thread
297 joko 1.7 //if (worker_index == 1)
298     // continue;
299    
300 joko 1.5 // 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 joko 1.9 if (VERBOSE)
307     printf("rows for last worker: %i\n", worker_rows);
308 joko 1.5 }
309 joko 1.6
310 joko 1.10 // assign each worker's arguments
311 joko 1.6 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 joko 1.10 if (!use_processes) {
316 joko 1.6
317 joko 1.10 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 joko 1.5 }
355    
356 joko 1.6 // wait for all threads
357 joko 1.9 if (VERBOSE)
358 joko 1.10 printf("waiting for workers to finish...\n");
359 joko 1.6 if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED)
360     perror("WaitForMultipleObjects");
361 joko 1.7
362 joko 1.9 // debugging: just run single thread
363 joko 1.7 //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 joko 1.3 /* 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 joko 1.1
389 joko 1.9 free(worker_args);
390     free(worker_handles);
391 joko 1.8
392     return 0;
393    
394 joko 1.1 }

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