VirtualBox

Changeset 37225 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 26, 2011 2:49:59 PM (14 years ago)
Author:
vboxsync
Message:

VBoxMouse/win: some cleanup & concurrency fuxes for NEW_PROTOCOL functionality

Location:
trunk/src/VBox/Additions/WINNT/Mouse/NT5
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMF.h

    r37221 r37225  
    4747typedef struct _VBOXMOUSE_DEVEXT
    4848{
     49    LIST_ENTRY ListEntry;
    4950    PDEVICE_OBJECT pdoMain;           /* PDO passed to VBoxDrvAddDevice */
    5051    PDEVICE_OBJECT pdoSelf;           /* our PDO created in VBoxDrvAddDevice*/
     
    7778VOID VBoxDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt);
    7879
     80NTSTATUS VBoxNewProtInit();
     81NTSTATUS VBoxNewProtTerm();
     82
    7983VOID VBoxDrvNotifyServiceCB(PVBOXMOUSE_DEVEXT pDevExt, PMOUSE_INPUT_DATA InputDataStart, PMOUSE_INPUT_DATA InputDataEnd, PULONG  InputDataConsumed);
    8084
  • trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFDriver.cpp

    r37221 r37225  
    5151    DriverObject->MajorFunction[IRP_MJ_PNP] = VBoxIrpPnP;
    5252
     53    NTSTATUS tmpStatus = VBoxNewProtInit();
     54    if (!NT_SUCCESS(tmpStatus))
     55    {
     56        WARN(("VBoxNewProtInit failed Status (0x%x)", tmpStatus));
     57    }
     58
    5359    LOGF_LEAVE();
    5460    return STATUS_SUCCESS;
     
    6066    PAGED_CODE();
    6167    LOGF_ENTER();
     68
     69    NTSTATUS tmpStatus = VBoxNewProtTerm();
     70    if (!NT_SUCCESS(tmpStatus))
     71    {
     72        WARN(("VBoxNewProtTerm failed Status (0x%x)", tmpStatus));
     73    }
     74
    6275
    6376    RTR0Term();
  • trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp

    r37221 r37225  
    4343    volatile PVBOXMOUSE_DEVEXT pCurrentDevExt;
    4444    LIST_ENTRY DevExtList;
     45    volatile bool fIsNewProtEnabled;
    4546    MOUSE_INPUT_DATA LastReportedData;
    4647} VBoxGlobalContext;
     
    4849static VBoxGlobalContext g_ctx = {};
    4950
     51/* Guest Device Communication API */
    5052NTSTATUS VBoxGdcInit()
    5153{
     
    207209}
    208210
    209 static NTSTATUS vboxNewProtInit(PVBOXMOUSE_DEVEXT pCurrentDevExt)
     211static BOOLEAN vboxNewProtIsInitialized()
     212{
     213    return !!g_ctx.pThread;
     214}
     215
     216static BOOLEAN vboxNewProtIsStarted()
     217{
     218    return (BOOLEAN)ASMAtomicReadBool(&g_ctx.fIsNewProtEnabled);
     219}
     220
     221NTSTATUS VBoxNewProtInit()
    210222{
    211223    NTSTATUS Status = VBoxGdcInit();
     
    215227        KeInitializeEvent(&g_ctx.TerminateEvent, NotificationEvent, FALSE);
    216228        KeInitializeEvent(&g_ctx.MouseEvent, SynchronizationEvent, FALSE);
    217 
    218         Status = VBoxGdcSetMouseNotifyEvent(&g_ctx.MouseEvent);
     229        InitializeListHead(&g_ctx.DevExtList);
     230        /* we assume the new prot data in g_ctx is zero-initialized (see g_ctx definition) */
     231
     232        Status = vboxCreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL);
    219233        if (NT_SUCCESS(Status))
    220234        {
    221             Status = vboxCreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL);
    222             if (NT_SUCCESS(Status))
    223             {
    224                 g_ctx.pCurrentDevExt = pCurrentDevExt;
    225                 return STATUS_SUCCESS;
    226             }
    227             g_ctx.pThread = NULL;
    228             NTSTATUS tmpStatus = VBoxGdcSetMouseNotifyEvent(NULL);
    229             Assert(NT_SUCCESS(tmpStatus));
    230         }
    231     }
    232 
    233     return Status;
    234 }
    235 
    236 static BOOLEAN vboxNewProtIsSupported()
    237 {
    238     return !!g_ctx.pThread;
    239 }
    240 
    241 static NTSTATUS vboxNewProtTerm()
    242 {
     235            return STATUS_SUCCESS;
     236        }
     237        g_ctx.pThread = NULL;
     238    }
     239
     240    return Status;
     241}
     242
     243NTSTATUS VBoxNewProtTerm()
     244{
     245    Assert(IsListEmpty(&g_ctx.DevExtList));
     246    Assert(!vboxNewProtIsStarted());
     247    if (!vboxNewProtIsInitialized())
     248        return STATUS_SUCCESS;
     249
    243250    KeSetEvent(&g_ctx.TerminateEvent, 0, FALSE);
    244251    NTSTATUS Status = KeWaitForSingleObject(g_ctx.pThread, Executive, KernelMode, FALSE, NULL);
     
    249256    }
    250257
    251     Status = VBoxGdcSetMouseNotifyEvent(NULL);
    252     if (!NT_SUCCESS(Status))
    253     {
    254         WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));
    255         return Status;
    256     }
    257 
    258258    ObDereferenceObject(g_ctx.pThread);
    259259    g_ctx.pThread = NULL;
     
    262262}
    263263
    264 static NTSTATUS vboxNewProtSetCurrentDevExt(PVBOXMOUSE_DEVEXT pCurrentDevExt)
    265 {
    266     ASMAtomicWritePtrVoid((void * volatile *)&g_ctx.pCurrentDevExt, pCurrentDevExt);
    267     return STATUS_SUCCESS;
     264static NTSTATUS vboxNewProtDeviceAdded(PVBOXMOUSE_DEVEXT pDevExt)
     265{
     266    if (!vboxNewProtIsInitialized())
     267        return STATUS_UNSUCCESSFUL;
     268
     269    NTSTATUS Status = STATUS_SUCCESS;
     270    KIRQL Irql;
     271    BOOLEAN fDoEventRegister = FALSE;
     272    KeAcquireSpinLock(&g_ctx.SyncLock, &Irql);
     273    InsertHeadList(&g_ctx.DevExtList, &pDevExt->ListEntry);
     274    if (!g_ctx.pCurrentDevExt)
     275    {
     276        ASMAtomicWritePtr(&g_ctx.pCurrentDevExt, pDevExt);
     277        /* ensure the object is not deleted while it is being used by a poller thread */
     278        ObReferenceObject(pDevExt->pdoSelf);
     279        fDoEventRegister = TRUE;
     280    }
     281    KeReleaseSpinLock(&g_ctx.SyncLock, Irql);
     282
     283    if (fDoEventRegister)
     284    {
     285        /* to ensure we do not concur with vboxNewProtDeviceRemoved cleaning the event,
     286         * do it in a loop until the cauuent state of fIsNewProtEnabled is false,
     287         * setting one and the same event multiple times will not hutr  */
     288        do
     289        {
     290            Status = VBoxGdcSetMouseNotifyEvent(&g_ctx.MouseEvent);
     291            if (!NT_SUCCESS(Status))
     292            {
     293                WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));
     294                break;
     295            }
     296        } while (ASMAtomicCmpXchgBool(&g_ctx.fIsNewProtEnabled, true, false));
     297
     298        if (NT_SUCCESS(Status))
     299        {
     300            /* signal the event to ensure we did not miss anything */
     301            KeSetEvent(&g_ctx.MouseEvent, 0, FALSE);
     302            Status = STATUS_SUCCESS;
     303        }
     304    }
     305#ifdef DEBUG_misha
     306    else
     307    {
     308        Assert(g_ctx.fIsNewProtEnabled);
     309    }
     310#endif
     311
     312    return Status;
     313}
     314
     315#define PVBOXMOUSE_DEVEXT_FROM_LE(_pLe) ( (PVBOXMOUSE_DEVEXT)(((uint8_t*)(_pLe)) - RT_OFFSETOF(VBOXMOUSE_DEVEXT, ListEntry)) )
     316
     317static NTSTATUS vboxNewProtDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt)
     318{
     319    if (!vboxNewProtIsInitialized())
     320        return STATUS_UNSUCCESSFUL;
     321
     322    KIRQL Irql;
     323    NTSTATUS Status = STATUS_SUCCESS;
     324    BOOLEAN fDoEventUnregister = FALSE;
     325    KeAcquireSpinLock(&g_ctx.SyncLock, &Irql);
     326    RemoveEntryList(&pDevExt->ListEntry);
     327    if (g_ctx.pCurrentDevExt == pDevExt)
     328    {
     329        ObDereferenceObject(pDevExt->pdoSelf);
     330        g_ctx.pCurrentDevExt = NULL;
     331        for (PLIST_ENTRY pCur = g_ctx.DevExtList.Flink; pCur != &g_ctx.DevExtList; pCur = pCur->Flink)
     332        {
     333            PVBOXMOUSE_DEVEXT pNewCurDevExt = PVBOXMOUSE_DEVEXT_FROM_LE(pCur);
     334            ASMAtomicWritePtr(&g_ctx.pCurrentDevExt, pNewCurDevExt);
     335            /* ensure the object is not deleted while it is being used by a poller thread */
     336            ObReferenceObject(pNewCurDevExt->pdoSelf);
     337            break;
     338        }
     339    }
     340
     341    fDoEventUnregister = IsListEmpty(&g_ctx.DevExtList);
     342    KeReleaseSpinLock(&g_ctx.SyncLock, Irql);
     343
     344    if (fDoEventUnregister)
     345    {
     346        if (vboxNewProtIsStarted())
     347        {
     348            Status = VBoxGdcSetMouseNotifyEvent(NULL);
     349            if (!NT_SUCCESS(Status))
     350            {
     351                WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));
     352            }
     353
     354            ASMAtomicWriteBool(&g_ctx.fIsNewProtEnabled, false);
     355        }
     356    }
     357
     358    return Status;
    268359}
    269360
     
    289380                    pData->LastY = pDevExt->pSCReq->pointerYPos;
    290381                    pData->Flags = MOUSE_MOVE_ABSOLUTE;
    291                     if (vboxNewProtIsSupported())
     382                    if (vboxNewProtIsStarted())
    292383                        pData->Flags |= MOUSE_VIRTUAL_DESKTOP;
    293384                    pData++;
     
    353444                WARN(("VBGL init failed with rc=%#x", rc));
    354445            }
    355 
    356             vboxNewProtInit(pDevExt);
    357         }
    358     }
     446        }
     447    }
     448
     449    vboxNewProtDeviceAdded(pDevExt);
    359450
    360451    if (!vboxIsHostMouseFound())
     
    454545        {
    455546            req->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
    456             if (vboxNewProtIsSupported())
     547            if (vboxNewProtIsStarted())
    457548                req->mouseFeatures |= VMMDEV_MOUSE_NEW_PROTOCOL;
    458549
     
    543634    LONG callCnt = InterlockedDecrement(&g_ctx.cDevicesStarted);
    544635
     636    vboxNewProtDeviceRemoved(pDevExt);
     637
    545638    if (callCnt == 0)
    546639    {
    547         vboxNewProtTerm();
    548 
    549640        if (vboxIsVBGLInited())
    550641        {
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