Changeset 24703 in vbox for trunk/src/VBox/HostServices/GuestProperties
- Timestamp:
- Nov 16, 2009 3:50:47 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestProperties/service.cpp
r24665 r24703 21 21 */ 22 22 23 /** 23 /** @page pg_svc_guest_properties Guest Property HGCM Service 24 * 24 25 * This HGCM service allows the guest to set and query values in a property 25 26 * store on the host. The service proxies the guest requests to the service … … 39 40 */ 40 41 41 #define LOG_GROUP LOG_GROUP_HGCM42 43 42 /******************************************************************************* 44 43 * Header Files * 45 44 *******************************************************************************/ 45 #define LOG_GROUP LOG_GROUP_HGCM 46 46 #include <VBox/HostServices/GuestPropertySvc.h> 47 47 48 48 #include <VBox/log.h> 49 #include <iprt/asm.h> 50 #include <iprt/assert.h> 51 #include <iprt/autores.h> 52 #include <iprt/cpputils.h> 49 53 #include <iprt/err.h> 50 #include <iprt/assert.h> 54 #include <iprt/mem.h> 55 #include <iprt/req.h> 51 56 #include <iprt/string.h> 52 #include <iprt/mem.h> 53 #include <iprt/autores.h> 57 #include <iprt/thread.h> 54 58 #include <iprt/time.h> 55 #include <iprt/cpputils.h>56 #include <iprt/req.h>57 #include <iprt/thread.h>58 59 59 60 #include <memory> /* for auto_ptr */ … … 163 164 /** Queue of outstanding property change notifications */ 164 165 RTREQQUEUE *mReqQueue; 166 /** Request that we've left pending in a call to flushNotifications. */ 167 PRTREQ mPendingDummyReq; 165 168 /** Thread for processing the request queue */ 166 169 RTTHREAD mReqThread; 167 170 /** Tell the thread that it should exit */ 168 bool mfExitThread;171 bool volatile mfExitThread; 169 172 /** Callback function supplied by the host for notification of updates 170 173 * to properties */ … … 222 225 public: 223 226 explicit Service(PVBOXHGCMSVCHELPERS pHelpers) 224 : mpHelpers(pHelpers), mfExitThread(false), mpfnHostCallback(NULL), 225 mpvHostData(NULL) 227 : mpHelpers(pHelpers) 228 , mPendingDummyReq(NULL) 229 , mfExitThread(false) 230 , mpfnHostCallback(NULL) 231 , mpvHostData(NULL) 226 232 { 227 233 int rc = RTReqCreateQueue(&mReqQueue); … … 321 327 int delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest); 322 328 int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 329 int flushNotifications(uint32_t cMsTimeout); 323 330 int getNotification(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, 324 331 VBOXHGCMSVCPARM paParms[]); … … 350 357 * @copydoc FNRTTHREAD 351 358 */ 359 /* static */ 352 360 DECLCALLBACK(int) Service::reqThreadFn(RTTHREAD ThreadSelf, void *pvUser) 353 361 { … … 819 827 rc = VERR_BUFFER_OVERFLOW; 820 828 } 829 return rc; 830 } 831 832 /** 833 * Flushes the notifications. 834 * 835 * @returns iprt status value 836 * @param cMsTimeout The timeout in milliseconds. 837 * @thread HGCM 838 */ 839 int Service::flushNotifications(uint32_t cMsTimeout) 840 { 841 LogFlowThisFunc(("cMsTimeout=%RU32\n", cMsTimeout)); 842 int rc; 843 844 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD 845 /* 846 * Wait for the thread to finish processing all current requests. 847 */ 848 if (!mPendingDummyReq && !RTReqIsBusy(mReqQueue)) 849 rc = VINF_SUCCESS; 850 else 851 { 852 if (!mPendingDummyReq) 853 rc = RTReqCallEx(mReqQueue, &mPendingDummyReq, 0 /*cMillies*/, RTREQFLAGS_VOID, (PFNRT)reqVoid, 0); 854 else 855 rc = VERR_TIMEOUT; 856 if (rc == VERR_TIMEOUT) 857 rc = RTReqWait(mPendingDummyReq, cMsTimeout); 858 if (RT_SUCCESS(rc)) 859 { 860 RTReqFree(mPendingDummyReq); 861 mPendingDummyReq = NULL; 862 } 863 } 864 #else 865 NOREF(cMsTimeout); 866 rc = VINF_SUCCESS; 867 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */ 868 821 869 return rc; 822 870 } … … 1095 1143 */ 1096 1144 /* static */ 1097 intService::reqNotify(PFNHGCMSVCEXT pfnCallback, void *pvData,1098 char *pszName, char *pszValue, uint32_t u32TimeHigh,1099 uint32_t u32TimeLow, char *pszFlags)1145 DECLCALLBACK(int) Service::reqNotify(PFNHGCMSVCEXT pfnCallback, void *pvData, 1146 char *pszName, char *pszValue, uint32_t u32TimeHigh, 1147 uint32_t u32TimeLow, char *pszFlags) 1100 1148 { 1101 1149 LogFlowFunc (("pfnCallback=%p, pvData=%p, pszName=%p, pszValue=%p, u32TimeHigh=%u, u32TimeLow=%u, pszFlags=%p\n", pfnCallback, pvData, pszName, pszValue, u32TimeHigh, u32TimeLow, pszFlags)); … … 1247 1295 break; 1248 1296 1297 /* The host wishes to flush all pending notification */ 1298 case FLUSH_NOTIFICATIONS_HOST: 1299 LogFlowFunc(("FLUSH_NOTIFICATIONS_HOST\n")); 1300 if (cParms == 1) 1301 { 1302 uint32_t cMsTimeout; 1303 rc = paParms[0].getUInt32(&cMsTimeout); 1304 if (RT_SUCCESS(rc)) 1305 rc = flushNotifications(cMsTimeout); 1306 } 1307 else 1308 rc = VERR_INVALID_PARAMETER; 1309 break; 1310 1249 1311 default: 1250 1312 rc = VERR_NOT_SUPPORTED; … … 1264 1326 { 1265 1327 int rc = VINF_SUCCESS; 1266 unsigned count = 0; 1267 1268 mfExitThread = true; 1328 1329 ASMAtomicWriteBool(&mfExitThread, true); 1330 1269 1331 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD 1332 /* 1333 * Send a dummy request to the thread so it is forced out of the loop and 1334 * notice that the exit flag is set. Give up waiting after 5 mins. 1335 * We call flushNotifications first to try clean up any pending request. 1336 */ 1337 flushNotifications(120*1000); 1338 1270 1339 rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT, (PFNRT)reqVoid, 0); 1271 1340 if (RT_SUCCESS(rc)) 1341 { 1342 unsigned count = 0; 1272 1343 do 1273 1344 { … … 1276 1347 Assert(RT_SUCCESS(rc) || ((VERR_TIMEOUT == rc) && (count != 5))); 1277 1348 } while ((VERR_TIMEOUT == rc) && (count < 300)); 1349 } 1278 1350 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */ 1279 1351 if (RT_SUCCESS(rc))
Note:
See TracChangeset
for help on using the changeset viewer.