RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id) { /* * Validate the input. */ RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc = VERR_POLL_HANDLE_ID_NOT_FOUND; uint32_t i = pThis->cHandles; while (i-- > 0) if (pThis->paHandles[i].id == id) { pThis->cHandles--; size_t const cToMove = pThis->cHandles - i; if (cToMove) { memmove(&pThis->paHandles[i], &pThis->paHandles[i + 1], cToMove * sizeof(pThis->paHandles[i])); memmove(&pThis->paPollFds[i], &pThis->paPollFds[i + 1], cToMove * sizeof(pThis->paPollFds[i])); } rc = VINF_SUCCESS; break; } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle) { /* * Validate the input. */ RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER); AssertPtrNullReturn(pHandle, VERR_INVALID_POINTER); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc = VERR_POLL_HANDLE_ID_NOT_FOUND; uint32_t i = pThis->cHandles; while (i-- > 0) if (pThis->paHandles[i].id == id) { if (pHandle) { pHandle->enmType = pThis->paHandles[i].enmType; pHandle->u = pThis->paHandles[i].u; } rc = VINF_SUCCESS; break; } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
/** Drain the host command queue. */ RTDECL(void) VBoxHGSMIProcessHostQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx) { while (pCtx->pfHostFlags->u32HostFlags & HGSMIHOSTFLAGS_COMMANDS_PENDING) { if (!ASMAtomicCmpXchgBool(&pCtx->fHostCmdProcessing, true, false)) return; hgsmiHostCommandQueryProcess(pCtx); ASMAtomicWriteBool(&pCtx->fHostCmdProcessing, false); } }
RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet) { /* * Validate the input. */ RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, UINT32_MAX); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, UINT32_MAX); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), UINT32_MAX); uint32_t cHandles = pThis->cHandles; ASMAtomicWriteBool(&pThis->fBusy, false); return cHandles; }
RTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet) { RTPOLLSETINTERNAL *pThis = hPollSet; if (pThis == NIL_RTPOLLSET) return VINF_SUCCESS; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC); RTMemFree(pThis->paPollFds); pThis->paPollFds = NULL; RTMemFree(pThis->paHandles); pThis->paHandles = NULL; RTMemFree(pThis); return VINF_SUCCESS; }
RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid) { RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertPtrNull(pfEvents); AssertPtrNull(pid); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid) { RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertPtrNull(pfEvents); AssertPtrNull(pid); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc; if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0) { do rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); while (rc == VERR_INTERRUPTED); } else { uint64_t MsStart = RTTimeMilliTS(); rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); while (RT_UNLIKELY(rc == VERR_INTERRUPTED)) { if (RTTimeMilliTS() - MsStart >= cMillies) { rc = VERR_TIMEOUT; break; } rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); } } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
RTDECL(int) RTPollSetEventsChange(RTPOLLSET hPollSet, uint32_t id, uint32_t fEvents) { /* * Validate the input. */ RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER); AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER); AssertReturn(fEvents, VERR_INVALID_PARAMETER); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc = VERR_POLL_HANDLE_ID_NOT_FOUND; uint32_t i = pThis->cHandles; while (i-- > 0) if (pThis->paHandles[i].id == id) { pThis->paPollFds[i].events = 0; if (fEvents & RTPOLL_EVT_READ) pThis->paPollFds[i].events |= POLLIN; if (fEvents & RTPOLL_EVT_WRITE) pThis->paPollFds[i].events |= POLLOUT; if (fEvents & RTPOLL_EVT_ERROR) pThis->paPollFds[i].events |= POLLERR; rc = VINF_SUCCESS; break; } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
/** * Start this service. */ bool org_virtualbox_VBoxGuest::start(IOService *pProvider) { if (!IOService::start(pProvider)) return false; /* Low level initialization should be performed only once */ if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) { IOService::stop(pProvider); return false; } m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); if (m_pIOPCIDevice) { if (isVmmDev(m_pIOPCIDevice)) { /* Enable memory response from VMM device */ m_pIOPCIDevice->setMemoryEnable(true); m_pIOPCIDevice->setIOEnable(true); IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); if (pMem) { IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */ if((IOPortBasePhys >> 16) == 0) { RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; void *pvMMIOBase = NULL; uint32_t cbMMIO = 0; m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); if (m_pMap) { pvMMIOBase = (void *)m_pMap->getVirtualAddress(); cbMMIO = m_pMap->getLength(); } int rc = VBoxGuestInitDevExt(&g_DevExt, IOPortBase, pvMMIOBase, cbMMIO, #if ARCH_BITS == 64 VBOXOSTYPE_MacOS_x64, #else VBOXOSTYPE_MacOS, #endif 0); if (RT_SUCCESS(rc)) { rc = VbgdDarwinCharDevInit(); if (rc == KMOD_RETURN_SUCCESS) { if (setupVmmDevInterrupts(pProvider)) { /* register the service. */ registerService(); LogRel(("VBoxGuest: IOService started\n")); return true; } LogRel(("VBoxGuest: Failed to set up interrupts\n")); VbgdDarwinCharDevRemove(); } else LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc)); VBoxGuestDeleteDevExt(&g_DevExt); } else LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc)); if (m_pMap) { m_pMap->release(); m_pMap = NULL; } } } else LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); } else
RTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id) { /* * Validate the input (tedious). */ RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER); AssertReturn(fEvents, VERR_INVALID_PARAMETER); AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER); if (!pHandle) return VINF_SUCCESS; AssertPtrReturn(pHandle, VERR_INVALID_POINTER); AssertReturn(pHandle->enmType > RTHANDLETYPE_INVALID && pHandle->enmType < RTHANDLETYPE_END, VERR_INVALID_PARAMETER); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc = VINF_SUCCESS; int fd = -1; switch (pHandle->enmType) { case RTHANDLETYPE_PIPE: if (pHandle->u.hPipe != NIL_RTPIPE) fd = (int)RTPipeToNative(pHandle->u.hPipe); break; case RTHANDLETYPE_SOCKET: if (pHandle->u.hSocket != NIL_RTSOCKET) fd = (int)RTSocketToNative(pHandle->u.hSocket); break; case RTHANDLETYPE_FILE: AssertMsgFailed(("Files are always ready for reading/writing and thus not pollable. Use native APIs for special devices.\n")); rc = VERR_POLL_HANDLE_NOT_POLLABLE; break; case RTHANDLETYPE_THREAD: AssertMsgFailed(("Thread handles are currently not pollable\n")); rc = VERR_POLL_HANDLE_NOT_POLLABLE; break; default: AssertMsgFailed(("\n")); rc = VERR_POLL_HANDLE_NOT_POLLABLE; break; } if (fd != -1) { uint32_t const i = pThis->cHandles; /* Check that the handle ID doesn't exist already. */ uint32_t j = i; while (j-- > 0) if (pThis->paHandles[j].id == id) { rc = VERR_POLL_HANDLE_ID_EXISTS; break; } if (RT_SUCCESS(rc)) { /* Grow the tables if necessary. */ if (i + 1 > pThis->cHandlesAllocated) { uint32_t const c = pThis->cHandlesAllocated + 32; void *pvNew; pvNew = RTMemRealloc(pThis->paHandles, c * sizeof(pThis->paHandles[0])); if (pvNew) { pThis->paHandles = (PRTPOLLSETHNDENT)pvNew; pvNew = RTMemRealloc(pThis->paPollFds, c * sizeof(pThis->paPollFds[0])); if (pvNew) pThis->paPollFds = (struct pollfd *)pvNew; else rc = VERR_NO_MEMORY; } else rc = VERR_NO_MEMORY; } if (RT_SUCCESS(rc)) { /* Add it to the poll file descriptor array and call poll to validate the event flags. */ pThis->paPollFds[i].fd = fd; pThis->paPollFds[i].revents = 0; pThis->paPollFds[i].events = 0; if (fEvents & RTPOLL_EVT_READ) pThis->paPollFds[i].events |= POLLIN; if (fEvents & RTPOLL_EVT_WRITE) pThis->paPollFds[i].events |= POLLOUT; if (fEvents & RTPOLL_EVT_ERROR) pThis->paPollFds[i].events |= POLLERR; if (poll(&pThis->paPollFds[i], 1, 0) >= 0) { /* Add the handle info and close the transaction. */ pThis->paHandles[i].enmType = pHandle->enmType; pThis->paHandles[i].u = pHandle->u; pThis->paHandles[i].id = id; pThis->cHandles = i + 1; rc = VINF_SUCCESS; } else { rc = RTErrConvertFromErrno(errno); pThis->paPollFds[i].fd = -1; } } } } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
/** * Start this service. */ bool org_virtualbox_VBoxVFS::start(IOService *pProvider) { int rc; if (!IOService::start(pProvider)) return false; /* Low level initialization should be performed only once */ if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) { IOService::stop(pProvider); return false; } /* Wait for VBoxGuest to be started */ coreService = waitForCoreService(); if (coreService) { rc = vboxInit(); if (RT_SUCCESS(rc)) { /* Connect to the host service. */ rc = vboxConnect(&g_vboxSFClient); if (RT_SUCCESS(rc)) { PINFO("VBox client connected"); rc = vboxCallSetUtf8(&g_vboxSFClient); if (RT_SUCCESS(rc)) { rc = VBoxVFSRegisterFilesystem(); if (RT_SUCCESS(rc)) { registerService(); PINFO("Successfully started I/O kit class instance"); return true; } PERROR("Unable to register VBoxVFS filesystem"); } else { PERROR("vboxCallSetUtf8 failed: rc=%d", rc); } vboxDisconnect(&g_vboxSFClient); } else { PERROR("Failed to get connection to host: rc=%d", rc); } vboxUninit(); } else { PERROR("Failed to initialize low level library"); } coreService->release(); } else { PERROR("VBoxGuest KEXT not started"); } ASMAtomicXchgBool(&g_fInstantiated, false); IOService::stop(pProvider); return false; }