VirtualBox

Changeset 37226 in vbox for trunk/src/VBox/Additions/WINNT


Ignore:
Timestamp:
May 26, 2011 5:06:02 PM (14 years ago)
Author:
vboxsync
Message:

VBoxMouse/VBoxGuest/win: avoid poller thread for mouse events notifications over NEW_PROTOCOL

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp

    r37225 r37226  
    3838    VBOXGDC Gdc;
    3939    KSPIN_LOCK SyncLock;
    40     KEVENT TerminateEvent;
    41     KEVENT MouseEvent;
    42     PKTHREAD pThread;
    4340    volatile PVBOXMOUSE_DEVEXT pCurrentDevExt;
    4441    LIST_ENTRY DevExtList;
    45     volatile bool fIsNewProtEnabled;
     42    BOOLEAN fIsNewProtEnabled;
    4643    MOUSE_INPUT_DATA LastReportedData;
    4744} VBoxGlobalContext;
     
    119116}
    120117
    121 /* overwrites the previously set one, can be NULL to clear the event */
    122 NTSTATUS VBoxGdcSetMouseNotifyEvent(PKEVENT pEvent)
    123 {
    124     if (!VBoxGdcIsInitialized())
    125     {
    126         WARN(("Guest Device Communication not initialized"));
    127         return STATUS_UNSUCCESSFUL;
    128     }
    129 
    130     NTSTATUS Status = vboxGdcSubmit(VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_EVENT, pEvent, sizeof (pEvent));
     118static DECLCALLBACK(void) vboxNewProtMouseEventCb(void *pvContext)
     119{
     120    PVBOXMOUSE_DEVEXT pDevExt = (PVBOXMOUSE_DEVEXT)ASMAtomicUoReadPtr((void * volatile *)&g_ctx.pCurrentDevExt);
     121    if (pDevExt)
     122    {
     123#define VBOXMOUSE_POLLERTAG 'PMBV'
     124        NTSTATUS Status = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt);
     125        if (NT_SUCCESS(Status))
     126        {
     127            ULONG InputDataConsumed = 0;
     128            VBoxDrvNotifyServiceCB(pDevExt, &g_ctx.LastReportedData, &g_ctx.LastReportedData + 1, &InputDataConsumed);
     129            IoReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt);
     130        }
     131        else
     132        {
     133            WARN(("IoAcquireRemoveLock failed, Status (0x%x)", Status));
     134        }
     135    }
     136    else
     137    {
     138        WARN(("no current pDevExt specified"));
     139    }
     140}
     141
     142static BOOLEAN vboxNewProtIsEnabled()
     143{
     144    return g_ctx.fIsNewProtEnabled;
     145}
     146
     147static NTSTATUS vboxNewProtRegisterMouseEventCb(BOOLEAN fRegister)
     148{
     149    VBoxGuestMouseSetNotifyCallback CbInfo = {};
     150    CbInfo.pfnNotify = fRegister ? vboxNewProtMouseEventCb : NULL;
     151
     152    NTSTATUS Status = vboxGdcSubmit(VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_CALLBACK, &CbInfo, sizeof (CbInfo));
    131153    if (!NT_SUCCESS(Status))
    132154    {
     
    136158}
    137159
    138 /**
    139  * helper function used for system thread creation
    140  */
    141 static NTSTATUS vboxCreateSystemThread(PKTHREAD *ppThread, PKSTART_ROUTINE pfnStartRoutine, PVOID pvStartContext)
    142 {
    143     OBJECT_ATTRIBUTES ObjectAttributes;
    144     Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
    145 
    146     InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
    147 
    148     HANDLE hThread;
    149     NTSTATUS Status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, (PKSTART_ROUTINE)pfnStartRoutine, pvStartContext);
    150     Assert(Status == STATUS_SUCCESS);
    151     if (Status == STATUS_SUCCESS)
    152     {
    153         Status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)ppThread, NULL);
    154         Assert(Status == STATUS_SUCCESS);
    155         ZwClose(hThread);
    156         if (Status == STATUS_SUCCESS)
    157         {
    158             return STATUS_SUCCESS;
    159         }
    160 
    161         /* @todo: how would we fail in this case ?*/
    162     }
    163     return Status;
    164 }
    165 
    166 static VOID vboxMouseEventPollerThread(PVOID pvContext)
    167 {
    168     PKEVENT apEvents[] = {&g_ctx.MouseEvent, &g_ctx.TerminateEvent};
    169     NTSTATUS Status;
    170     while (1)
    171     {
    172         Status = KeWaitForMultipleObjects(RT_ELEMENTS(apEvents), (PVOID*)apEvents,
    173                 WaitAny, Executive, KernelMode, FALSE /* BOOLEAN  Alertable */,
    174                 NULL /* PLARGE_INTEGER Timeout */,
    175                 NULL /* PKWAIT_BLOCK WaitBlockArray */
    176                 );
    177         Assert(NT_SUCCESS(Status));
    178 
    179         if (Status != STATUS_WAIT_0)
    180         {
    181             /* terminate event */
    182             Assert(Status == STATUS_WAIT_1);
    183             break;
    184         }
    185 
    186         ULONG InputDataConsumed = 0;
    187         PVBOXMOUSE_DEVEXT pDevExt = (PVBOXMOUSE_DEVEXT)ASMAtomicUoReadPtr((void * volatile *)&g_ctx.pCurrentDevExt);
    188         if (pDevExt)
    189         {
    190 #define VBOXMOUSE_POLLERTAG 'PMBV'
    191             Status = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt);
    192             if (NT_SUCCESS(Status))
    193             {
    194                 VBoxDrvNotifyServiceCB(pDevExt, &g_ctx.LastReportedData, &g_ctx.LastReportedData + 1, &InputDataConsumed);
    195                 IoReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt);
    196             }
    197             else
    198             {
    199                 WARN(("IoAcquireRemoveLock failed, Status (0x%x)", Status));
    200             }
    201         }
    202         else
    203         {
    204             WARN(("no current pDevExt specified"));
    205         }
    206     }
    207 
    208     PsTerminateSystemThread(STATUS_SUCCESS);
    209 }
    210 
    211 static BOOLEAN vboxNewProtIsInitialized()
    212 {
    213     return !!g_ctx.pThread;
    214 }
    215 
    216 static BOOLEAN vboxNewProtIsStarted()
    217 {
    218     return (BOOLEAN)ASMAtomicReadBool(&g_ctx.fIsNewProtEnabled);
    219 }
    220160
    221161NTSTATUS VBoxNewProtInit()
     
    225165    {
    226166        KeInitializeSpinLock(&g_ctx.SyncLock);
    227         KeInitializeEvent(&g_ctx.TerminateEvent, NotificationEvent, FALSE);
    228         KeInitializeEvent(&g_ctx.MouseEvent, SynchronizationEvent, FALSE);
    229167        InitializeListHead(&g_ctx.DevExtList);
    230168        /* we assume the new prot data in g_ctx is zero-initialized (see g_ctx definition) */
    231169
    232         Status = vboxCreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL);
     170        Status = vboxNewProtRegisterMouseEventCb(TRUE);
    233171        if (NT_SUCCESS(Status))
    234172        {
     173            g_ctx.fIsNewProtEnabled = TRUE;
    235174            return STATUS_SUCCESS;
    236175        }
    237         g_ctx.pThread = NULL;
     176        VBoxGdcTerm();
    238177    }
    239178
     
    244183{
    245184    Assert(IsListEmpty(&g_ctx.DevExtList));
    246     Assert(!vboxNewProtIsStarted());
    247     if (!vboxNewProtIsInitialized())
     185    if (!vboxNewProtIsEnabled())
     186    {
     187        WARN(("New Protocol is disabled"));
    248188        return STATUS_SUCCESS;
    249 
    250     KeSetEvent(&g_ctx.TerminateEvent, 0, FALSE);
    251     NTSTATUS Status = KeWaitForSingleObject(g_ctx.pThread, Executive, KernelMode, FALSE, NULL);
     189    }
     190
     191    g_ctx.fIsNewProtEnabled = FALSE;
     192
     193    NTSTATUS Status = vboxNewProtRegisterMouseEventCb(FALSE);
    252194    if (!NT_SUCCESS(Status))
    253195    {
     
    256198    }
    257199
    258     ObDereferenceObject(g_ctx.pThread);
    259     g_ctx.pThread = NULL;
    260 
    261     return Status;
     200    VBoxGdcTerm();
     201
     202    return STATUS_SUCCESS;
    262203}
    263204
    264205static NTSTATUS vboxNewProtDeviceAdded(PVBOXMOUSE_DEVEXT pDevExt)
    265206{
    266     if (!vboxNewProtIsInitialized())
     207    if (!vboxNewProtIsEnabled())
     208    {
     209        WARN(("New Protocol is disabled"));
    267210        return STATUS_UNSUCCESSFUL;
     211    }
    268212
    269213    NTSTATUS Status = STATUS_SUCCESS;
    270214    KIRQL Irql;
    271     BOOLEAN fDoEventRegister = FALSE;
    272215    KeAcquireSpinLock(&g_ctx.SyncLock, &Irql);
    273216    InsertHeadList(&g_ctx.DevExtList, &pDevExt->ListEntry);
     
    277220        /* ensure the object is not deleted while it is being used by a poller thread */
    278221        ObReferenceObject(pDevExt->pdoSelf);
    279         fDoEventRegister = TRUE;
    280222    }
    281223    KeReleaseSpinLock(&g_ctx.SyncLock, Irql);
    282224
    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 
    312225    return Status;
    313226}
     
    317230static NTSTATUS vboxNewProtDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt)
    318231{
    319     if (!vboxNewProtIsInitialized())
     232    if (!vboxNewProtIsEnabled())
     233    {
     234        WARN(("New Protocol is disabled"));
    320235        return STATUS_UNSUCCESSFUL;
     236    }
    321237
    322238    KIRQL Irql;
    323239    NTSTATUS Status = STATUS_SUCCESS;
    324     BOOLEAN fDoEventUnregister = FALSE;
    325240    KeAcquireSpinLock(&g_ctx.SyncLock, &Irql);
    326241    RemoveEntryList(&pDevExt->ListEntry);
     
    339254    }
    340255
    341     fDoEventUnregister = IsListEmpty(&g_ctx.DevExtList);
    342256    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     }
    357257
    358258    return Status;
     
    380280                    pData->LastY = pDevExt->pSCReq->pointerYPos;
    381281                    pData->Flags = MOUSE_MOVE_ABSOLUTE;
    382                     if (vboxNewProtIsStarted())
     282                    if (vboxNewProtIsEnabled())
    383283                        pData->Flags |= MOUSE_VIRTUAL_DESKTOP;
    384284                    pData++;
     
    545445        {
    546446            req->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
    547             if (vboxNewProtIsStarted())
     447            if (vboxNewProtIsEnabled())
    548448                req->mouseFeatures |= VMMDEV_MOUSE_NEW_PROTOCOL;
    549449
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