ModuleInstance* instantiateModule(const IR::Module& module,ImportBindings&& imports) { ModuleInstance* moduleInstance = new ModuleInstance( std::move(imports.functions), std::move(imports.tables), std::move(imports.memories), std::move(imports.globals) ); // Get disassembly names for the module's objects. DisassemblyNames disassemblyNames; IR::getDisassemblyNames(module,disassemblyNames); // Check the type of the ModuleInstance's imports. errorUnless(moduleInstance->functions.size() == module.functions.imports.size()); for(Uptr importIndex = 0;importIndex < module.functions.imports.size();++importIndex) { errorUnless(isA(moduleInstance->functions[importIndex],module.types[module.functions.imports[importIndex].type.index])); } errorUnless(moduleInstance->tables.size() == module.tables.imports.size()); for(Uptr importIndex = 0;importIndex < module.tables.imports.size();++importIndex) { errorUnless(isA(moduleInstance->tables[importIndex],module.tables.imports[importIndex].type)); } errorUnless(moduleInstance->memories.size() == module.memories.imports.size()); for(Uptr importIndex = 0;importIndex < module.memories.imports.size();++importIndex) { errorUnless(isA(moduleInstance->memories[importIndex],module.memories.imports[importIndex].type)); } errorUnless(moduleInstance->globals.size() == module.globals.imports.size()); for(Uptr importIndex = 0;importIndex < module.globals.imports.size();++importIndex) { errorUnless(isA(moduleInstance->globals[importIndex],module.globals.imports[importIndex].type)); } // Instantiate the module's memory and table definitions. for(const TableDef& tableDef : module.tables.defs) { auto table = createTable(tableDef.type); if(!table) { causeException(Exception::Cause::outOfMemory); } moduleInstance->tables.push_back(table); } for(const MemoryDef& memoryDef : module.memories.defs) { if(!MemoryInstance::theMemoryInstance) { MemoryInstance::theMemoryInstance = createMemory(memoryDef.type); if(!MemoryInstance::theMemoryInstance) { causeException(Exception::Cause::outOfMemory); } } moduleInstance->memories.push_back(MemoryInstance::theMemoryInstance); } // Find the default memory and table for the module. if(moduleInstance->memories.size() != 0) { assert(moduleInstance->memories.size() == 1); moduleInstance->defaultMemory = moduleInstance->memories[0]; } if(moduleInstance->tables.size() != 0) { assert(moduleInstance->tables.size() == 1); moduleInstance->defaultTable = moduleInstance->tables[0]; } // If any memory or table segment doesn't fit, throw an exception before mutating any memory/table. for(auto& tableSegment : module.tableSegments) { TableInstance* table = moduleInstance->tables[tableSegment.tableIndex]; const Value baseOffsetValue = evaluateInitializer(moduleInstance,tableSegment.baseOffset); errorUnless(baseOffsetValue.type == ValueType::i32); const U32 baseOffset = baseOffsetValue.i32; if(baseOffset > table->elements.size() || table->elements.size() - baseOffset < tableSegment.indices.size()) { causeException(Exception::Cause::invalidSegmentOffset); } } //Previously, the module instantiation would write in to the memoryInstance here. Don't do that //since the memoryInstance is shared across all moduleInstances and we could be compiling //a new instance while another instance is running // Instantiate the module's global definitions. for(const GlobalDef& globalDef : module.globals.defs) { const Value initialValue = evaluateInitializer(moduleInstance,globalDef.initializer); errorUnless(initialValue.type == globalDef.type.valueType); moduleInstance->globals.push_back(new GlobalInstance(globalDef.type,initialValue)); } // Create the FunctionInstance objects for the module's function definitions. for(Uptr functionDefIndex = 0;functionDefIndex < module.functions.defs.size();++functionDefIndex) { const Uptr functionIndex = moduleInstance->functions.size(); const DisassemblyNames::Function& functionNames = disassemblyNames.functions[functionIndex]; std::string debugName = functionNames.name; if(!debugName.size()) { debugName = "<function #" + std::to_string(functionDefIndex) + ">"; } auto functionInstance = new FunctionInstance(moduleInstance,module.types[module.functions.defs[functionDefIndex].type.index],nullptr,debugName.c_str()); moduleInstance->functionDefs.push_back(functionInstance); moduleInstance->functions.push_back(functionInstance); } // Generate machine code for the module. LLVMJIT::instantiateModule(module,moduleInstance); // Set up the instance's exports. for(const Export& exportIt : module.exports) { ObjectInstance* exportedObject = nullptr; switch(exportIt.kind) { case ObjectKind::function: exportedObject = moduleInstance->functions[exportIt.index]; break; case ObjectKind::table: exportedObject = moduleInstance->tables[exportIt.index]; break; case ObjectKind::memory: exportedObject = moduleInstance->memories[exportIt.index]; break; case ObjectKind::global: exportedObject = moduleInstance->globals[exportIt.index]; break; default: Errors::unreachable(); } moduleInstance->exportMap[exportIt.name] = exportedObject; } // Copy the module's table segments into the module's default table. for(const TableSegment& tableSegment : module.tableSegments) { TableInstance* table = moduleInstance->tables[tableSegment.tableIndex]; const Value baseOffsetValue = evaluateInitializer(moduleInstance,tableSegment.baseOffset); errorUnless(baseOffsetValue.type == ValueType::i32); const U32 baseOffset = baseOffsetValue.i32; assert(baseOffset + tableSegment.indices.size() <= table->elements.size()); for(Uptr index = 0;index < tableSegment.indices.size();++index) { const Uptr functionIndex = tableSegment.indices[index]; assert(functionIndex < moduleInstance->functions.size()); setTableElement(table,baseOffset + index,moduleInstance->functions[functionIndex]); } } // Call the module's start function. if(module.startFunctionIndex != UINTPTR_MAX) { assert(moduleInstance->functions[module.startFunctionIndex]->type == IR::FunctionType::get()); moduleInstance->startFunctionIndex = module.startFunctionIndex; } moduleInstances.push_back(moduleInstance); return moduleInstance; }
handle<cl_mem> createMemory(cl_mem_flags flags, const VectorType<SCALARTYPE, A> & _buffer) { return createMemory(flags, static_cast<unsigned int>(sizeof(SCALARTYPE) * _buffer.size()), (void*)&_buffer[0]); }
int main(int argc, char *argv[]) { int i, j, m, n, k, pid, total = 0, errorCheck = FALSE; /* 2D integer arrays to point to shared memory block. */ int *matrixA_ptr = NULL, *matrixB_ptr = NULL, *matrixC_ptr = NULL; /* Names of the shared memory objects. */ char *matrixA = "matrixA", *matrixB = "matrixB", *matrixC = "matrixC", *subtotal = "subtotal"; Shared *ptr; /* Error check the number of command line arguements. */ if (argc != 6) { printf("Incorrect number of command line arguements!\n"); errorCheck = TRUE; } /* If there was the correct number of command line arguments then continue with the program. */ if (errorCheck != TRUE) { /* Convert command-line args from string to int. */ m = atoi(argv[3]); n = atoi(argv[4]); k = atoi(argv[5]); if (m < 0 || n < 0 || k < 0) { printf("One or more matrix dimensions are invalid!\n"); return 0; } /* Create shared memory objects. */ matrixA_ptr = (int*)createMemory(matrixA, sizeof(int)*m*n); matrixB_ptr = (int*)createMemory(matrixB, sizeof(int)*n*k); matrixC_ptr = (int*)createMemory(matrixC, sizeof(int)*m*k); ptr = (Shared*)createMemory(subtotal, sizeof(Shared)); /* Read matrix files. */ readMatrix(argv[1], m, n, matrixA_ptr); readMatrix(argv[2], n, k, matrixB_ptr); /* Initialise semaphores. */ sem_init(&ptr->mutex, 1, 1); sem_init(&ptr->empty, 1, 1); sem_init(&ptr->full, 1, 0); /* Kills zombie processes. */ signal(SIGCHLD, SIG_IGN); /* Create m child processes. */ for (i = 0; i < m; i++) { pid = fork(); /*Fork error*/ if (pid < 0) { perror("Fork Failed"); return 0; } /*Do child processing*/ else if (pid == 0) { childProcess(matrixA_ptr, matrixB_ptr, matrixC_ptr, ptr, i, n, k); exit(0); } } /*Parent Process*/ for (j = 0; j < m; j++) { sem_wait(&ptr->full); sem_wait(&ptr->mutex); /*Consume buffer*/ printf("Subtotal produced by process with ID %d: %d\n",ptr->process, ptr->subtotal); total += ptr->subtotal; sem_post(&ptr->mutex); sem_post(&ptr->empty); } printf("Total: %d\n", total); } return 0; }
/** * Load ROM from file. * \param [in] filename ROM filename. * \param [out] memmap Memory map. * \return 1 upon success, 0 if an error occured. */ int loadROM(const char* filename, MemoryMap* memmap) { FILE *in; size_t size; size_t count, nRead; /* Open file */ in = fopen(filename, "rb"); if(NULL == in) { ERROR_MSG("Unable to open %s : %s", filename, strerror(errno)); return 0; } /* Compute file size. */ fseek(in, 0, SEEK_END); size = ftell(in); fseek(in, 0, SEEK_SET); size -= ftell(in); /* Check size */ if(0 == size) { ERROR_MSG("Empty file: %s", filename); goto err_0; } /* Check for possible header */ if(size & 0x200) { /* Jump header */ size &= ~0x200; if(fseek(in, 0x200, SEEK_SET)) { ERROR_MSG("Failed to jump rom header in %s: %s", filename, strerror(errno)); goto err_0; } } /* Allocate rom storage */ if(0 == createMemory(&memmap->rom, (size + 0x1fff) & ~0x1fff)) { ERROR_MSG("Failed to allocate ROM storage : %s", strerror(errno)); goto err_0; } /* Fill rom with 0xff */ memset(memmap->rom.data, 0xff, memmap->rom.len); /* Read ROM data */ count = (size < memmap->rom.len) ? size : memmap->rom.len; nRead = fread(memmap->rom.data, 1, count, in); if(nRead != count) { ERROR_MSG("Failed to read ROM data from %s : %s", filename, strerror(errno)); goto err_1; } fclose(in); /* Initialize ROM pages (from mednafen source code). */ /* Note : the decrement by (i*8192) is a trick to avoid doing a * bitwise with the address when reading a byte from that * page. */ if(0x60000 == memmap->rom.len) { int i; for(i=0; i<64; i++) { memmap->page[i] = &memmap->rom.data[(i & 0x1f) * 8192] - (i*8192); } for(i=64; i<128; i++) { memmap->page[i] = &memmap->rom.data[((i & 0x0f) + 32) * 8192] - (i*8192); } } else if(0x80000 == memmap->rom.len) { int i; for(i=0; i<64; i++) { memmap->page[i] = &memmap->rom.data[(i & 0x3f) * 8192] - (i*8192); } for(i=64; i<128; i++) { memmap->page[i] = &memmap->rom.data[((i & 0x1f) + 32) * 8192] - (i*8192); } } else { int i; for(i=0; i<128; i++) { uint8_t bank = i % (memmap->rom.len / 8192); memmap->page[i] = &memmap->rom.data[bank * 8192] - (i*8192); } } return 1; err_1: destroyMemory(&memmap->rom); err_0: fclose(in); return 0; }