int VDIoBackendMemCreate(PPVDIOBACKENDMEM ppIoBackend) { int rc = VINF_SUCCESS; PVDIOBACKENDMEM pIoBackend = NULL; pIoBackend = (PVDIOBACKENDMEM)RTMemAllocZ(sizeof(VDIOBACKENDMEM)); if (pIoBackend) { rc = RTCircBufCreate(&pIoBackend->pRequestRing, VDMEMIOBACKEND_REQS * sizeof(PVDIOBACKENDREQ)); if (RT_SUCCESS(rc)) { pIoBackend->cReqsRing = VDMEMIOBACKEND_REQS * sizeof(VDIOBACKENDREQ); pIoBackend->fRunning = true; rc = RTSemEventCreate(&pIoBackend->EventSem); if (RT_SUCCESS(rc)) { rc = RTThreadCreate(&pIoBackend->hThreadIo, vdIoBackendMemThread, pIoBackend, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "MemIo"); if (RT_SUCCESS(rc)) { *ppIoBackend = pIoBackend; LogFlowFunc(("returns success\n")); return VINF_SUCCESS; } RTSemEventDestroy(pIoBackend->EventSem); } RTCircBufDestroy(pIoBackend->pRequestRing); } RTMemFree(pIoBackend); } else rc = VERR_NO_MEMORY; return rc; }
/** * Basic API checks. */ static void tst1(void) { void *pvBuf; size_t cbSize; char pcTestPattern1[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9 }; char pcTestPattern2[] = { 0x8, 0x9, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9 }; char pcTestPattern3[] = { 0x5, 0x6, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }; /* Create */ RTTestISub("Creation"); PRTCIRCBUF pBuf; RTTESTI_CHECK_RC(RTCircBufCreate(&pBuf, 10), VINF_SUCCESS); RTTESTI_CHECK(RTCircBufFree(pBuf) == 10); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 0); /* Full write */ RTTestISub("Full write"); RTCircBufAcquireWriteBlock(pBuf, 10, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 10); memcpy(pvBuf, pcTestPattern1, 10); RTCircBufReleaseWriteBlock(pBuf, 10); RTTESTI_CHECK(RTCircBufFree(pBuf) == 0); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 10); // RTTESTI_CHECK(memcmp(pBuf->pvBuf, pcTestPattern1, 10) == 0); /* Check the internal state */ /* Half read */ RTTestISub("Half read"); RTCircBufAcquireReadBlock(pBuf, 5, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 5); RTTESTI_CHECK(memcmp(pvBuf, pcTestPattern1, 5) == 0); RTCircBufReleaseReadBlock(pBuf, 5); RTTESTI_CHECK(RTCircBufFree(pBuf) == 5); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 5); /* Sub write */ RTTestISub("Sub write"); RTCircBufAcquireWriteBlock(pBuf, 2, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 2); memcpy(pvBuf, &pcTestPattern1[8], 2); RTCircBufReleaseWriteBlock(pBuf, 2); RTTESTI_CHECK(RTCircBufFree(pBuf) == 3); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 7); // RTTESTI_CHECK(memcmp(pBuf->pvBuf, pcTestPattern2, 10) == 0); /* Check the internal state */ /* Split tests */ /* Split read */ RTTestISub("Split read"); RTCircBufAcquireReadBlock(pBuf, 7, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 5); RTTESTI_CHECK(memcmp(pvBuf, &pcTestPattern1[5], 5) == 0); RTCircBufReleaseReadBlock(pBuf, 5); RTTESTI_CHECK(RTCircBufFree(pBuf) == 8); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 2); RTCircBufAcquireReadBlock(pBuf, 2, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 2); RTTESTI_CHECK(memcmp(pvBuf, &pcTestPattern1[8], 2) == 0); RTCircBufReleaseReadBlock(pBuf, 2); RTTESTI_CHECK(RTCircBufFree(pBuf) == 10); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 0); /* Split write */ RTTestISub("Split write"); RTCircBufAcquireWriteBlock(pBuf, 10, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 8); memcpy(pvBuf, pcTestPattern1, 8); RTCircBufReleaseWriteBlock(pBuf, 8); RTTESTI_CHECK(RTCircBufFree(pBuf) == 2); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 8); RTCircBufAcquireWriteBlock(pBuf, 2, &pvBuf, &cbSize); RTTESTI_CHECK(cbSize == 2); memcpy(pvBuf, &pcTestPattern1[5], 2); RTCircBufReleaseWriteBlock(pBuf, 2); RTTESTI_CHECK(RTCircBufFree(pBuf) == 0); RTTESTI_CHECK(RTCircBufUsed(pBuf) == 10); // RTTESTI_CHECK(memcmp(pBuf->pvBuf, pcTestPattern3, 10) == 0); /* Check the internal state */ /* Destroy */ RTCircBufDestroy(pBuf); }
static int shaOpenCallback(void *pvUser, const char *pszLocation, uint32_t fOpen, PFNVDCOMPLETED pfnCompleted, void **ppInt) { /* Validate input. */ AssertPtrReturn(pvUser, VERR_INVALID_PARAMETER); AssertPtrReturn(pszLocation, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnCompleted, VERR_INVALID_PARAMETER); AssertPtrReturn(ppInt, VERR_INVALID_POINTER); AssertReturn((fOpen & RTFILE_O_READWRITE) != RTFILE_O_READWRITE, VERR_INVALID_PARAMETER); /* No read/write allowed */ PSHASTORAGE pShaStorage = (PSHASTORAGE)pvUser; PVDINTERFACEIO pIfIo = VDIfIoGet(pShaStorage->pVDImageIfaces); AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); DEBUG_PRINT_FLOW(); PSHASTORAGEINTERNAL pInt = (PSHASTORAGEINTERNAL)RTMemAllocZ(sizeof(SHASTORAGEINTERNAL)); if (!pInt) return VERR_NO_MEMORY; int rc = VINF_SUCCESS; do { pInt->pfnCompleted = pfnCompleted; pInt->pShaStorage = pShaStorage; pInt->fEOF = false; pInt->fOpenMode = fOpen; pInt->u32Status = STATUS_WAIT; /* Circular buffer in the read case. */ rc = RTCircBufCreate(&pInt->pCircBuf, _1M * 2); if (RT_FAILURE(rc)) break; if (fOpen & RTFILE_O_WRITE) { /* The zero buffer is used for appending empty parts at the end of the * file (or our buffer) in setSize or when uOffset in writeSync is * increased in steps bigger than a byte. */ pInt->cbZeroBuf = _1K; pInt->pvZeroBuf = RTMemAllocZ(pInt->cbZeroBuf); if (!pInt->pvZeroBuf) { rc = VERR_NO_MEMORY; break; } } /* Create an event semaphore to indicate a state change for the worker * thread. */ rc = RTSemEventCreate(&pInt->newStatusEvent); if (RT_FAILURE(rc)) break; /* Create an event semaphore to indicate a finished calculation of the worker thread. */ rc = RTSemEventCreate(&pInt->workFinishedEvent); if (RT_FAILURE(rc)) break; /* Create the worker thread. */ rc = RTThreadCreate(&pInt->pWorkerThread, shaCalcWorkerThread, pInt, 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, RTTHREADFLAGS_WAITABLE, "SHA-Worker"); if (RT_FAILURE(rc)) break; if (pShaStorage->fCreateDigest) { /* Create a SHA1/SHA256 context the worker thread will work with. */ if (pShaStorage->fSha256) RTSha256Init(&pInt->ctx.Sha256); else RTSha1Init(&pInt->ctx.Sha1); } /* Open the file. */ rc = vdIfIoFileOpen(pIfIo, pszLocation, fOpen, pInt->pfnCompleted, &pInt->pvStorage); if (RT_FAILURE(rc)) break; if (fOpen & RTFILE_O_READ) { /* Immediately let the worker thread start the reading. */ rc = shaSignalManifestThread(pInt, STATUS_READ); } } while(0); if (RT_FAILURE(rc)) { if (pInt->pWorkerThread) { shaSignalManifestThread(pInt, STATUS_END); RTThreadWait(pInt->pWorkerThread, RT_INDEFINITE_WAIT, 0); } if (pInt->workFinishedEvent) RTSemEventDestroy(pInt->workFinishedEvent); if (pInt->newStatusEvent) RTSemEventDestroy(pInt->newStatusEvent); if (pInt->pCircBuf) RTCircBufDestroy(pInt->pCircBuf); if (pInt->pvZeroBuf) RTMemFree(pInt->pvZeroBuf); RTMemFree(pInt); } else *ppInt = pInt; return rc; }