Changeset 75712 in vbox for trunk/src/VBox/Additions/common/VBoxGuest
- Timestamp:
- Nov 25, 2018 11:45:15 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 126911
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp
r75705 r75712 129 129 130 130 protected: 131 #ifdef USE_INTERRUPT_SOURCE132 IOWorkLoop *m_pWorkLoop;133 #else134 131 /** Non-NULL if interrupts are registered. Probably same as getProvider(). */ 135 132 IOService *m_pInterruptProvider; 136 #endif137 133 138 134 public: … … 143 139 virtual void stop(IOService *pProvider); 144 140 virtual bool terminate(IOOptionBits fOptions); 145 #ifdef USE_INTERRUPT_SOURCE146 IOWorkLoop * getWorkLoop();147 #else148 141 static void vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc); 149 150 #endif151 142 }; 152 143 … … 252 243 /** The notifier handle for the sleep callback handler. */ 253 244 static IONotifier *g_pSleepNotifier = NULL; 254 255 #ifdef USE_INTERRUPT_SOURCE256 /* 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 #endif264 245 265 246 … … 827 808 void org_virtualbox_VBoxGuest::free(void) 828 809 { 829 RTLogBackdoorPrintf("IOService::free([%p])\n", this); /* might go tsideways if we use LogFlow() here. weird. */810 RTLogBackdoorPrintf("IOService::free([%p])\n", this); /* might go sideways if we use LogFlow() here. weird. */ 830 811 IOService::free(); 831 812 } … … 1028 1009 } 1029 1010 1030 #ifdef USE_INTERRUPT_SOURCE1031 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's1040 * 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 work1050 * 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 else1055 {1056 /* Notify the rest of threads about the fact that there was1057 * 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 or1064 * in the process of being.1065 */1066 else1067 {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 */1153 1011 1154 1012 /** … … 1157 1015 /*static*/ void org_virtualbox_VBoxGuest::vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc) 1158 1016 { 1017 #ifdef LOG_ENABLED 1159 1018 RTLogBackdoorPrintf("vgdrvDarwinIrqHandler: %p %p %p %d\n", pTarget, pvRefCon, pNub, iSrc); 1019 #endif 1160 1020 RT_NOREF(pvRefCon, pNub, iSrc); 1161 1021 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. */ 1187 1025 } 1188 1026 … … 1246 1084 } 1247 1085 1248 #endif /* !USE_INTERRUPT_SOURCE */1249 1086 1250 1087 /**
Note:
See TracChangeset
for help on using the changeset viewer.