VirtualBox

Changeset 57766 in vbox for trunk/src


Ignore:
Timestamp:
Sep 15, 2015 3:37:33 PM (9 years ago)
Author:
vboxsync
Message:

HostServices/GuestProperties: asynch host notifications.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r57358 r57766  
    5858#include <string>
    5959#include <list>
     60
     61/** @todo Delete the old !ASYNC_HOST_NOTIFY code and remove this define. */
     62#define ASYNC_HOST_NOTIFY
    6063
    6164namespace guestProp {
     
    287290        , mPrevTimestamp(0)
    288291        , mcTimestampAdjustments(0)
     292#ifdef ASYNC_HOST_NOTIFY
     293        , mhThreadNotifyHost(NIL_RTTHREAD)
     294        , mhReqQNotifyHost(NIL_RTREQQUEUE)
     295#endif
    289296    { }
    290297
     
    365372        return VINF_SUCCESS;
    366373    }
     374
     375#ifdef ASYNC_HOST_NOTIFY
     376    int initialize();
     377#endif
    367378
    368379private:
     
    392403    void dbgInfoShow(PCDBGFINFOHLP pHlp);
    393404    static DECLCALLBACK(void) dbgInfo(void *pvUser, PCDBGFINFOHLP pHlp, const char *pszArgs);
     405
     406#ifdef ASYNC_HOST_NOTIFY
     407    /* Thread for handling host notifications. */
     408    RTTHREAD mhThreadNotifyHost;
     409    /* Queue for handling requests for notifications. */
     410    RTREQQUEUE mhReqQNotifyHost;
     411    static DECLCALLBACK(int) threadNotifyHost(RTTHREAD self, void *pvUser);
     412#endif
    394413};
    395414
     
    12081227}
    12091228
     1229#ifdef ASYNC_HOST_NOTIFY
     1230static DECLCALLBACK(void) notifyHostAsyncWorker(PFNHGCMSVCEXT pfnHostCallback,
     1231                                                void *pvHostData,
     1232                                                HOSTCALLBACKDATA *pHostCallbackData)
     1233{
     1234    pfnHostCallback(pvHostData, 0 /*u32Function*/,
     1235                   (void *)pHostCallbackData,
     1236                   sizeof(HOSTCALLBACKDATA));
     1237    RTMemFree(pHostCallbackData);
     1238}
     1239#endif
     1240
    12101241/**
    12111242 * Notify the service owner that a property has been added/deleted/changed.
     
    12211252    LogFlowFunc(("pszName=%s, pszValue=%s, u64Timestamp=%llu, pszFlags=%s\n",
    12221253                 pszName, pszValue, u64Timestamp, pszFlags));
     1254#ifdef ASYNC_HOST_NOTIFY
     1255    int rc = VINF_SUCCESS;
     1256
     1257    /* Allocate buffer for the callback data and strings. */
     1258    size_t cbName = pszName? strlen(pszName): 0;
     1259    size_t cbValue = pszValue? strlen(pszValue): 0;
     1260    size_t cbFlags = pszFlags? strlen(pszFlags): 0;
     1261    size_t cbAlloc = sizeof(HOSTCALLBACKDATA) + cbName + cbValue + cbFlags + 3;
     1262    HOSTCALLBACKDATA *pHostCallbackData = (HOSTCALLBACKDATA *)RTMemAlloc(cbAlloc);
     1263    if (pHostCallbackData)
     1264    {
     1265        uint8_t *pu8 = (uint8_t *)pHostCallbackData;
     1266        pu8 += sizeof(HOSTCALLBACKDATA);
     1267
     1268        pHostCallbackData->u32Magic     = HOSTCALLBACKMAGIC;
     1269
     1270        pHostCallbackData->pcszName     = (const char *)pu8;
     1271        memcpy(pu8, pszName, cbName);
     1272        pu8 += cbName;
     1273        *pu8++ = 0;
     1274
     1275        pHostCallbackData->pcszValue    = (const char *)pu8;
     1276        memcpy(pu8, pszValue, cbValue);
     1277        pu8 += cbValue;
     1278        *pu8++ = 0;
     1279
     1280        pHostCallbackData->u64Timestamp = u64Timestamp;
     1281
     1282        pHostCallbackData->pcszFlags    = (const char *)pu8;
     1283        memcpy(pu8, pszFlags, cbFlags);
     1284        pu8 += cbFlags;
     1285        *pu8++ = 0;
     1286
     1287        rc = RTReqQueueCallEx(mhReqQNotifyHost, NULL, 0, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     1288                              (PFNRT)notifyHostAsyncWorker, 3,
     1289                              mpfnHostCallback, mpvHostData, pHostCallbackData);
     1290        if (RT_FAILURE(rc))
     1291        {
     1292            RTMemFree(pHostCallbackData);
     1293        }
     1294    }
     1295    else
     1296    {
     1297        rc = VERR_NO_MEMORY;
     1298    }
     1299#else
    12231300    HOSTCALLBACKDATA HostCallbackData;
    12241301    HostCallbackData.u32Magic     = HOSTCALLBACKMAGIC;
     
    12301307                              (void *)(&HostCallbackData),
    12311308                              sizeof(HostCallbackData));
     1309#endif
    12321310    LogFlowFunc(("returning rc=%Rrc\n", rc));
    12331311    return rc;
     
    14401518}
    14411519
     1520#ifdef ASYNC_HOST_NOTIFY
     1521/* static */
     1522DECLCALLBACK(int) Service::threadNotifyHost(RTTHREAD self, void *pvUser)
     1523{
     1524    Service *pThis = (Service *)pvUser;
     1525    int rc = VINF_SUCCESS;
     1526
     1527    LogFlowFunc(("ENTER: %p\n", pThis));
     1528
     1529    for (;;)
     1530    {
     1531        rc = RTReqQueueProcess(pThis->mhReqQNotifyHost, RT_INDEFINITE_WAIT);
     1532
     1533        AssertMsg(rc == VWRN_STATE_CHANGED,
     1534                  ("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n",
     1535                   rc));
     1536        if (rc == VWRN_STATE_CHANGED)
     1537        {
     1538            break;
     1539        }
     1540    }
     1541
     1542    LogFlowFunc(("LEAVE: %Rrc\n", rc));
     1543    return rc;
     1544}
     1545
     1546static DECLCALLBACK(int) wakeupNotifyHost(void)
     1547{
     1548    /* Returning a VWRN_* will cause RTReqQueueProcess return. */
     1549    return VWRN_STATE_CHANGED;
     1550}
     1551
     1552int Service::initialize()
     1553{
     1554    /* The host notification thread and queue. */
     1555    int rc = RTReqQueueCreate(&mhReqQNotifyHost);
     1556    if (RT_SUCCESS(rc))
     1557    {
     1558        rc = RTThreadCreate(&mhThreadNotifyHost,
     1559                            threadNotifyHost,
     1560                            this,
     1561                            0 /* default stack size */,
     1562                            RTTHREADTYPE_DEFAULT,
     1563                            0, /* no flags. */
     1564                            "GSTPROPNTFY");
     1565    }
     1566
     1567    if (RT_FAILURE(rc))
     1568    {
     1569        if (mhReqQNotifyHost != NIL_RTREQQUEUE)
     1570        {
     1571            RTReqQueueDestroy(mhReqQNotifyHost);
     1572            mhReqQNotifyHost = NIL_RTREQQUEUE;
     1573        }
     1574    }
     1575
     1576    return rc;
     1577}
     1578#endif
     1579
    14421580int Service::uninit()
    14431581{
     1582#ifdef ASYNC_HOST_NOTIFY
     1583    if (mhReqQNotifyHost != NIL_RTREQQUEUE)
     1584    {
     1585        /* Stop the thread */
     1586        PRTREQ pReq;
     1587        int rc = RTReqQueueCall(mhReqQNotifyHost, &pReq, 10000, (PFNRT)wakeupNotifyHost, 0);
     1588        if (RT_SUCCESS(rc))
     1589            RTReqRelease(pReq);
     1590
     1591        rc = RTReqQueueDestroy(mhReqQNotifyHost);
     1592        AssertRC(rc);
     1593        mhReqQNotifyHost = NIL_RTREQQUEUE;
     1594        mhThreadNotifyHost = NIL_RTTHREAD;
     1595    }
     1596#endif
     1597
    14441598    return VINF_SUCCESS;
    14451599}
     
    15011655                /* Service specific initialization. */
    15021656                ptable->pvService = pService;
     1657
     1658#ifdef ASYNC_HOST_NOTIFY
     1659                rc = pService->initialize();
     1660                if (RT_FAILURE(rc))
     1661                {
     1662                    delete pService;
     1663                    pService = NULL;
     1664                }
     1665#endif
    15031666            }
    15041667            else
Note: See TracChangeset for help on using the changeset viewer.

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