int MFNHashTypePlainCUDA::setCUDADeviceID(int newCUDADeviceId) { trace_printf("MFNHashTypePlainCUDA::setCUDADeviceID(%d)\n", newCUDADeviceId); CHCUDAUtils *CudaUtils = MultiforcerGlobalClassFactory.getCudaUtilsClass(); MFNCommandLineData *CommandLineData = MultiforcerGlobalClassFactory.getCommandlinedataClass(); if (newCUDADeviceId >= CudaUtils->getCudaDeviceCount()) { printf("Invalid device ID - greater than number of devices!\n"); exit(1); } this->gpuDeviceId = newCUDADeviceId; // If the blocks or threads are set, use them, else use the default. if (CommandLineData->GetGpuBlocks()) { this->GPUBlocks = CommandLineData->GetGpuBlocks(); klaunch_printf("Using CLI GPU Blocks %d\n", this->GPUBlocks); } else { this->GPUBlocks = CudaUtils->getCudaDefaultBlockCount(newCUDADeviceId); klaunch_printf("Using Default GPU Blocks %d\n", this->GPUBlocks); } if (CommandLineData->GetGpuThreads()) { this->GPUThreads = CommandLineData->GetGpuThreads(); klaunch_printf("Using CLI GPU Threads %d\n", this->GPUThreads); } else { this->GPUThreads = CudaUtils->getCudaDefaultThreadCount(newCUDADeviceId); klaunch_printf("Using Default GPU Threads %d\n", this->GPUThreads); } // If target time is 0, use defaults. if (CommandLineData->GetTargetExecutionTimeMs()) { this->kernelTimeMs = CommandLineData->GetTargetExecutionTimeMs(); } else { if (CudaUtils->getCudaHasTimeout(newCUDADeviceId)) { this->kernelTimeMs = 50; } else { this->kernelTimeMs = 500; } } // Override thread count if needed for hash type. this->GPUThreads = this->getMaxHardwareThreads(this->GPUThreads); this->VectorWidth = 1; this->TotalKernelWidth = this->GPUBlocks * this->GPUThreads * this->VectorWidth; //printf("Successfully added device %d, thread ID %d\n", newCUDADeviceId, this->threadId); //printf("Thread %d blocks/threads/vec: %d/%d/%d\n", this->threadId, this->GPUBlocks, this->GPUThreads, this->VectorWidth); return 1; }
void MFNHashTypePlainCUDA::setupDevice() { trace_printf("CHHashTypeVPlainCUDA::setupDevice()\n"); CHCUDAUtils *CudaUtils = MultiforcerGlobalClassFactory.getCudaUtilsClass(); // Set the CUDA device trace_printf("Thread %d setting device to %d\n",this->threadId, this->gpuDeviceId); cudaSetDevice(this->gpuDeviceId); // If the user requests zerocopy and the device can handle it, add it. if (this->CommandLineData->GetUseZeroCopy() && CudaUtils->getCudaCanMapHostMemory(this->gpuDeviceId)) { this->useZeroCopy = 1; } // If the device is integrated & can map memory, add it - integrated devices // are already sharing host memory, so no point in copying the data over. if (CudaUtils->getCudaIsIntegrated(this->gpuDeviceId) && CudaUtils->getCudaCanMapHostMemory(this->gpuDeviceId)) { this->useZeroCopy = 1; } // Enable blocking sync. This dramatically reduces CPU usage. // If zero copy is being used, set DeviceMapHost as well if (this->useZeroCopy) { cudaSetDeviceFlags(cudaDeviceBlockingSync | cudaDeviceMapHost); } else { cudaSetDeviceFlags(cudaDeviceBlockingSync); } }
void MFNWorkunitNetworkClient::SubmitWorkunitById(uint64_t completedWorkunitId) { trace_printf("MFNWorkunitNetworkClient::SubmitWorkunitById(%u)\n", completedWorkunitId); std::list<MFNWorkunitRobustElement>::iterator inflightWorkunit; this->workunitMutexBoost.lock(); // Look for workunit in the list for (inflightWorkunit = this->assignedWorkunits.begin(); inflightWorkunit != this->assignedWorkunits.end(); inflightWorkunit++) { // Check for the unique Workunit ID if (inflightWorkunit->WorkUnitID == completedWorkunitId) { if (this->DebugOutput) { printf("Found inflight WU ID: %lu\n", inflightWorkunit->WorkUnitID); } this->assignedWorkunits.erase(inflightWorkunit); if (this->DebugOutput) { printf("Inflight left: %d\n", this->assignedWorkunits.size()); } break; } } if (this->DebugOutput) { this->PrintInternalState(); } this->workunitMutexBoost.unlock(); MultiforcerGlobalClassFactory.getNetworkClientClass()-> submitWorkunit(completedWorkunitId); }
// Needed for the Windows side of things. void MFNRun() { if (MultiforcerGlobalClassFactory.getCommandlinedataClass()->GetIsNetworkClient()) { runNetworkClientMode(); } else { runStandaloneOrServerMode(); } }
int MFNHashTypePlainOpenCL::setOpenCLDeviceID(int newOpenCLPlatformId, int newOpenCLDeviceId) { trace_printf("MFNHashTypePlainOpenCL::setOpenCLDeviceID(%d, %d)\n", newOpenCLPlatformId, newOpenCLDeviceId); MFNCommandLineData *CommandLineData = MultiforcerGlobalClassFactory.getCommandlinedataClass(); this->OpenCL = new CryptohazeOpenCL(); if (newOpenCLPlatformId > this->OpenCL->getNumberOfPlatforms()) { printf("Error: OpenCL Platform ID %d not valid!\n", newOpenCLPlatformId); exit(1); } this->OpenCL->selectPlatformById(newOpenCLPlatformId); if (newOpenCLDeviceId > this->OpenCL->getNumberOfDevices()) { printf("Error: OpenCL Device ID %d not valid!\n", newOpenCLDeviceId); exit(1); } this->OpenCL->selectDeviceById(newOpenCLDeviceId); this->openCLPlatformId = newOpenCLPlatformId; this->gpuDeviceId = newOpenCLDeviceId; // If the blocks or threads are set, use them, else use the default. if (CommandLineData->GetGpuBlocks()) { this->GPUBlocks = CommandLineData->GetGpuBlocks(); } else { this->GPUBlocks = this->OpenCL->getDefaultBlockCount(); } if (CommandLineData->GetGpuThreads()) { this->GPUThreads = CommandLineData->GetGpuThreads(); } else { this->GPUThreads = this->OpenCL->getDefaultThreadCount(); } // If target time is 0, use defaults. if (CommandLineData->GetTargetExecutionTimeMs()) { this->kernelTimeMs = CommandLineData->GetTargetExecutionTimeMs(); } else { this->kernelTimeMs = 100; } this->OpenCL->createContext(); this->OpenCL->createCommandQueue(); // For now - set by CLI later. this->VectorWidth = 4; this->TotalKernelWidth = this->GPUBlocks * this->GPUThreads * this->VectorWidth; trace_printf("Thread %d added OpenCL Device (%d, %d)\n", this->threadId, newOpenCLPlatformId, newOpenCLDeviceId);; return 1; }
MFNHashTypePlainOpenCL::MFNHashTypePlainOpenCL(int hashLengthBytes) : MFNHashTypePlain(hashLengthBytes) { trace_printf("MFNHashTypePlainOpenCL::MFNHashTypePlainOpenCL(%d)\n", hashLengthBytes); this->MFNHashTypeMutex.lock(); this->threadId = MultiforcerGlobalClassFactory.getDisplayClass()->getFreeThreadId(GPU_THREAD); this->numberThreads++; trace_printf("MFNHashType GPU/OpenCL Thread ID %d\n", this->threadId); this->MFNHashTypeMutex.unlock(); }
void MFNHashTypePlainOpenCL::setupDevice() { trace_printf("CHHashTypeVPlainCUDA::setupDevice()\n"); char buildOptions[1024]; cl_int errorCode; // Set the OpenCL platform & device trace_printf("Thread %d setting OpenCL platform/device to %d, %d\n", this->threadId, this->openCLPlatformId, this->gpuDeviceId); this->OpenCL->selectPlatformById(this->openCLPlatformId); this->OpenCL->selectDeviceById(this->gpuDeviceId); /** * Handle generating the kernels. This involves building with the specified * password length, vector width, and BFI_INT status. */ if (MultiforcerGlobalClassFactory.getCommandlinedataClass()->GetUseBfiInt()) { // BFI_INT patching - pass BITALIGN to kernel sprintf(buildOptions, "-D PASSWORD_LENGTH=%d -D VECTOR_WIDTH=%d -D BITALIGN=1", this->passwordLength, this->VectorWidth); } else { // No BFI_INT patching. sprintf(buildOptions, "-D PASSWORD_LENGTH=%d -D VECTOR_WIDTH=%d", this->passwordLength, this->VectorWidth); } this->OpenCL->buildProgramFromManySourcesConcat(this->getHashFileNames(), buildOptions); // If the BFI_INT patching is being used, patch the generated binary. if (MultiforcerGlobalClassFactory.getCommandlinedataClass()->GetUseBfiInt()) { this->OpenCL->doAMDBFIPatch(); } this->HashProgram = this->OpenCL->getProgram(); this->HashKernel = clCreateKernel (this->HashProgram, this->getHashKernelName().c_str(), &errorCode); if (errorCode != CL_SUCCESS) { printf("Error: %s\n", print_cl_errstring(errorCode)); exit(1); } }
void MFNHashTypePlainCUDA::outputFoundHashes() { trace_printf("MFNHashTypePlain::outputFoundHashes()\n"); uint32_t i, j; /** * A vector containing the hash, processed back into the raw format. */ std::vector<uint8_t> rawHash; std::vector<uint8_t> foundPassword; uint8_t *hostSuccessArray = this->HostSuccessAddress; uint8_t *hostSuccessReportedArray = this->HostSuccessReportedAddress; uint8_t *hostPasswords = this->HostFoundPasswordsAddress; for (i = 0; i < this->activeHashesProcessed.size(); i++) { if (hostSuccessArray[i] && !hostSuccessReportedArray[i]) { rawHash = this->postProcessHash(this->activeHashesProcessed[i]); // Resize to the max pass length + 1 - this ensures that strlen // will find a null byte at the end and stop measuring. foundPassword.resize(this->maxFoundPlainLength + 1, 0); for (j = 0; j < this->maxFoundPlainLength; j++) { foundPassword[j] = hostPasswords[this->maxFoundPlainLength * i + j]; } // Resize to the length of the found password. foundPassword.resize(strlen((char *)&foundPassword[0])); this->HashFile->ReportFoundPassword(rawHash, foundPassword, hostSuccessArray[i]); // Report the found hash over the network. if (this->CommandLineData->GetIsNetworkClient()) { MultiforcerGlobalClassFactory.getNetworkClientClass()-> submitFoundHash(rawHash, foundPassword, hostSuccessArray[i]); } this->Display->addCrackedPassword(foundPassword); hostSuccessReportedArray[i] = 1; } } // Check to see if we should exit (as all hashes are found). if (this->HashFile->GetUncrackedHashCount() == 0) { //global_interface.exit = 1; } }
// Runs the multiforcer in standalone or network server mode. void runStandaloneOrServerMode() { int i; CHCharsetNew *Charset; MFNWorkunitBase *Workunit; CHHashFileV *HashFile; MFNDisplay *Display; char printBuffer[1000]; MFNHashClassLauncher HashClassLauncher; MFNHashIdentifiers *HashIdentifiers; MFNNetworkServer *NetworkServer = NULL; MFNGeneralInformation *GeneralInformation; MFNCommandLineData *CommandLineData; uint32_t hashId; int maxPasswordLength = 0; CommandLineData = MultiforcerGlobalClassFactory.getCommandlinedataClass(); // Default size. May be overridden. int WorkunitSize = 32; std::vector<uint8_t> RestoreData; std::string ResumeFilename; { char ResumeTimestampBuffer[1024]; struct timeval resume_time; time_t resume_time_t; // Get the resume filename with timestamp. gettimeofday(&resume_time, NULL); resume_time_t=resume_time.tv_sec; memset(ResumeTimestampBuffer, 0, sizeof(ResumeTimestampBuffer)); strftime(ResumeTimestampBuffer, 128, "%Y-%m-%d-%H-%M-%S", localtime(&resume_time_t)); ResumeFilename = "CM-Resume-"; ResumeFilename += ResumeTimestampBuffer; ResumeFilename += ".mfr"; } // Determine the hash type HashIdentifiers = MultiforcerGlobalClassFactory.getHashIdentifiersClass(); if (!HashIdentifiers) { printf("Cannot get hash identifiers class!\n"); exit(1); } hashId = HashIdentifiers->GetHashIdFromString(CommandLineData->GetHashTypeString()); if (hashId == MFN_HASHTYPE_UNDEFINED) { printf("Invalid hash type %s!\n", CommandLineData->GetHashTypeString().c_str()); HashIdentifiers->PrintAllHashTypes(); exit(1); } GeneralInformation = MultiforcerGlobalClassFactory.getGeneralInformationClass(); GeneralInformation->setCharsetClassId(CH_CHARSET_NEW_CLASS_ID); GeneralInformation->setHashId(hashId); GeneralInformation->setPasswordLength(CommandLineData->GetMinPasswordLength()); // Get our classes MultiforcerGlobalClassFactory.setCharsetClassType(CH_CHARSET_NEW_CLASS_ID); if (CommandLineData->GetDebug()) { MultiforcerGlobalClassFactory.setDisplayClassType(MFN_DISPLAY_CLASS_DEBUG); } else if (CommandLineData->GetDaemon()) { MultiforcerGlobalClassFactory.setDisplayClassType(MFN_DISPLAY_CLASS_DAEMON); } else { MultiforcerGlobalClassFactory.setDisplayClassType(MFN_DISPLAY_CLASS_CURSES); } // If this is a wordlist class, use a wordlist workunit. if (HashIdentifiers->GetHasWordlist()) { MultiforcerGlobalClassFactory.setWorkunitClassType(MFN_WORKUNIT_WORDLIST_CLASS_ID); } else { MultiforcerGlobalClassFactory.setWorkunitClassType(MFN_WORKUNIT_ROBUST_CLASS_ID); } // Set up the hash specific stuff. MultiforcerGlobalClassFactory.setHashfileClassType(HashIdentifiers->GetHashData().HashFileIdentifier); HashClassLauncher.setHashType(HashIdentifiers->GetHashData().HashTypeIdentifier); Charset = MultiforcerGlobalClassFactory.getCharsetClass(); if (!Charset) { printf("Cannot get charset class!\n"); exit(1); } Workunit = MultiforcerGlobalClassFactory.getWorkunitClass(); if (!Workunit) { printf("Cannot get workunit class!\n"); exit(1); } HashFile = MultiforcerGlobalClassFactory.getHashfileClass(); if (!HashFile) { printf("Cannot get hashfile class!\n"); exit(1); } Display = MultiforcerGlobalClassFactory.getDisplayClass(); if (!Display) { printf("Cannot get display class!\n"); exit(1); } if (CommandLineData->GetDevDebug()) { Workunit->EnableDebugOutput(); } /* if (CommandLineData->GetUseRestoreFile()) { if (!RobustWorkunit->LoadStateFromFile(CommandLineData->GetRestoreFileName())) { printf("Loading state from file failed.\n"); exit(1); } RestoreData = RobustWorkunit->GetResumeMetadata(); CommandLineData->SetDataFromRestore(RestoreData); // Overwrite the existing one as we progress. RobustWorkunit->SetResumeFile(ResumeFilename); } else { RobustWorkunit->SetResumeFile(ResumeFilename); } */ // Set the hash type being used. //HashTypes.SetHashId(CommandLineData->GetHashType()); // Get the HashType class and HashFile class /* */ // If an output file is to be used, set it here. if (CommandLineData->GetOutputFileName().length()) { HashFile->SetFoundHashesOutputFilename(CommandLineData->GetOutputFileName()); } // If the workunit size was set on the command line, use it here. if (CommandLineData->GetWorkunitBits()) { WorkunitSize = CommandLineData->GetWorkunitBits(); } else { WorkunitSize = HashIdentifiers->GetDefaultWorkunitSizeBits(); } if (!Charset->readCharsetFromFile(CommandLineData->GetCharsetFileName())) { printf("Cannot open charset!\n"); exit(1); } //printf("Charset opened properly.\n"); if (!HashFile->OpenHashFile(CommandLineData->GetHashListFileName())) { printf("Cannot open hash file!\n"); exit(1); } //printf("Hashfile opened properly.\n"); // Add hex output option if desired. HashFile->SetAddHexOutput(CommandLineData->GetAddHexOutput()); HashFile->setPrintAlgorithm(CommandLineData->GetPrintAlgorithms()); // If requested bring the network online and assign types to it if (CommandLineData->GetIsNetworkServer()) { MultiforcerGlobalClassFactory.setNetworkServerPort(CommandLineData->GetNetworkPort()); NetworkServer = MultiforcerGlobalClassFactory.getNetworkServerClass(); NetworkServer->startNetwork(); // Update the display with the server info. char portBuffer[16]; sprintf(portBuffer, "%d", CommandLineData->GetNetworkPort()); Display->setSystemMode(SYSTEM_MODE_SERVER, std::string(portBuffer)); } Display->setHashName(HashIdentifiers->GetHashData().HashDescriptor); if (!CommandLineData->GetIsServerOnly()) { if (!HashClassLauncher.addAllDevices(CommandLineData->GetDevicesToUse())) { printf("Cannot add devices!\n"); exit(1); } } // Pick the desired max length. if (CommandLineData->GetMaxPasswordLength()) { maxPasswordLength = CommandLineData->GetMaxPasswordLength(); } else { maxPasswordLength = HashIdentifiers->GetMaxSupportedLength(); } for (i = CommandLineData->GetMinPasswordLength(); i <= maxPasswordLength; i++) { uint64_t NumberOfPasswords; GeneralInformation->setPasswordLength(i); Display->setPasswordLen(i); // Set the status line to indicate where we are. sprintf(printBuffer, "Starting pw len %d", i); Display->addStatusLine(printBuffer); // If no hashes are left, exit. if (HashFile->GetUncrackedHashCount() == 0) { global_interface.exit = 1; strcpy(global_interface.exit_message, "All hashes found! Exiting!\n"); break; } NumberOfPasswords = Charset->getPasswordSpaceSize(i); // Check for errors from charset and break. if (global_interface.exit) { break; } /* // Provide the correct metadata to the workunit class RestoreData = CommandLineData->GetRestoreData(i); RobustWorkunit->SetResumeMetadata(RestoreData); // If we are NOT restoring, create new workunits. if (!CommandLineData->GetUseRestoreFile()) { RobustWorkunit->CreateWorkunits(NumberOfPasswords, WorkunitSize, i); } if (global_interface.exit) { break; } */ Workunit->CreateWorkunits(NumberOfPasswords, WorkunitSize, i); // If there are threads running locally, launch them. if (!CommandLineData->GetIsServerOnly()) { HashClassLauncher.launchThreads(i); } // Wait until all the workunits are completed. This is useful in // server-only mode. while (Workunit->GetNumberOfCompletedWorkunits() < Workunit->GetNumberOfWorkunits()) { CHSleep(1); Display->Refresh(); // Make termination work properly for the server if (global_interface.exit) { // Break from the while loop. break; } } // Break from the password length loop. if (global_interface.exit) { break; } } delete Workunit; delete Display; HashFile->PrintAllFoundHashes(); // If we are outputting unfound hashes, do it now. if (CommandLineData->GetUnfoundOutputFileName().length()) { HashFile->OutputUnfoundHashesToFile(CommandLineData->GetUnfoundOutputFileName()); } }
/** * This function will wait for a server to arrive, do all the setup for the * instance, and will continue until the server disconnects, at which point this * function will return. */ void runNetworkOneConnect() { MFNCommandLineData *CommandLineData; MFNNetworkClient *NetworkClient; MFNHashIdentifiers *HashIdentifiers; MFNGeneralInformation *GeneralInformation; MFNDisplay *Display; MFNHashClassLauncher HashClassLauncher; CommandLineData = MultiforcerGlobalClassFactory.getCommandlinedataClass(); GeneralInformation = MultiforcerGlobalClassFactory.getGeneralInformationClass(); HashIdentifiers = MultiforcerGlobalClassFactory.getHashIdentifiersClass(); // Set up the network client class. This will wait until a connection is // created, or until the user exits. MultiforcerGlobalClassFactory.setNetworkClientPort(CommandLineData->GetNetworkPort()); MultiforcerGlobalClassFactory.setNetworkClientRemoteHost(CommandLineData->GetNetworkRemoteHostname()); MultiforcerGlobalClassFactory.setNetworkClientOneshot(0); NetworkClient = MultiforcerGlobalClassFactory.getNetworkClientClass(); // If the user has requested an exit, we can just terminate now. if (global_interface.user_exit) { exit(0); } // Update the general information structure to continue setup. NetworkClient->updateGeneralInfo(); // Set the hash ID from the server, and continue setting up the system. HashIdentifiers->SetHashId(GeneralInformation->getHashId()); MultiforcerGlobalClassFactory.setCharsetClassType(CH_CHARSET_NEW_CLASS_ID); if (CommandLineData->GetDebug()) { MultiforcerGlobalClassFactory.setDisplayClassType(MFN_DISPLAY_CLASS_DEBUG); } else if (CommandLineData->GetDaemon()) { MultiforcerGlobalClassFactory.setDisplayClassType(MFN_DISPLAY_CLASS_DAEMON); } else { MultiforcerGlobalClassFactory.setDisplayClassType(MFN_DISPLAY_CLASS_CURSES); } MultiforcerGlobalClassFactory.setWorkunitClassType(MFN_WORKUNIT_NETWORK_CLASS_ID); // Set up the hash specific stuff based on the general information. MultiforcerGlobalClassFactory.setHashfileClassType(HashIdentifiers->GetHashData().HashFileIdentifier); HashClassLauncher.setHashType(HashIdentifiers->GetHashData().HashTypeIdentifier); NetworkClient->updateCharset(); // TODO: This should handle non-existent devices cleanly. if (!HashClassLauncher.addAllDevices(CommandLineData->GetDevicesToUse())) { printf("Cannot add devices!\n"); exit(1); } // Display online - no more output! Display = MultiforcerGlobalClassFactory.getDisplayClass(); Display->setHashName(HashIdentifiers->GetHashData().HashDescriptor); // Loop until the server has gone away while (!global_interface.exit) { // Get the password length/etc. NetworkClient->updateGeneralInfo(); MultiforcerGlobalClassFactory.getWorkunitClass()-> setPasswordLength(GeneralInformation->getPasswordLength()); Display->setPasswordLen(GeneralInformation->getPasswordLength()); NetworkClient->updateUncrackedHashes(); // Only run if there are hashes to crack. if (MultiforcerGlobalClassFactory.getHashfileClass()->GetUncrackedHashCount()) { HashClassLauncher.launchThreads(GeneralInformation->getPasswordLength()); } else { // No hashes left - why should we continue to try and run? CHSleep(5); break; } } // Reset for future runs. global_interface.exit = 0; // Out of the main loop - clean up. MultiforcerGlobalClassFactory.destroyCharsetClass(); MultiforcerGlobalClassFactory.destroyHashfileClass(); MultiforcerGlobalClassFactory.destroyNetworkClientClass(); MultiforcerGlobalClassFactory.destroyWorkunitClass(); MultiforcerGlobalClassFactory.destroyDisplayClass(); }
struct MFNWorkunitRobustElement MFNWorkunitNetworkClient::GetNextWorkunit(uint32_t NetworkClientId) { trace_printf("MFNWorkunitNetworkClient::GetNextWorkunit(%u)\n", NetworkClientId); struct MFNWorkunitRobustElement Workunit; this->workunitMutexBoost.lock(); if (this->pendingWorkunits.size() == 0) { network_printf("No workunits - trying to fetch 10.\n"); MultiforcerGlobalClassFactory.getNetworkClientClass()-> fetchWorkunits(MFN_NETWORK_WORKUNIT_NUMBER_WUS_TO_FETCH, this->CurrentPasswordLength); network_printf("pending size: %d\n", this->pendingWorkunits.size()); } // Check to see if there are valid workunits left. if (this->pendingWorkunits.size() == 0) { // If not, return a unit with the specified flags. if (this->DebugOutput) { printf("pendingWorkunits.size() == 0; returning.\n"); } memset(&Workunit, 0, sizeof(MFNWorkunitRobustElement)); // Set the flags specified if needed. if (this->returnWaitWorkunit) { Workunit.Flags = WORKUNIT_DELAY; } else if (this->returnTerminateWorkunit) { Workunit.Flags = WORKUNIT_TERMINATE; } // Otherwise, return a null workunit, which is a term signal too. this->workunitMutexBoost.unlock(); if (this->DebugOutput) { PrintRobustWorkunit(Workunit); } return Workunit; } // We still have workunits left. // Get the next waiting workunit from the main queue. Workunit = this->pendingWorkunits.front(); this->pendingWorkunits.pop_front(); if (this->DebugOutput) { printf("Popped WU ID %lu\n", Workunit.WorkUnitID); } // Set some variables we can make use of. Workunit.IsAssigned = 1; // Add the workunit to the in-flight queue. this->assignedWorkunits.push_back(Workunit); if (this->DebugOutput) { printf("In flight WUs: %lu\n", this->assignedWorkunits.size()); } this->workunitMutexBoost.unlock(); if (this->DebugOutput) { PrintRobustWorkunit(Workunit); } return Workunit; }