[ofw] [RFC] [PATCH 1/2] work_queue: new abstraction for queuing work

Fab Tillier ftillier at windows.microsoft.com
Thu May 21 14:14:17 PDT 2009


>> From the CM callback, you know that the EP is still valid and you can
>> check to see if you have a disconnect request queued.  If so, you can
>> remove it from the queue (so it can't be cancelled), and queue the work
>> item using the request as context.  From the work item callback,
>> reference the EP and QP (since they now could have been destroyed)
>> based on the IOCTL parameters (just like you did when you first
>> received the IRP), and assuming they're valid, move the QP.  You
>> actually might not need to reference the EP, just the QP might do.
>
> This is what the code does.  I just didn't realize that I could store
> additional context in the IRP.

I know you can with the IRP, I don't know though if the WDF framework reserves those fields (Tail.Overlay.DriverContext array).

>> No, you could have a pool of work items that you would pull from when
>> you get the CM callback and need to queue it.  If the pool is empty,
>> you could allocate new work items dynamically since that is valid
>> operation at DISPATCH.
>
> The work queue abstraction is the pool of work items.  I just don't
> allow the pool to grow.  And since IO_WORKITEMs are opaque, maintaining
> them in a pool requires additional structures around them.  You can't
> just have calls like:
> 
> IO_WORKITEM *PoolGet();
> PoolPut(IO_WORKITEM *);

Complib already has what you need: Quick pool.

void* wi_pool_ctor(
    void* p_obj,
    void* context,
    cl_pool_item_t** const pp_item )
{
    cl_pool_obj_t* p_new_obj = (cl_pool_obj_t*)p_obj;

    p_new_obj->object = IoAllocateWorkItem( (DEVICE_OBJECT*)context );
    if( p_new_obj->object == NULL )
    {
        ExFreePool( p_new_obj );
        return CL_ERROR;
    }

    *pp_item = *p_new_obj->item;
    return CL_SUCCESS;
}

void wi_pool_dtor(
    void* const cl_pool_item_t* p_item,
    void* context )
{
    IoFreeWorkItem( ((cl_pool_obj_t*)p_item)->object );
}
 
cl_qpool_init( 
    &wi_pool,
    WI_POOL_MIN,
    WI_POOL_MAX,
    WI_POOL_GROW,
    sizeof(cl_pool_obj_t),
    wi_pool_ctor,
    wi_pool_dtor,
    pDevObj );

The you can use cl_qpool_get/put with the appropriate cast.

-Fab



More information about the ofw mailing list