--- joko/Uni/BSArch/04/bmp_fractal.c 2006/07/02 12:08:10 1.15 +++ joko/Uni/BSArch/04/bmp_fractal.c 2006/07/02 12:41:56 1.18 @@ -5,7 +5,7 @@ * Uebung 4.4 */ -// $Id: bmp_fractal.c,v 1.15 2006/07/02 12:08:10 joko Exp $ +// $Id: bmp_fractal.c,v 1.18 2006/07/02 12:41:56 joko Exp $ #include #include @@ -15,6 +15,9 @@ #define YSIZE 500 #include "algorithm.h" +#define MAX_COMMAND_LINE 65536 +#define MMAP_NAME "bmp_fractal" + BOOL VERBOSE = FALSE; @@ -92,7 +95,10 @@ } // close file handle - fclose(fd); + if (fclose(fd) != 0) { + perror("Error while closing file handle"); + exit(1); + } } @@ -115,8 +121,6 @@ int x, y; char bgr[3]; - thread_id = GetCurrentThreadId(); - // get worker arguments args = (PWORKERARGS)lpParam; @@ -125,6 +129,7 @@ // debugging if (VERBOSE) { + thread_id = GetCurrentThreadId(); fprintf(stdout, "----------------------------------------------\n"); fprintf(stdout, "thread_id: %i\n", thread_id); fprintf(stdout, "arg.start_row: %i\n", args->start_row); @@ -136,6 +141,8 @@ for (y = (args->start_row + args->number_of_rows) - 1; y >= args->start_row; y--) { //fprintf(stdout, "calc: thread=%i; y=%i limits: %i,%i p: %p\n", thread_id, y, args->start_row, args->number_of_rows, pDataBitmapSegment); for (x = 0; x < XSIZE; x++) { + + // call to function in static linked library getColorValuesAt(x * (2.0 / XSIZE) - 1.5, y * (2.0 / YSIZE) - 1.0, &bgr[2], &bgr[1], &bgr[0]); // transfer color values to current pixel @@ -156,7 +163,6 @@ } -//BOOL scan_argv(int argc, char *argv[], char opt_name[], char *opt_value[]) { BOOL scan_argv(int argc, char *argv[], char opt_name[], char *opt_value) { int i; char * opt_current_name; @@ -187,10 +193,11 @@ unsigned char *pDataBitmap; // workers - int workers = 5; + int workers; int worker_index, worker_rows, worker_startrow; HANDLE *worker_handles; PWORKERARGS worker_args; + int worker_count; // threads or processes? BOOL use_processes = FALSE; @@ -199,7 +206,7 @@ // information for creating processes STARTUPINFO si; PROCESS_INFORMATION pi; - char szCmdline[65536]; + char szCmdline[MAX_COMMAND_LINE]; // command line stuff char arg_option[1024]; @@ -208,12 +215,14 @@ char *verbose_option = ""; - // parse command line arguments + // check command line arguments if (argc < 2) { - fprintf(stderr, "Can not run without arguments!\nPlease specify '-t {number of threads}' or '-p {number of processes}' and an image filename.\n"); + fprintf(stderr, "Error: Can not run without arguments!\nPlease specify '-t {number of threads}' or '-p {number of processes}' and an image filename.\n"); exit(EXIT_FAILURE); } + + // parse command line arguments if (scan_argv(argc, argv, "--verbose", arg_value)) { VERBOSE = TRUE; } @@ -224,7 +233,7 @@ } else if (scan_argv(argc, argv, "-p", arg_value)) { if (strlen(arg_value) == 0) { - fprintf(stderr, "Please specify number of processes!\n"); + fprintf(stderr, "Error: Please specify number of processes!\n"); exit(EXIT_FAILURE); } use_processes = TRUE; @@ -232,16 +241,20 @@ workers = atoi(arg_value); } else if (scan_argv(argc, argv, "-t", arg_value)) { - if (strlen(arg_value) == 0) { - fprintf(stderr, "Please specify number of threads!\n"); + + if (strlen(arg_value) == 0) + fprintf(stderr, "Error: Please specify number of threads!\n"), exit(EXIT_FAILURE); - } + use_processes = FALSE; is_worker_process = FALSE; workers = atoi(arg_value); } - + + if (!is_worker_process && workers < 1) + fprintf(stderr, "Error: Number of threads/processes must be >0!\n"), + exit(EXIT_FAILURE); if (VERBOSE && use_processes) { fprintf(stdout, "===================================================== "); @@ -256,7 +269,7 @@ if (!is_worker_process) { if (argc < 4) { - fprintf(stderr, "Must give filename of image as third argument!\n"); + fprintf(stderr, "Error: Must give filename of image as third argument!\n"); exit(EXIT_FAILURE); } @@ -273,7 +286,7 @@ } // create the file mapping object - hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, "bmp_fractal"); + hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, MMAP_NAME); if (NULL == hMap) { printErrorAndExit("Error at CreateFileMapping", GetLastError()); } @@ -282,7 +295,7 @@ } else { // open existing mapping object - hMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, "bmp_fractal"); + hMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, MMAP_NAME); if (NULL == hMap) printErrorAndExit("Error at OpenFileMapping", GetLastError()); } @@ -400,9 +413,11 @@ if (VERBOSE) verbose_option = "--verbose"; - _snprintf(szCmdline, 1023, "%s %s %i %i %s", argv[0], "--worker", worker_startrow, worker_rows, verbose_option); + _snprintf(szCmdline, MAX_COMMAND_LINE - 1, "%s %s %i %i %s", argv[0], "--worker", worker_startrow, worker_rows, verbose_option); if (VERBOSE) fprintf(stdout, "starting worker process: %s\n", szCmdline); + + // prepare data structures for CreateProcess ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); @@ -427,38 +442,37 @@ } - // wait for all threads if (VERBOSE) fprintf(stdout, "waiting for workers to finish...\n"); - if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED) - printErrorAndExit("Error at WaitForMultipleObjects", GetLastError()); + + // wait for all workers + for (worker_index = 0; worker_index < workers; worker_index += MAXIMUM_WAIT_OBJECTS) { + worker_count = ((workers - worker_index) > MAXIMUM_WAIT_OBJECTS) ? MAXIMUM_WAIT_OBJECTS : (workers - worker_index); + if (WaitForMultipleObjects(worker_count, &worker_handles[worker_index], TRUE, INFINITE) == WAIT_FAILED) + printErrorAndExit("Error at WaitForMultipleObjects", GetLastError()); + } // debugging: just run single thread //if (WaitForSingleObject(worker_handles[0], INFINITE) == WAIT_FAILED) // perror("WaitForSingleObject"); // close all worker handles - for (worker_index = 0; worker_index < workers; worker_index++) - CloseHandle(worker_handles[worker_index]); + for (worker_index = 0; worker_index < workers; worker_index++) { + if (!CloseHandle(worker_handles[worker_index])) + printErrorAndExit("Error at CloseHandle for worker handles", GetLastError()); + } // write the result into the file - if (!FlushViewOfFile(pData, 0)) { - err = GetLastError(); - printErrorAndExit("Error at UnmapViewOfFile", err); - } + if (!FlushViewOfFile(pData, 0)) + printErrorAndExit("Error at UnmapViewOfFile", GetLastError()); // remove the mapped file - if (!UnmapViewOfFile(pData)) { - err = GetLastError(); - printErrorAndExit("Error at UnmapViewOfFile", err); - exit(err); - } + if (!UnmapViewOfFile(pData)) + printErrorAndExit("Error at UnmapViewOfFile", GetLastError()); // cleanup handles - if (!CloseHandle(hMap) || !CloseHandle(hFile) ) { - err = GetLastError(); - printErrorAndExit("Error at CloseHandle", err); - } + if (!CloseHandle(hMap) || !CloseHandle(hFile) ) + printErrorAndExit("Error at CloseHandle for memory mapped file", GetLastError()); free(worker_args); free(worker_handles);