TVMStatus VMMemoryPoolAllocate(TVMMemoryPoolID memory, TVMMemorySize size, void **pointer){ TMachineSignalState sigState; MachineSuspendSignals(&sigState); ThreadStore* tStore = ThreadStore::getInstance(); if((size == 0) || (pointer == NULL)){ printf("VMMemoryPoolAllocate(): size was zero or pointer was null.\n"); MachineResumeSignals(&sigState); return VM_STATUS_ERROR_INVALID_PARAMETER; } // printf("VMMemoryPoolAllocate(): looking for pool: %d\n", memory); MemoryPool *pool = tStore->findMemoryPoolByID(memory); if(pool == NULL){ printf("VMMemoryPoolAllocate(): pool was null.\n"); MachineResumeSignals(&sigState); return VM_STATUS_ERROR_INVALID_PARAMETER; } uint8_t* newMemory = pool->allocateMemory(size); // printf("VMMemoryPoolAllocate(): allocated chunk %d\n", newMemory); if(newMemory == NULL){ printf("VMMemoryPoolAllocate(): new memory allocated was null.\n"); return VM_STATUS_ERROR_INSUFFICIENT_RESOURCES; } // printf("VMMemoryPoolAllocate(): Memory allocated successfully!\n"); *pointer = newMemory; //if execution gets here, everything is valid and MachineResumeSignals(&sigState); //the memory should be allocated return VM_STATUS_SUCCESS; }
TVMStatus VMFileWrite(int fileDescriptor, void* data, int *length){ TMachineSignalState sigState; MachineSuspendSignals(&sigState); //suspend signals so we cannot be pre-empted while scheduling a new thread ThreadStore* tStore = ThreadStore::getInstance(); MemoryPool* sharedMemory = tStore->findMemoryPoolByID((TVMMemoryPoolID)1); TCB* currentThread = tStore->getCurrentThread(); uint8_t* sharedLocation; TVMMemorySize allocSize = *length; //Step 0 - validate data if((data == NULL) || (length == NULL)){ MachineResumeSignals (&sigState); return VM_STATUS_ERROR_INVALID_PARAMETER; } //Step 1 - initialize shared memory location, and wait if memory is not available from share pool if(allocSize > 512){ //make sure thread never asks for > 512 bytes allocSize = 512; } if(allocSize > sharedMemory->getSize()){ allocSize = sharedMemory->getSize(); } sharedLocation = sharedMemory->allocateMemory(allocSize); //allocate a space in the shared memory pool if(sharedLocation == NULL){ // printf("VMFileWrite(): shared location was null\n"); sharedLocation = tStore->waitCurrentThreadOnMemory(allocSize, 1); } //Step 2 - IO loop. If the data to transfer is > 512 bytes, loop. If it isn't, loop only runs once. int bytesLeft = *length; int chunkSize = bytesLeft; void *dataLocation = data; int bytesTransferred = 0; if(bytesLeft > allocSize) chunkSize = allocSize; for(bytesLeft; bytesLeft > 0; bytesLeft -= chunkSize){ if(bytesLeft < chunkSize) chunkSize = bytesLeft; //printf("tid %d outputting\n", tStore->getCurrentThread()->getThreadID()); //copy chunkSize bytes of data from *data into the shared memory location, starting at dataLocation memcpy((void*)sharedLocation, dataLocation, chunkSize*sizeof(uint8_t)); //step 3 - call MachineFileWrite with the pointer to the shared memory location MachineFileWrite(fileDescriptor, sharedLocation, chunkSize, &machineFileIOCallback, (void*)currentThread); tStore->waitCurrentThreadOnIO(); //switch to a new thread while waiting on IO //update bytesLeft and dataLocation for the next iteration bytesTransferred = bytesTransferred + currentThread->getFileIOResult(); dataLocation = ((uint8_t*)dataLocation + chunkSize); } //step 4 - Deallocate the shared memory location, do last error check, and return sharedMemory->deallocate(sharedLocation); if(bytesTransferred < 0){ MachineResumeSignals (&sigState); return VM_STATUS_FAILURE; } MachineResumeSignals (&sigState); return VM_STATUS_SUCCESS; }
TVMStatus VMFileRead(int filedescriptor, void *data, int *length){ TMachineSignalState sigState; MachineSuspendSignals(&sigState); //suspend signals so we cannot be pre-empted while scheduling a new thread ThreadStore* tStore = ThreadStore::getInstance(); MemoryPool* sharedMemory = tStore->findMemoryPoolByID((TVMMemoryPoolID)1); TCB* currentThread = tStore->getCurrentThread(); uint8_t* sharedLocation; TVMMemorySize allocSize = *length; //Step 0 - validation if ((data == NULL) || (length == NULL)){ MachineResumeSignals (&sigState); return VM_STATUS_ERROR_INVALID_PARAMETER; } //Step 1 - initialize shared memory location, and wait if memory is not available from share pool if(allocSize > 512){ //make sure thread never asks for > 512 bytes allocSize = 512; } if(allocSize > sharedMemory->getSize()){ allocSize = sharedMemory->getSize(); } sharedLocation = sharedMemory->allocateMemory(allocSize); //allocate a space in the shared memory pool if(sharedLocation == NULL){ //if there isn't enough room in shared memory to do the IO, the current thread must wait until a chunk //of size allocSize becomes avaliable. waitCurrentThread puts the thread to sleep until that happens, //then returns the amount of shared memory requested. sharedLocation = tStore->waitCurrentThreadOnMemory(allocSize, 1); } //Step 2 - Set up loop int bytesLeft = *length; int chunkSize = bytesLeft; void *dataLocation = data; int bytesTransferred = 0; if(bytesLeft > allocSize) chunkSize = allocSize; for(bytesLeft; bytesLeft > 0; bytesLeft -= chunkSize){ if(bytesLeft < chunkSize) chunkSize = bytesLeft; //read the amount of data specified by chunkSize into the location specified by sharedLocation MachineFileRead(filedescriptor, (void*)sharedLocation, chunkSize, &machineFileIOCallback, (void*)currentThread); tStore->waitCurrentThreadOnIO(); //resume execution here after IO completes //copy chunkSize bytes of data from sharedLocation into dataLocation, starting at sharedLocation memcpy(dataLocation, (void*)sharedLocation, chunkSize*sizeof(uint8_t)); //update bytesLeft and dataLocation for the next iteration bytesTransferred = bytesTransferred + currentThread->getFileIOResult(); dataLocation = ((uint8_t*)dataLocation + chunkSize); } if(currentThread->getFileIOResult() < 0){ //if call to open() failed MachineResumeSignals (&sigState); return VM_STATUS_FAILURE; //return failure state } *length = bytesTransferred; MachineResumeSignals(&sigState); return VM_STATUS_SUCCESS; }