--- joko/Uni/BSArch/04/bmp_fractal.c 2006/07/02 00:24:17 1.9 +++ joko/Uni/BSArch/04/bmp_fractal.c 2006/07/02 01:51:26 1.10 @@ -5,7 +5,7 @@ * Uebung 4.4 */ -// $Id: bmp_fractal.c,v 1.9 2006/07/02 00:24:17 joko Exp $ +// $Id: bmp_fractal.c,v 1.10 2006/07/02 01:51:26 joko Exp $ #include #include @@ -15,7 +15,9 @@ #define YSIZE 500 #include "algorithm.h" -BOOL VERBOSE = FALSE; +#define MASTER -1 + +BOOL VERBOSE = TRUE; /* BMP Header */ @@ -104,7 +106,7 @@ } WORKERARGS, *PWORKERARGS; // worker thread - main entry function -DWORD WINAPI fractal_thread (LPVOID lpParam) { +DWORD WINAPI fractal_create_segment (LPVOID lpParam) { // thread stuff int thread_id; @@ -166,26 +168,56 @@ unsigned char *pDataBitmap; // workers - int workers = 50; + int workers = 5; int worker_index, worker_rows, worker_startrow; HANDLE *worker_handles; PWORKERARGS worker_args; + // threads or processes? + BOOL use_processes = TRUE; + int worker_id = MASTER; + + // information for creating processes + STARTUPINFO si; + PROCESS_INFORMATION pi; + char szCmdline[1024]; + + + // "parse" command line arguments + if (argc >= 2) { + worker_id = atoi(argv[1]); + } + + if (VERBOSE) { + printf("==============================================================\n"); + printf("worker-id: %i\n", worker_id); + } // create empty bmp-file (black background) - write_blank_file("test.bmp"); + if (worker_id == MASTER) + write_blank_file("test.bmp"); - /* open file for reading and writing */ - hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (INVALID_HANDLE_VALUE == hFile) { - err = GetLastError(); - printErrorAndExit("Error at CreateFile",err); - } + if (worker_id == MASTER) { + + /* open file for reading and writing */ + hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (INVALID_HANDLE_VALUE == hFile) { + err = GetLastError(); + printErrorAndExit("Error at CreateFile",err); + } - /* create the file mapping object */ - hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); - if (NULL == hMap) { - printErrorAndExit("Error at CreateFileMapping", GetLastError()); + /* create the file mapping object */ + hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, "bmp_fractal"); + if (NULL == hMap) { + printErrorAndExit("Error at CreateFileMapping", GetLastError()); + } + + } else { + + // open existing mapping object + hMap = OpenFileMapping(FILE_MAP_WRITE, FALSE, "bmp_fractal"); + if (NULL == hMap) + printErrorAndExit("Error at OpenFileMapping", GetLastError()); } /* map the whole file into the process context */ @@ -204,6 +236,31 @@ printf("pos. of bitmap: %p\n", pDataBitmap); } + + if (use_processes && worker_id != MASTER) { + + if (VERBOSE) + printf("inside worker-process\n"); + + worker_index = worker_id; + + worker_startrow = atoi(argv[2]); + worker_rows = atoi(argv[3]); + + // allocate memory for one worker's arguments + if ((worker_args = malloc(sizeof(worker_args[0]))) == NULL) + perror("malloc"), exit(1); + + // assign worker's arguments + worker_args[0].start_row = worker_startrow; + worker_args[0].number_of_rows = worker_rows; + worker_args[0].pBitmap = pDataBitmap; + + fractal_create_segment(&worker_args[0]); + + return 0; + } + /* // turn bitmap into white canvas for (offset = 0; offset < 500 * 500 * 3; offset++) { @@ -228,10 +285,12 @@ perror("malloc"), exit(1); - // calculate segments of bitmap for worker threads/processes and start them + // calculate bitmap segment length for workers worker_rows = YSIZE / workers; if (VERBOSE) printf("rows for each worker: %i\n", worker_rows); + + // start workers for (worker_index = 0; worker_index < workers; worker_index++) { // debugging: just run single thread @@ -248,24 +307,55 @@ printf("rows for last worker: %i\n", worker_rows); } + // assign each worker's arguments worker_args[worker_index].start_row = worker_startrow; worker_args[worker_index].number_of_rows = worker_rows; worker_args[worker_index].pBitmap = pDataBitmap; - worker_handles[worker_index] = CreateThread( - NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, - 0, // SIZE_T dwStackSize, - &fractal_thread, // LPTHREAD_START_ROUTINE lpStartAddress, - &worker_args[worker_index], // LPVOID lpParameter, - 0, // DWORD dwCreationFlags, - NULL // LPDWORD lpThreadId - ); + if (!use_processes) { + worker_handles[worker_index] = CreateThread( + NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, + 0, // SIZE_T dwStackSize, + &fractal_create_segment, // LPTHREAD_START_ROUTINE lpStartAddress, + &worker_args[worker_index], // LPVOID lpParameter, + 0, // DWORD dwCreationFlags, + NULL // LPDWORD lpThreadId + ); + + if (!worker_handles[worker_index]) + printErrorAndExit("CreateThread failed", GetLastError()); + + } else { + + _snprintf(szCmdline, 1023, "%s %i %i %i", argv[0], worker_index + 1, worker_startrow, worker_rows); + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + + if (!CreateProcess( + NULL, // No module name (use command line) + szCmdline, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi // Pointer to PROCESS_INFORMATION structure + )) + printErrorAndExit("CreateProcess failed", GetLastError()); + + worker_handles[worker_index] = pi.hProcess; + + } + } // wait for all threads if (VERBOSE) - printf("waiting...\n"); + printf("waiting for workers to finish...\n"); if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED) perror("WaitForMultipleObjects");