diff options
Diffstat (limited to 'src/VBox/Devices/USB/darwin')
| -rw-r--r-- | src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp | 120 |
1 files changed, 98 insertions, 22 deletions
diff --git a/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp b/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp index 79102d08..e8f1a767 100644 --- a/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp +++ b/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -36,6 +36,7 @@ #include <iprt/assert.h> #include <iprt/critsect.h> +#include <iprt/list.h> #include <iprt/mem.h> #include <iprt/once.h> #include <iprt/string.h> @@ -165,6 +166,13 @@ typedef struct USBPROXYPIPEOSX uint64_t u64NextFrameNo; } USBPROXYPIPEOSX, *PUSBPROXYPIPEOSX, **PPUSBPROXYPIPEOSX; +typedef struct RUNLOOPREFLIST +{ + RTLISTNODE List; + CFRunLoopRef RunLoopRef; +} RUNLOOPREFLIST, *PRUNLOOPREFLIST; +typedef RUNLOOPREFLIST **PPRUNLOOPREFLIST; + /** * Per-interface data for the Darwin usb proxy backend. */ @@ -191,6 +199,7 @@ typedef struct USBPROXYIFOSX CFRunLoopSourceRef RunLoopSrcRef; /** List of isochronous buffer collections. * These are allocated on demand by the URB queuing routine and then recycled until the interface is destroyed. */ + RTLISTANCHOR HeadOfRunLoopLst; PUSBPROXYISOCBUFCOL pIsocBufCols; } USBPROXYIFOSX, *PUSBPROXYIFOSX, **PPUSBPROXYIFOSX; /** Pointer to a pointer to an darwin interface. */ @@ -208,9 +217,9 @@ typedef struct USBPROXYDEVOSX /** The run loop source for the async operations on the device level * (i.e. the default control pipe stuff). */ CFRunLoopSourceRef RunLoopSrcRef; - /** The run loop this device and its interfaces send their events to. */ - CFRunLoopRef RunLoopRef; - + /** we want to add and remove RunLoopSourceRefs to run loop's of + * every EMT thread participated in USB processing. */ + RTLISTANCHOR HeadOfRunLoopLst; /** Pointer to the proxy device instance. */ PUSBPROXYDEV pProxyDev; @@ -255,7 +264,7 @@ static mach_port_t g_MasterPort = NULL; * @param pvUser1 NULL, ignored. * @param pvUser2 NULL, ignored. */ -static DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1, void *pvUser2) +static DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1) { int rc; kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &g_MasterPort); @@ -271,6 +280,65 @@ static DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1, void *pvUser2 return rc; } +/** + * Adds Source ref to current run loop and adds it the list of runloops. + */ +static int usbProxyDarwinAddRunLoopRef(PRTLISTANCHOR pListHead, + CFRunLoopSourceRef SourceRef) +{ + AssertPtrReturn(pListHead, VERR_INVALID_PARAMETER); + AssertReturn(CFRunLoopSourceIsValid(SourceRef), VERR_INVALID_PARAMETER); + + if (CFRunLoopContainsSource(CFRunLoopGetCurrent(), SourceRef, g_pRunLoopMode)) + return VINF_SUCCESS; + + /* Add to the list */ + PRUNLOOPREFLIST pListNode = (PRUNLOOPREFLIST)RTMemAllocZ(sizeof(RUNLOOPREFLIST)); + if (!pListNode) + return VERR_NO_MEMORY; + + pListNode->RunLoopRef = CFRunLoopGetCurrent(); + + CFRetain(pListNode->RunLoopRef); + CFRetain(SourceRef); /* We want to be aware of releasing */ + + CFRunLoopAddSource(pListNode->RunLoopRef, SourceRef, g_pRunLoopMode); + + RTListInit(&pListNode->List); + + RTListAppend((PRTLISTNODE)pListHead, &pListNode->List); + + return VINF_SUCCESS; +} + + +/* + * Removes all source reference from mode of run loop's we've registered them. + * + */ +static int usbProxyDarwinRemoveSourceRefFromAllRunLoops(PRTLISTANCHOR pHead, + CFRunLoopSourceRef SourceRef) +{ + AssertPtrReturn(pHead, VERR_INVALID_PARAMETER); + + while (!RTListIsEmpty(pHead)) + { + PRUNLOOPREFLIST pNode = RTListGetFirst(pHead, RUNLOOPREFLIST, List); + /* XXX: Should Release Reference? */ + Assert(CFGetRetainCount(pNode->RunLoopRef)); + + CFRunLoopRemoveSource(pNode->RunLoopRef, SourceRef, g_pRunLoopMode); + CFRelease(SourceRef); + CFRelease(pNode->RunLoopRef); + + RTListNodeRemove(&pNode->List); + + RTMemFree(pNode); + } + + return VINF_SUCCESS; +} + /** * Allocates a Darwin URB request structure. @@ -616,9 +684,12 @@ static void usbProxyDarwinReleaseAllInterfaces(PUSBPROXYDEVOSX pDevOsX) if (pIf->RunLoopSrcRef) { - CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode); + int rc = usbProxyDarwinRemoveSourceRefFromAllRunLoops((PRTLISTANCHOR)&pIf->HeadOfRunLoopLst, pIf->RunLoopSrcRef); + AssertRC(rc); + CFRelease(pIf->RunLoopSrcRef); pIf->RunLoopSrcRef = NULL; + RTListInit((PRTLISTNODE)&pIf->HeadOfRunLoopLst); } while (pIf->pIsocBufCols) @@ -823,7 +894,9 @@ static int usbProxyDarwinSeizeAllInterfaces(PUSBPROXYDEVOSX pDevOsX, bool fMakeT irc = (*ppIfI)->CreateInterfaceAsyncEventSource(ppIfI, &pIf->RunLoopSrcRef); if (irc == kIOReturnSuccess) { - CFRunLoopAddSource(pDevOsX->RunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode); + RTListInit((PRTLISTNODE)&pIf->HeadOfRunLoopLst); + usbProxyDarwinAddRunLoopRef(&pIf->HeadOfRunLoopLst, + pIf->RunLoopSrcRef); /* * Just link the interface into the list and we're good. @@ -1009,7 +1082,7 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo /* * Init globals once. */ - vrc = RTOnce(&g_usbProxyDarwinOnce, usbProxyDarwinInitOnce, NULL, NULL); + vrc = RTOnce(&g_usbProxyDarwinOnce, usbProxyDarwinInitOnce, NULL); AssertRCReturn(vrc, vrc); /* @@ -1151,14 +1224,13 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)RTMemAllocZ(sizeof(*pDevOsX)); if (pDevOsX) { + RTListInit((PRTLISTNODE)&pDevOsX->HeadOfRunLoopLst); vrc = RTCritSectInit(&pDevOsX->CritSect); if (RT_SUCCESS(vrc)) { pDevOsX->USBDevice = USBDevice; pDevOsX->ppDevI = ppDevI; pDevOsX->pProxyDev = pProxyDev; - pDevOsX->RunLoopRef = CFRunLoopGetCurrent(); - CFRetain(pDevOsX->RunLoopRef); /* paranoia */ /* * Try seize all the interface. @@ -1175,8 +1247,6 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo irc = (*ppDevI)->CreateDeviceAsyncEventSource(ppDevI, &pDevOsX->RunLoopSrcRef); if (irc == kIOReturnSuccess) { - CFRunLoopAddSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode); - /* * Determine the active configuration. * Can cause hangs, so drop it for now. @@ -1191,11 +1261,10 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo pProxyDev->cIgnoreSetConfigs = 1; pProxyDev->Backend.pv = pDevOsX; + usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef); return VINF_SUCCESS; /* return */ } vrc = VERR_VUSB_DEVICE_NOT_ATTACHED; - - CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode); } else vrc = RTErrConvertFromDarwin(irc); @@ -1268,7 +1337,11 @@ static void usbProxyDarwinClose(PUSBPROXYDEV pProxyDev) if (pDevOsX->RunLoopSrcRef) { - CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode); + int rc = usbProxyDarwinRemoveSourceRefFromAllRunLoops(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef); + AssertRC(rc); + + RTListInit((PRTLISTNODE)&pDevOsX->HeadOfRunLoopLst); + CFRelease(pDevOsX->RunLoopSrcRef); pDevOsX->RunLoopSrcRef = NULL; } @@ -1297,12 +1370,6 @@ static void usbProxyDarwinClose(PUSBPROXYDEV pProxyDev) */ RTCritSectDelete(&pDevOsX->CritSect); - if (pDevOsX->RunLoopRef) - { - CFRelease(pDevOsX->RunLoopRef); - pDevOsX->RunLoopRef = NULL; - } - PUSBPROXYURBOSX pUrbOsX; while ((pUrbOsX = pDevOsX->pInFlightHead) != NULL) { @@ -1529,9 +1596,16 @@ static int usbProxyDarwinUrbQueue(PVUSBURB pUrb) pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt, pUrb->cbData)); return false; } + + if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pIf->RunLoopSrcRef, g_pRunLoopMode)) + usbProxyDarwinAddRunLoopRef(&pIf->HeadOfRunLoopLst, pIf->RunLoopSrcRef); + } /* else: pIf == NULL -> default control pipe.*/ + if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevOsX->RunLoopSrcRef, g_pRunLoopMode)) + usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef); + /* * Allocate a Darwin urb. */ @@ -1748,7 +1822,9 @@ static PVUSBURB usbProxyDarwinUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMill } if (pUrb) - LogFlow(("%s: usbProxyDarwinUrbReap: pProxyDev=%s returns %p\n", pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb)); + LogFlowFunc(("LEAVE: %s: pProxyDev=%s returns %p\n", pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb)); + else + LogFlowFunc(("LEAVE: NULL pProxyDev=%s returns NULL", pProxyDev->pUsbIns->pszName)); return pUrb; } |
