VirtualBox

Changeset 27781 in vbox


Ignore:
Timestamp:
Mar 29, 2010 11:52:20 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59430
Message:

HostServices/GuestProperties: get rid of the notification thread (see XTracker #3201 comment 91)

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestPropertySvc.h

    r25647 r27781  
    251251     * Takes one 32-bit unsigned integer parameter for the flags.
    252252     */
    253     SET_GLOBAL_FLAGS_HOST = 7,
    254 
    255     /**
    256      * Flush notifications.
    257      * Takes one 32-bit unsigned integer parameter that gives the number of
    258      * milliseconds to wait for the worker thread to get the work done.
    259      */
    260     FLUSH_NOTIFICATIONS_HOST
     253    SET_GLOBAL_FLAGS_HOST = 7
    261254};
    262255
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r26749 r27781  
    163163    CallList mGuestWaiters;
    164164    /** @todo we should have classes for thread and request handler thread */
    165     /** Queue of outstanding property change notifications */
    166     RTREQQUEUE *mReqQueue;
    167     /** Request that we've left pending in a call to flushNotifications. */
    168     PRTREQ mPendingDummyReq;
    169     /** Thread for processing the request queue */
    170     RTTHREAD mReqThread;
    171     /** Tell the thread that it should exit */
    172     bool volatile mfExitThread;
    173165    /** Callback function supplied by the host for notification of updates
    174166     * to properties */
     
    249241        : mpHelpers(pHelpers)
    250242        , meGlobalFlags(NILFLAG)
    251         , mPendingDummyReq(NULL)
    252         , mfExitThread(false)
    253243        , mpfnHostCallback(NULL)
    254244        , mpvHostData(NULL)
    255     {
    256         int rc = RTReqCreateQueue(&mReqQueue);
    257 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
    258         if (RT_SUCCESS(rc))
    259             rc = RTThreadCreate(&mReqThread, reqThreadFn, this, 0,
    260                                 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
    261                                 "GuestPropReq");
    262 #endif
    263         if (RT_FAILURE(rc))
    264             throw rc;
    265     }
     245    { }
    266246
    267247    /**
     
    350330    int delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest);
    351331    int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    352     int flushNotifications(uint32_t cMsTimeout);
    353332    int getNotification(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms,
    354333                        VBOXHGCMSVCPARM paParms[]);
     
    357336    int getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop);
    358337    void doNotifications(const char *pszProperty, uint64_t u64Timestamp);
    359     static DECLCALLBACK(int) reqNotify(PFNHGCMSVCEXT pfnCallback,
    360                                        void *pvData, char *pszName,
    361                                        char *pszValue, uint32_t u32TimeHigh,
    362                                        uint32_t u32TimeLow, char *pszFlags);
    363     /**
    364      * Empty request function for terminating the request thread.
    365      * @returns VINF_EOF to cause the request processing function to return
    366      * @todo    return something more appropriate
    367      */
    368     static DECLCALLBACK(int) reqVoid() { return VINF_EOF; }
     338    int notifyHost(const char *pszName, const char *pszValue,
     339                   uint64_t u64Timestamp, const char *pszFlags);
    369340
    370341    void call (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
     
    374345    int uninit ();
    375346};
    376 
    377 
    378 /**
    379  * Thread function for processing the request queue
    380  * @copydoc FNRTTHREAD
    381  */
    382 /* static */
    383 DECLCALLBACK(int) Service::reqThreadFn(RTTHREAD ThreadSelf, void *pvUser)
    384 {
    385     SELF *pSelf = reinterpret_cast<SELF *>(pvUser);
    386     while (!pSelf->mfExitThread)
    387         RTReqProcess(pSelf->mReqQueue, RT_INDEFINITE_WAIT);
    388     return VINF_SUCCESS;
    389 }
    390347
    391348
     
    849806}
    850807
    851 /**
    852  * Flushes the notifications.
    853  *
    854  * @returns iprt status value
    855  * @param   cMsTimeout  The timeout in milliseconds.
    856  * @thread  HGCM
    857  */
    858 int Service::flushNotifications(uint32_t cMsTimeout)
    859 {
    860     LogFlowThisFunc(("cMsTimeout=%RU32\n", cMsTimeout));
    861     int rc;
    862 
    863 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
    864     /*
    865      * Wait for the thread to finish processing all current requests.
    866      */
    867     if (!mPendingDummyReq && !RTReqIsBusy(mReqQueue))
    868         rc = VINF_SUCCESS;
    869     else
    870     {
    871         if (!mPendingDummyReq)
    872             rc = RTReqCallEx(mReqQueue, &mPendingDummyReq, 0 /*cMillies*/, RTREQFLAGS_VOID, (PFNRT)reqVoid, 0);
    873         else
    874             rc = VERR_TIMEOUT;
    875         if (rc == VERR_TIMEOUT)
    876             rc = RTReqWait(mPendingDummyReq, cMsTimeout);
    877         if (RT_SUCCESS(rc))
    878         {
    879             RTReqFree(mPendingDummyReq);
    880             mPendingDummyReq = NULL;
    881         }
    882     }
    883 #else
    884     NOREF(cMsTimeout);
    885     rc = VINF_SUCCESS;
    886 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    887 
    888     return rc;
    889 }
    890808
    891809/** Helper query used by getOldNotification */
     
    919837}
    920838
     839
    921840/** Helper query used by getNotification */
    922841int Service::getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop)
     
    957876}
    958877
     878
    959879/**
    960880 * Get the next guest notification.
     
    1015935}
    1016936
     937
    1017938/**
    1018939 * Notify the service owner and the guest that a property has been
     
    1020941 * @param pszProperty  the name of the property which has changed
    1021942 * @param u64Timestamp the time at which the change took place
    1022  * @note this call allocates memory which the reqNotify request is expected to
    1023  *       free again, using RTStrFree().
    1024943 *
    1025944 * @thread  HGCM service
     
    10911010        mGuestNotifications.pop_front();
    10921011
    1093 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
    10941012    /*
    10951013     * Host notifications - first case: if the property exists then send its
    10961014     * current value
    10971015     */
    1098     char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;
    1099 
    11001016    if (found && mpfnHostCallback != NULL)
    11011017    {
    11021018        char szFlags[MAX_FLAGS_LEN];
    11031019        /* Send out a host notification */
    1104         rc = writeFlags(prop.mFlags, szFlags);
     1020        const char *pszValue = prop.mValue.c_str();
    11051021        if (RT_SUCCESS(rc))
    1106             rc = RTStrDupEx(&pszName, pszProperty);
     1022            rc = writeFlags(prop.mFlags, szFlags);
    11071023        if (RT_SUCCESS(rc))
    1108             rc = RTStrDupEx(&pszValue, prop.mValue.c_str());
    1109         if (RT_SUCCESS(rc))
    1110             rc = RTStrDupEx(&pszFlags, szFlags);
    1111         if (RT_SUCCESS(rc))
    1112         {
    1113             LogFlowThisFunc (("pszName=%p (%s)\n", pszName, pszName));
    1114             LogFlowThisFunc (("pszValue=%p (%s)\n", pszValue, pszValue));
    1115             LogFlowThisFunc (("pszFlags=%p (%s)\n", pszFlags, pszFlags));
    1116             rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT,
    1117                              (PFNRT)Service::reqNotify, 7, mpfnHostCallback,
    1118                              mpvHostData, pszName, pszValue,
    1119                              (uint32_t) RT_HIDWORD(u64Timestamp),
    1120                              (uint32_t) RT_LODWORD(u64Timestamp), pszFlags);
    1121         }
     1024            rc = notifyHost(pszProperty, pszValue, u64Timestamp, szFlags);
    11221025    }
    11231026
     
    11291032    {
    11301033        /* Send out a host notification */
    1131         rc = RTStrDupEx(&pszName, pszProperty);
    11321034        if (RT_SUCCESS(rc))
    1133         {
    1134             LogFlowThisFunc (("pszName=%p (%s)\n", pszName, pszName));
    1135             rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT,
    1136                              (PFNRT)Service::reqNotify, 7, mpfnHostCallback,
    1137                              mpvHostData, pszName, (uintptr_t) NULL,
    1138                              (uint32_t) RT_HIDWORD(u64Timestamp),
    1139                              (uint32_t) RT_LODWORD(u64Timestamp),
    1140                              (uintptr_t) NULL);
    1141        }
    1142     }
    1143     if (RT_FAILURE(rc)) /* clean up if we failed somewhere */
    1144     {
    1145         LogThisFunc (("Failed, freeing allocated strings.\n"));
    1146         RTStrFree(pszName);
    1147         RTStrFree(pszValue);
    1148         RTStrFree(pszFlags);
     1035            rc = notifyHost(pszProperty, NULL, u64Timestamp, NULL);
    11491036    }
    11501037    LogFlowThisFunc (("returning\n"));
    1151 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    11521038}
    11531039
    11541040/**
    11551041 * Notify the service owner that a property has been added/deleted/changed.
    1156  * asynchronous part.
    1157  * @param pszProperty the name of the property which has changed
    1158  * @note this call allocates memory which the reqNotify request is expected to
    1159  *       free again, using RTStrFree().
    1160  *
    1161  * @thread  request thread
    1162  */
    1163 /* static */
    1164 DECLCALLBACK(int) Service::reqNotify(PFNHGCMSVCEXT pfnCallback, void *pvData,
    1165                                      char *pszName, char *pszValue, uint32_t u32TimeHigh,
    1166                                      uint32_t u32TimeLow, char *pszFlags)
    1167 {
    1168     LogFlowFunc (("pfnCallback=%p, pvData=%p, pszName=%p, pszValue=%p, u32TimeHigh=%u, u32TimeLow=%u, pszFlags=%p\n", pfnCallback, pvData, pszName, pszValue, u32TimeHigh, u32TimeLow, pszFlags));
    1169     LogFlowFunc (("pszName=%s\n", pszName));
    1170     LogFlowFunc (("pszValue=%s\n", pszValue));
    1171     LogFlowFunc (("pszFlags=%s\n", pszFlags));
    1172     /* LogFlowFunc (("pfnCallback=%p, pvData=%p, pszName=%s, pszValue=%s, u32TimeHigh=%u, u32TimeLow=%u, pszFlags=%s\n", pfnCallback, pvData, pszName, pszValue, u32TimeHigh, u32TimeLow, pszFlags)); */
     1042 * @returns  IPRT status value
     1043 * @param    pszName       the property name
     1044 * @param    pszValue      the new value, or NULL if the property was deleted
     1045 * @param    u64Timestamp  the time of the change
     1046 * @param    pszFlags      the new flags string
     1047 */
     1048int Service::notifyHost(const char *pszName, const char *pszValue,
     1049                        uint64_t u64Timestamp, const char *pszFlags)
     1050{
     1051    LogFlowFunc (("pszName=%s, pszValue=%s, u64Timestamp=%llu, pszFlags=%s\n",
     1052                  pszName, pszValue, u64Timestamp, pszFlags));
    11731053    HOSTCALLBACKDATA HostCallbackData;
    11741054    HostCallbackData.u32Magic     = HOSTCALLBACKMAGIC;
    11751055    HostCallbackData.pcszName     = pszName;
    11761056    HostCallbackData.pcszValue    = pszValue;
    1177     HostCallbackData.u64Timestamp = RT_MAKE_U64(u32TimeLow, u32TimeHigh);
     1057    HostCallbackData.u64Timestamp = u64Timestamp;
    11781058    HostCallbackData.pcszFlags    = pszFlags;
    1179     int rc = pfnCallback(pvData, 0 /*u32Function*/, (void *)(&HostCallbackData),
    1180                          sizeof(HostCallbackData));
    1181     AssertRC(rc);
    1182     LogFlowFunc (("Freeing strings\n"));
    1183     RTStrFree(pszName);
    1184     RTStrFree(pszValue);
    1185     RTStrFree(pszFlags);
    1186     LogFlowFunc (("returning success\n"));
    1187     return VINF_SUCCESS;
     1059    int rc = mpfnHostCallback (mpvHostData, 0 /*u32Function*/,
     1060                           (void *)(&HostCallbackData),
     1061                           sizeof(HostCallbackData));
     1062    LogFlowFunc (("returning %Rrc\n", rc));
     1063    return rc;
    11881064}
    11891065
     
    13281204                break;
    13291205
    1330             /* The host wishes to flush all pending notification */
    1331             case FLUSH_NOTIFICATIONS_HOST:
    1332                 LogFlowFunc(("FLUSH_NOTIFICATIONS_HOST\n"));
    1333                 if (cParms == 1)
    1334                 {
    1335                     uint32_t cMsTimeout;
    1336                     rc = paParms[0].getUInt32(&cMsTimeout);
    1337                     if (RT_SUCCESS(rc))
    1338                         rc = flushNotifications(cMsTimeout);
    1339                 }
    1340                 else
    1341                     rc = VERR_INVALID_PARAMETER;
    1342                 break;
    1343 
    13441206            default:
    13451207                rc = VERR_NOT_SUPPORTED;
     
    13581220int Service::uninit()
    13591221{
    1360     int rc = VINF_SUCCESS;
    1361 
    1362     ASMAtomicWriteBool(&mfExitThread, true);
    1363 
    1364 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
    1365     /*
    1366      * Send a dummy request to the thread so it is forced out of the loop and
    1367      * notice that the exit flag is set.  Give up waiting after 5 mins.
    1368      * We call flushNotifications first to try clean up any pending request.
    1369      */
    1370     flushNotifications(120*1000);
    1371 
    1372     rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT, (PFNRT)reqVoid, 0);
    1373     if (RT_SUCCESS(rc))
    1374     {
    1375         unsigned count = 0;
    1376         do
    1377         {
    1378             rc = RTThreadWait(mReqThread, 1000, NULL);
    1379             ++count;
    1380             Assert(RT_SUCCESS(rc) || ((VERR_TIMEOUT == rc) && (count != 5)));
    1381         } while ((VERR_TIMEOUT == rc) && (count < 300));
    1382     }
    1383 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    1384     if (RT_SUCCESS(rc))
    1385         RTReqDestroyQueue(mReqQueue);
    1386     return rc;
     1222    return VINF_SUCCESS;
    13871223}
    13881224
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