VirtualBox

Ignore:
Timestamp:
Nov 25, 2018 11:45:15 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
126911
Message:

darwin/VBoxGuest: Kicked out the workloop and alternative interrupt code. bugref:4686

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp

    r75705 r75712  
    129129
    130130protected:
    131 #ifdef USE_INTERRUPT_SOURCE
    132     IOWorkLoop                *m_pWorkLoop;
    133 #else
    134131    /** Non-NULL if interrupts are registered.  Probably same as getProvider(). */
    135132    IOService                 *m_pInterruptProvider;
    136 #endif
    137133
    138134public:
     
    143139    virtual void stop(IOService *pProvider);
    144140    virtual bool terminate(IOOptionBits fOptions);
    145 #ifdef USE_INTERRUPT_SOURCE
    146     IOWorkLoop * getWorkLoop();
    147 #else
    148141    static void  vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc);
    149 
    150 #endif
    151142};
    152143
     
    252243/** The notifier handle for the sleep callback handler. */
    253244static IONotifier          *g_pSleepNotifier = NULL;
    254 
    255 #ifdef USE_INTERRUPT_SOURCE
    256 /* States of atimic variable aimed to protect dynamic object allocation in SMP environment. */
    257 #define VBOXGUEST_OBJECT_UNINITIALIZED  (0)
    258 #define VBOXGUEST_OBJECT_INITIALIZING   (1)
    259 #define VBOXGUEST_OBJECT_INITIALIZED    (2)
    260 #define VBOXGUEST_OBJECT_INVALID        (3)
    261 /** Atomic variable used to protect work loop allocation when multiple threads attempt to obtain it. */
    262 static uint8_t volatile     g_fWorkLoopCreated  = VBOXGUEST_OBJECT_UNINITIALIZED;
    263 #endif
    264245
    265246
     
    827808void org_virtualbox_VBoxGuest::free(void)
    828809{
    829     RTLogBackdoorPrintf("IOService::free([%p])\n", this); /* might got sideways if we use LogFlow() here. weird. */
     810    RTLogBackdoorPrintf("IOService::free([%p])\n", this); /* might go sideways if we use LogFlow() here. weird. */
    830811    IOService::free();
    831812}
     
    10281009}
    10291010
    1030 #ifdef USE_INTERRUPT_SOURCE
    1031 
    1032 /**
    1033  * Lazy initialization of the m_pWorkLoop member.
    1034  *
    1035  * @returns m_pWorkLoop.
    1036  */
    1037 IOWorkLoop *org_virtualbox_VBoxGuest::getWorkLoop()
    1038 {
    1039 /** @todo r=bird: This is actually a classic RTOnce scenario, except it's
    1040  *        tied to a org_virtualbox_VBoxGuest instance.  */
    1041     /*
    1042      * Handle the case when work loop was not created yet.
    1043      */
    1044     if (ASMAtomicCmpXchgU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_INITIALIZING, VBOXGUEST_OBJECT_UNINITIALIZED))
    1045     {
    1046         m_pWorkLoop = IOWorkLoop::workLoop();
    1047         if (m_pWorkLoop)
    1048         {
    1049             /* Notify the rest of threads about the fact that work
    1050              * loop was successully allocated and can be safely used */
    1051             Log(("VBoxGuest: created new work loop\n"));
    1052             ASMAtomicWriteU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_INITIALIZED);
    1053         }
    1054         else
    1055         {
    1056             /* Notify the rest of threads about the fact that there was
    1057              * an error during allocation of a work loop */
    1058             Log(("VBoxGuest: failed to create new work loop!\n"));
    1059             ASMAtomicWriteU8(&g_fWorkLoopCreated, VBOXGUEST_OBJECT_UNINITIALIZED);
    1060         }
    1061     }
    1062     /*
    1063      * Handle the case when work loop is already create or
    1064      * in the process of being.
    1065      */
    1066     else
    1067     {
    1068         uint8_t fWorkLoopCreated = ASMAtomicReadU8(&g_fWorkLoopCreated);
    1069         while (fWorkLoopCreated == VBOXGUEST_OBJECT_INITIALIZING)
    1070         {
    1071             thread_block(0);
    1072             fWorkLoopCreated = ASMAtomicReadU8(&g_fWorkLoopCreated);
    1073         }
    1074         if (fWorkLoopCreated != VBOXGUEST_OBJECT_INITIALIZED)
    1075             Log(("VBoxGuest: No work loop!\n"));
    1076     }
    1077 
    1078     return m_pWorkLoop;
    1079 }
    1080 
    1081 
    1082 /**
    1083  * Perform pending wake ups in work loop context.
    1084  */
    1085 static void vgdrvDarwinDeferredIrqHandler(OSObject *pOwner, IOInterruptEventSource *pSrc, int cInts)
    1086 {
    1087     NOREF(pOwner); NOREF(pSrc); NOREF(cInts);
    1088 
    1089     VGDrvCommonWaitDoWakeUps(&g_DevExt);
    1090 }
    1091 
    1092 
    1093 /**
    1094  * Callback triggered when interrupt occurs.
    1095  */
    1096 static bool vgdrvDarwinDirectIrqHandler(OSObject *pOwner, IOFilterInterruptEventSource *pSrc)
    1097 {
    1098     RT_NOREF(pOwner);
    1099     if (!pSrc)
    1100         return false;
    1101 
    1102     bool fTaken = VGDrvCommonISR(&g_DevExt);
    1103     if (!fTaken) /** @todo r=bird: This looks bogus as we might actually be sharing interrupts with someone. */
    1104         Log(("VGDrvCommonISR error\n"));
    1105 
    1106     return fTaken;
    1107 }
    1108 
    1109 
    1110 bool org_virtualbox_VBoxGuest::setupVmmDevInterrupts(IOService *pProvider)
    1111 {
    1112     IOWorkLoop *pWorkLoop = getWorkLoop();
    1113     if (!pWorkLoop)
    1114         return false;
    1115 
    1116     m_pInterruptSrc = IOFilterInterruptEventSource::filterInterruptEventSource(this,
    1117                                                                                &vgdrvDarwinDeferredIrqHandler,
    1118                                                                                &vgdrvDarwinDirectIrqHandler,
    1119                                                                                pProvider);
    1120     IOReturn rc = pWorkLoop->addEventSource(m_pInterruptSrc);
    1121     if (rc == kIOReturnSuccess)
    1122     {
    1123         m_pInterruptSrc->enable();
    1124         return true;
    1125     }
    1126 
    1127     m_pInterruptSrc->disable();
    1128     m_pInterruptSrc->release();
    1129     m_pInterruptSrc = NULL;
    1130     return false;
    1131 }
    1132 
    1133 
    1134 bool org_virtualbox_VBoxGuest::disableVmmDevInterrupts(void)
    1135 {
    1136     IOWorkLoop *pWorkLoop = (IOWorkLoop *)getWorkLoop();
    1137 
    1138     if (!pWorkLoop)
    1139         return false;
    1140 
    1141     if (!m_pInterruptSrc)
    1142         return false;
    1143 
    1144     m_pInterruptSrc->disable();
    1145     pWorkLoop->removeEventSource(m_pInterruptSrc);
    1146     m_pInterruptSrc->release();
    1147     m_pInterruptSrc = NULL;
    1148 
    1149     return true;
    1150 }
    1151 
    1152 #else  /* !USE_INTERRUPT_SOURCE */
    11531011
    11541012/**
     
    11571015/*static*/ void org_virtualbox_VBoxGuest::vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc)
    11581016{
     1017#ifdef LOG_ENABLED
    11591018    RTLogBackdoorPrintf("vgdrvDarwinIrqHandler: %p %p %p %d\n", pTarget, pvRefCon, pNub, iSrc);
     1019#endif
    11601020    RT_NOREF(pvRefCon, pNub, iSrc);
    11611021
    1162     bool fTaken = VGDrvCommonISR(&g_DevExt);
    1163     if (fTaken)
    1164     {
    1165         RTLogBackdoorPrintf("VBoxGuest: our interrupt!\n");
    1166 # ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP /* Turns out this isn't needed.  Will ditch it later. */
    1167         /*
    1168          * This is essentially what IOFilterInterruptEventSource does, only it
    1169          * disables after the filter returns true and re-enables again after
    1170          * the workloop job has called the handler.
    1171          */
    1172         org_virtualbox_VBoxGuest *pThis = (org_virtualbox_VBoxGuest *)pTarget;
    1173         if (pThis)
    1174         {
    1175             IOService *pProvider = pThis->m_pInterruptProvider;
    1176             if (pProvider)
    1177             {
    1178                 pProvider->disableInterrupt(0);
    1179                 VGDrvCommonWaitDoWakeUps(&g_DevExt); /* Could we perhaps do theses elsewhere? */
    1180                 pProvider->enableInterrupt(0);
    1181                 return;
    1182             }
    1183         }
    1184         VGDrvCommonWaitDoWakeUps(&g_DevExt);
    1185 # endif
    1186     }
     1022    VGDrvCommonISR(&g_DevExt);
     1023    /* There is in fact no way of indicating that this is our interrupt, other
     1024       than making the device lower it.  So, the return code is ignored. */
    11871025}
    11881026
     
    12461084}
    12471085
    1248 #endif /* !USE_INTERRUPT_SOURCE */
    12491086
    12501087/**
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette