none
Why WdfCreateWorkItem() called into EvtIOControl causes an exception ? RRS feed

  • Question

  • Hi,

    I'm developing a PCIe Card driver using WDF. I'm not an Windows driver expert.

    My driver receives an IOCTL request and creates a work item object. But, the kernel raise an exception when WdfWorkItemCreate() function is called (cf. Bugcheck analysis).

    I do not understand the problem? (indeed, code "looks" like AMCC5933::AmccIsaEvtIoDeviceControl() sample code).

    The code snippet from my EvtIoControl callback looks like :
    [...]
          case PEGD_IOCTL_WAIT_FOR_INTERRUPT:
             TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "DeviceIoControl(PEGD_IOCTL_WAIT_FOR_INTERRUPT) received...");
             status = PEGD_IoctlWaitForInterrupt(device_ctx_ptr->hwr_id, hRequest, device_ctx_ptr, ioctl_input_memory, ioctl_output_memory);
             doComplete = NT_SUCCESS(status) ? FALSE : TRUE;
             break;
    [...]
    The code of the PEGD_IoctlWaitForInterrupt() looks like :

    NTSTATUS
    PEGD_IoctlWaitForInterrupt(
       _In_ const PEGD_HARDWARE_ID eHardwareIdentifier,
       _In_ WDFREQUEST hRequest,
       _In_ PDEVICE_CONTEXT pDeviceCtx,
       _In_ WDFMEMORY hIoctlInMem,
       _Out_ WDFMEMORY hIoctlOutMem
    )
    {
       NTSTATUS status;
       PEGD_Command incmd;
       PEGD_Command outcmd = { .status = PEGD_INTERNAL_STATUS_ERROR };
      
       if (PEGD_HARDWARE_ID_NUMS == eHardwareIdentifier || !pDeviceCtx)
       {
          TraceEvents(TRACE_LEVEL_ERROR, TRACE_IOCTL, "%!FUNC! error : invalid parameters");
          return STATUS_INVALID_PARAMETER;
       }
       else if (!NT_SUCCESS(status = WdfMemoryCopyToBuffer(hIoctlInMem, 0, &incmd, sizeof incmd)))
       {
          TraceEvents(TRACE_LEVEL_ERROR, TRACE_IOCTL, "WdfMemoryCopyToBuffer() call failed [ errcode = %!STATUS! ]", status);
          return status;
       }
       else
       {
          PEGD_InterruptWaiter *waiter_ptr = NULL;
          WDFMEMORY             memory;
          WDF_OBJECT_ATTRIBUTES memory_attributes;
          WDF_OBJECT_ATTRIBUTES workitem_attributes;
          PWORKITEM_CONTEXT     workitem_ctx_ptr = NULL;
          WDF_WORKITEM_CONFIG   workitem_cfg;
          WDFWORKITEM           workitem;
    
          // Set work item attributes  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, WORKITEM_CONTEXT);
          workitem_attributes.ParentObject = pDeviceCtx->handle;
    
          // Initialize work item configuration
          WDF_WORKITEM_CONFIG_INIT(&workitem_cfg, PEGD_EvtWaitForInterruptWorkItem);
    
          // Create work item
          status = WdfWorkItemCreate(&workitem_cfg, &workitem_attributes, &workitem); // <== EXCEPTION !!!
    
          if (!NT_SUCCESS(status))
          {
             TraceEvents(TRACE_LEVEL_ERROR, TRACE_IOCTL, "WdfWorkItemCreate() call failed [ errcode = %!STATUS! ]", status);
             return status;
          }
    
          // Allocate memory to store waiter information
          WDF_OBJECT_ATTRIBUTES_INIT(&memory_attributes);
          memory_attributes.ParentObject = pDeviceCtx->handle;
    
          status = WdfMemoryCreate(&memory_attributes, NonPagedPool, 0, sizeof *waiter_ptr, &memory, &waiter_ptr);
    
          if (!NT_SUCCESS(status))
          {
             TraceEvents(TRACE_LEVEL_ERROR, TRACE_IOCTL, "WdfMemoryCreate() call failed [ errcode = %!STATUS! ]", status);
             return status;
          }
    [...]
          // Enqueue the work item
          WdfWorkItemEnqueue(workitem);
    
          return STATUS_PENDING;
       }
    }
    Any feedback to understand what is happening? Thanks.

    Cheers.

    **************** Bugcheck Analysis ******************

    Unknown bugcheck code (0)
    Unknown bugcheck description
    Arguments:
    Arg1: 0000000000000000
    Arg2: 0000000000000000
    Arg3: 0000000000000000
    Arg4: 0000000000000000

    Debugging Details:
    ------------------
    PROCESS_NAME:  tpegd-x64-w64-

    FAULTING_IP:
    nt!DbgBreakPoint+0
    fffff800`016c39d0 cc              int     3

    ERROR_CODE: (NTSTATUS) 0x80000003 - {EXCEPTION}  Point d
    EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - Un ou plusieurs arguments sont incorrects
    EXCEPTION_PARAMETER1:  0000000000000000
    DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT
    BUGCHECK_STR:  0x0
    CURRENT_IRQL:  2
    ANALYSIS_VERSION: 6.3.9600.16384 (debuggers(dbg).130821-1623) amd64fre
    LAST_CONTROL_TRANSFER:  from fffff88000e5db56 to fffff800016c39d0
    STACK_TEXT:  
    fffff880`067e90a8 fffff880`00e5db56 : fffffa80`02700fd0 fffffa80`02700fd0 fffff880`067e9100 00000000`00000000 : nt!DbgBreakPoint
    fffff880`067e90b0 fffff880`00e5f52e : fffffa80`02e5e3f0 fffffa80`02700e40 fffff880`00000002 fffff880`067e92e0 : Wdf01000!FxObject::_GetEffectiveLock+0xee
    fffff880`067e90f0 fffff880`00e5f446 : fffffa80`032799c8 fffffa80`02e5e3f0 fffffa80`03279960 fffff880`067e92f8 : Wdf01000!FxWorkItem::Initialize+0xae
    fffff880`067e9150 fffff880`00e5f33c : fffffa80`03279960 fffff880`067e92b8 fffff880`067e92f8 fffff880`067e91d0 : Wdf01000!FxWorkItem::_Create+0xea
    fffff880`067e91b0 fffff880`07f6fbaa : fffffa80`03279960 fffffa80`04b1e490 fffff880`067e9700 fffffa80`034307d0 : Wdf01000!imp_WdfWorkItemCreate+0x22c
    fffff880`067e9230 fffff880`07f6f051 : fffff880`067e92e0 fffff880`067e92f8 fffff880`067e92b8 00000000`00000120 : pegd!WdfWorkItemCreate+0x4a [c:\program files (x86)\windows kits\8.1\include\wdf\kmdf\1.11\wdfworkitem.h @ 117]
    fffff880`067e9270 fffff880`07f703e5 : 7fffffff`00000004 0000057f`fb4e1b68 fffffa80`03279c10 0000057f`fb4e1aa1 : pegd!PEGD_IoctlWaitForInterrupt+0x261 [p:\110676_pciegendriver\branches\dev-sdiwindrv\src\driver\windows\pegd_ioctl_api.c @ 408]
    fffff880`067e95d0 fffff880`00e2db7c : 0000057f`fd493f78 0000057f`fb4e1b68 00000000`00000120 00000000`00000120 : pegd!PEGD_EvtIoDeviceControl+0x7f5 [p:\110676_pciegendriver\branches\dev-sdiwindrv\src\driver\windows\pegd_queue.c @ 210]
    fffff880`067e96c0 fffff880`00e2d1ff : fffffa80`02b6c000 fffffa80`00000120 fffffa80`02b6c080 00000000`00000000 : Wdf01000!FxIoQueue::DispatchRequestToDriver+0x488
    [...]

    STACK_COMMAND:  kb

    FOLLOWUP_IP:
    pegd!WdfWorkItemCreate+4a [c:\program files (x86)\windows kits\8.1\include\wdf\kmdf\1.11\wdfworkitem.h @ 117]
    fffff880`07f6fbaa 4883c438        add     rsp,38h

    FAULTING_SOURCE_LINE:  c:\program files (x86)\windows kits\8.1\include\wdf\kmdf\1.11\wdfworkitem.h
    FAULTING_SOURCE_FILE:  c:\program files (x86)\windows kits\8.1\include\wdf\kmdf\1.11\wdfworkitem.h

    FAULTING_SOURCE_LINE_NUMBER:  117

    FAULTING_SOURCE_CODE:  
       113:     WDFWORKITEM* WorkItem
       114:     )
       115: {
       116:     return ((PFN_WDFWORKITEMCREATE) WdfFunctions[WdfWorkItemCreateTableIndex])(WdfDriverGlobals, Config, Attributes, WorkItem);
    >  117: }

    SYMBOL_STACK_INDEX:  5
    SYMBOL_NAME:  pegd!WdfWorkItemCreate+4a
    FOLLOWUP_NAME:  MachineOwner
    MODULE_NAME: pegd
    IMAGE_NAME:  pegd.sys
    DEBUG_FLR_IMAGE_TIMESTAMP:  525fbf6d
    FAILURE_BUCKET_ID:  X64_0x0_VRF_pegd!WdfWorkItemCreate+4a
    BUCKET_ID:  X64_0x0_VRF_pegd!WdfWorkItemCreate+4a
    ANALYSIS_SOURCE:  KM
    FAILURE_ID_HASH_STRING:  km:x64_0x0_vrf_pegd!wdfworkitemcreate+4a
    FAILURE_ID_HASH:  {2e86b1ca-9bce-11cd-88ee-be80dd7096a8}
    Thursday, October 17, 2013 10:55 AM

Answers

  • If you run !wdfkd.wdflogdump pegd, it will tell you why the bp was hit. My guess is because you didn't init the work item attributes

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 17, 2013 2:36 PM
  • DeviceScope by default means everything runs at dispatch level. a work item must run at passive level, so you configuration doesn't allow for the work item to run. If you set AutomaticSerialization  to FALSE, you can create and use the work item, but it will not be synchronized with your other callbacks (you can acquire the lock used for that synchronization by calling WdfObjectAcquireLock on your WDFDEVICE if needed within the work item callback)

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 17, 2013 5:34 PM
  • Creation at dispatch is fine. The problem is configuration. Device scope means everything runs at dispatch and serialized. A work item runs at passive, so asking for a work item that just run at dispatch makes no sense, hence not allowed. By setting AutomicSerialization to false with DeviceScope set you are allowing the work item to run at passive without serialization

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    • Marked as answer by Netguesh Friday, October 18, 2013 8:52 AM
    Thursday, October 17, 2013 6:19 PM

All replies

  • If you run !wdfkd.wdflogdump pegd, it will tell you why the bp was hit. My guess is because you didn't init the work item attributes

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 17, 2013 2:36 PM
  • Hi Don,

    Thanks for the feedback. I'going to run '!wdfkd.wdflogdump pegd' command.

    I think their is a copy/paste issue with code inserter.

    You read:
          // Set work item attributes  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, WORKITEM_CONTEXT);
          workitem_attributes.ParentObject = pDeviceCtx->handle;
    But it should be presented as below :
          // Set work item attributes
          WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitem_attributes, WORKITEM_CONTEXT);
          workitem_attributes.ParentObject = pDeviceCtx->handle;
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE() performs the attribute initialization job. Does it?

    Cheers.
    Thursday, October 17, 2013 3:22 PM
  • Did you specify a sync or execution scope when configuring the queue or device?

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 17, 2013 4:00 PM
  • I use the device scope sync.

    NTSTATUS
    PEGD_CreateDevice(
    	_Inout_ PWDFDEVICE_INIT *pphDeviceInit,
    	_Out_ WDFDEVICE *phDevice
    )
    {
       NTSTATUS              status = STATUS_SUCCESS;
    	WDF_OBJECT_ATTRIBUTES attributes;
    
       DECLARE_CONST_UNICODE_STRING(nt_device_name, PEGD_NT_DEVICE_NAME);
       DECLARE_CONST_UNICODE_STRING(dos_device_name, PEGD_DOS_DEVICE_NAME);
    
    	PAGED_CODE();
    
       // Create a NT device name
       status = WdfDeviceInitAssignName(*pphDeviceInit, &nt_device_name);
    
       if (!NT_SUCCESS(status)) {
          TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "WdfDeviceInitAssignName() call failed [ errcode = %!STATUS! ]", status);
          return status;
       }
    
       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
    
       //
       // We want all the queue callbacks, cancel routine, and DpcForIsr to be serialized
       // at the device level, so we don't have worry about any synchronization issues.
       //
       attributes.SynchronizationScope = WdfSynchronizationScopeDevice; // <== Device scope sync.
    [...]
    }


    Thursday, October 17, 2013 4:18 PM
  • Herein an extract of '!wdfkd.wdflogdump pegd' command :

    [...]
    142: FxPkgIo::Dispatch - WDFDEVICE 0x0000057FFC44B558 !devobj 0xFFFFFA800195D900 0x0000000e(IRP_MJ_DEVICE_CONTROL), IRP_MN 0, IRP 0xFFFFF980134ACE10
    143: FxIoQueue::QueueRequest - Queuing WDFREQUEST 0x0000057FFB4B4188 on WDFQUEUE 0x0000057FFBC5F668
    144: FxIoQueue::DispatchEvents - Thread FFFFFA800327F5D0 is processing WDFQUEUE 0x0000057FFBC5F668
    145: FxIoQueue::DispatchRequestToDriver - Calling driver EvtIoDeviceControl for WDFREQUEST 0x0000057FFB4B4188
    146: FxRequest::Complete - Completing WDFREQUEST 0x0000057FFB4B4188 for IRP 0xFFFFF980134ACE10 with Information 0x120, STATUS_SUCCESS
    147: FxObject::SetObjectStateLocked - Object FFFFFA8004B4BE70, WDFOBJECT 0000057FFB4B4188 transitioning from FxObjectStateCreated to FxObjectStateDisposingEarly
    148: FxObject::SetObjectStateLocked - Object FFFFFA8004B4BE70, WDFOBJECT 0000057FFB4B4188 transitioning from FxObjectStateDisposingEarly to FxObjectStateDisposingDisposeChildren
    149: FxObject::SetObjectStateLocked - Object FFFFFA8004B4BE70, WDFOBJECT 0000057FFB4B4188 transitioning from FxObjectStateDisposingDisposeChildren to FxObjectStateDisposed
    150: FxObject::SetObjectStateLocked - Object FFFFFA8004B4BE70, WDFOBJECT 0000057FFB4B4188 transitioning from FxObjectStateDisposed to FxObjectStateDeletedAndDisposed
    151: FxObject::SetObjectStateLocked - Object FFFFFA8004B4BE70, WDFOBJECT 0000057FFB4B4188 transitioning from FxObjectStateDeletedAndDisposed to FxObjectStateDestroyed
    152: FxPkgIo::Dispatch - WDFDEVICE 0x0000057FFC44B558 !devobj 0xFFFFFA800195D900 0x0000000e(IRP_MJ_DEVICE_CONTROL), IRP_MN 0, IRP 0xFFFFF980017E4E10
    153: FxIoQueue::QueueRequest - Queuing WDFREQUEST 0x0000057FFB4B4188 on WDFQUEUE 0x0000057FFBC5F668
    154: FxIoQueue::DispatchEvents - Thread FFFFFA8003FDB370 is processing WDFQUEUE 0x0000057FFBC5F668
    155: FxIoQueue::DispatchRequestToDriver - Calling driver EvtIoDeviceControl for WDFREQUEST 0x0000057FFB4B4188
    ---- end of log ----
    1: kd> !wdfkd.wdfrequest 0x0000057FFB4B4188 
    Treating handle as a KMDF handle!
        !irp 0xfffff980017e4e10
    
    !wdfqueue 0x0000057ffbc5f668
       State:  Pending, Allocated by WDF for incoming IRP
       System Buffer 0xfffff9800a714ee0, Length 0x120, !wdfmemory 0x0000057ffb4b40c1
       IOCTL Output Buffer 0xfffff9800a714ee0, Length 0x120, !wdfmemory 0x0000057ffb4b40b1
    
    1: kd> !wdfmemory 0x0000057ffb4b40c1
    Treating handle as a KMDF handle!
    WDFMEMORY 0x0000057ffb4b40c1:  Buffer 0xfffff9800a714ee0, Length 0x120 (288) bytes
    1: kd> !wdfmemory 0x0000057ffb4b40b1
    Treating handle as a KMDF handle!
    WDFMEMORY 0x0000057ffb4b40b1:  Buffer 0xfffff9800a714ee0, Length 0x120 (288) bytes
    1: kd> !irp 0xfffff980017e4e10
    Irp is active with 4 stacks 3 is current (= 0xfffff980017e4f70)
     No Mdl: System buffer=fffff9800a714ee0: Thread fffffa8003fdb370:  Irp stack trace.  
         cmd  flg cl Device   File     Completion-Context
     [  0, 0]   0  0 00000000 00000000 00000000-00000000    
    
    			Args: 00000000 00000000 00000000 00000000
     [  0, 0]   0 10 00000000 00000000 00000000-00000000    
    
    			Args: 00000000 00000000 00000000 00000000
    >[  e, 0]   5 e1 fffffa800195d900 fffffa8004484e20 fffff80001b20eb0-fffff980017e4fb8 Success Error Cancel pending
    	       \Driver\pegd	nt!IovpInternalCompletionTrap
    			Args: 00000120 00000120 8a7ee35c 00000000
     [  e, 0]   5  0 fffffa80044e2b10 fffffa8004484e20 00000000-00000000    
    	       \DRIVER\VERIFIER_FILTER
    			Args: 00000120 00000120 8a7ee35c 00000000

    Thursday, October 17, 2013 4:21 PM
  • DeviceScope by default means everything runs at dispatch level. a work item must run at passive level, so you configuration doesn't allow for the work item to run. If you set AutomaticSerialization  to FALSE, you can create and use the work item, but it will not be synchronized with your other callbacks (you can acquire the lock used for that synchronization by calling WdfObjectAcquireLock on your WDFDEVICE if needed within the work item callback)

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 17, 2013 5:34 PM
  • unfortunately the log statement indicating error is made after the DbgBreakPoint. if you return back to your driver, you would see something like this in the log

    ParentObject Xxx cannot automatically synchronize callbacks with a WorkItem since it is not configured for passive level callback constraints.  Use a WDFDPC instead or set  AutomaticSerialization to FALSE. <NTSTATUS value>


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 17, 2013 5:36 PM
  • I supposed that work items could be created at DISPATCH_LEVEL. Indeed, I read that EvtInterruptDpc() (which run at DISPATCH_LEVEL) could use work items to run code at PASSIVE_LEVEL :
    "The EvtInterruptDpc callback function executes at DISPATCH_LEVEL and must not access pageable code. If an EvtInterruptDpc callback function must perform operations at IRQL = PASSIVE_LEVEL, it can use framework work items." (http://msdn.microsoft.com/en-us/library/windows/hardware/ff541721%28v=vs.85%29.aspx)

    At a first glance, it looks like my use case. Doesn't it?

    Sorry I'm not really comfortable with all these concepts yet. Could clarify the point ?

    Thanks.
    • Edited by Netguesh Thursday, October 17, 2013 5:50 PM
    Thursday, October 17, 2013 5:48 PM
  • Creation at dispatch is fine. The problem is configuration. Device scope means everything runs at dispatch and serialized. A work item runs at passive, so asking for a work item that just run at dispatch makes no sense, hence not allowed. By setting AutomicSerialization to false with DeviceScope set you are allowing the work item to run at passive without serialization

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    • Marked as answer by Netguesh Friday, October 18, 2013 8:52 AM
    Thursday, October 17, 2013 6:19 PM
  • hi Doron,

    That's solve the issue.

    Cheers.
    Friday, October 18, 2013 8:52 AM