/* $Id$ * reactos IO_WORKITEM handling by libcaptive * Copyright (C) 2002 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "reactos/ddk/iofuncs.h" /* self */ #include #include "captive/macros.h" #include "reactos/ddk/obfuncs.h" /* for ObDereferenceObject() */ #include typedef struct _IO_WORKITEM { DEVICE_OBJECT *DeviceObject; PIO_WORKITEM_ROUTINE WorkerRoutine; VOID *Context; } IO_WORKITEM; /** * IoAllocateWorkItem: * @DeviceObject: Existing initialized #PDEVICE_OBJECT to bind with allocated #IO_WORKITEM. * %NULL value is forbidden. * * Allocates and initializes the memory for #IO_WORKITEM. * You may pass it to IoQueueWorkItem() later. At most one active IoQueueWorkItem() * request may be pending for this returned #IO_WORKITEM. * * Returns: Allocated #IO_WORKITEM ready to be used by IoQueueWorkItem(). */ PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject) { IO_WORKITEM *r; g_return_val_if_fail(DeviceObject!=NULL,NULL); captive_new(r); r->DeviceObject=DeviceObject; r->WorkerRoutine=NULL; return r; } /** * IoFreeWorkItem: * @IoWorkItem: #IO_WORKITEM allocated by IoAllocateWorkItem(). * %NULL value is forbidden. * * Frees the resources allocated for @IoWorkItem. * No request by IoQueueWorkItem() may be pending. */ VOID IoFreeWorkItem(PIO_WORKITEM IoWorkItem) { g_return_if_fail(IoWorkItem!=NULL); g_return_if_fail(IoWorkItem->WorkerRoutine==NULL); /* no request should be pending */ g_free(IoWorkItem); } static gboolean IoQueueWorkItem_idlefunc(IO_WORKITEM *IoWorkItem /* data */) { g_return_val_if_fail(IoWorkItem!=NULL,FALSE); /* false=>remove-me */ g_return_val_if_fail(IoWorkItem->DeviceObject!=NULL,FALSE); /* false=>remove-me */ g_return_val_if_fail(IoWorkItem->WorkerRoutine!=NULL,FALSE); /* false=>remove-me */ (*IoWorkItem->WorkerRoutine)(IoWorkItem->DeviceObject,IoWorkItem->Context); ObDereferenceObject(IoWorkItem->DeviceObject); IoWorkItem->WorkerRoutine=NULL; /* request is no longer pending */ return FALSE; /* remove-me */ } /** * IoQueueWorkItem: * @IoWorkItem: Allocated space of #IO_WORKITEM to be initialize. * %NULL value is forbidden. * @WorkerRoutine: Function address to call in the idle time. * %NULL value is forbidden. * @QueueType: Queue priority. * @Context: Context pointer to pass to @WorkerRoutine during its invocation. * %NULL value is permitted. * * Inserts a work item in a queue for one of the system worker threads to * process. It will be processed through g_idle_add_full() with priority * range %G_PRIORITY_DEFAULT+10 ... %G_PRIORITY_DEFAULT+30. * * At most one active IoQueueWorkItem() request per one @IoWorkItem may be pending. */ VOID IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine,IN WORK_QUEUE_TYPE QueueType,IN PVOID Context) { gint priority; g_return_if_fail(IoWorkItem!=NULL); g_return_if_fail(IoWorkItem->DeviceObject!=NULL); g_return_if_fail(IoWorkItem->WorkerRoutine==NULL); /* no other request pending */ g_return_if_fail(WorkerRoutine!=NULL); IoWorkItem->WorkerRoutine=WorkerRoutine; IoWorkItem->Context=Context; ObReferenceObjectByPointer(IoWorkItem->DeviceObject,FILE_ALL_ACCESS,NULL,KernelMode); switch (QueueType) { case DelayedWorkQueue: priority=G_PRIORITY_DEFAULT+30; /* positive towards G_PRIORITY_HIGH_IDLE */ break; case CriticalWorkQueue: priority=G_PRIORITY_DEFAULT+20; /* positive towards G_PRIORITY_HIGH_IDLE */ break; case HyperCriticalWorkQueue: priority=G_PRIORITY_DEFAULT+10; /* positive towards G_PRIORITY_HIGH_IDLE */ break; default: g_assert_not_reached(); priority=G_PRIORITY_DEFAULT; } g_idle_add_full( priority, /* priority */ (GSourceFunc)IoQueueWorkItem_idlefunc, /* function */ IoWorkItem, /* data */ NULL); /* notify */ }