Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / io / iowork.c
1 /* $Id$
2  * reactos IO_WORKITEM handling by libcaptive
3  * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "reactos/ddk/iofuncs.h"        /* self */
23 #include <glib/gmessages.h>
24 #include "captive/macros.h"
25 #include "reactos/ddk/obfuncs.h"        /* for ObDereferenceObject() */
26 #include <glib/gmain.h>
27
28
29 typedef struct _IO_WORKITEM {
30         DEVICE_OBJECT *DeviceObject;
31         PIO_WORKITEM_ROUTINE WorkerRoutine;
32         VOID *Context;
33 } IO_WORKITEM;
34
35
36 /**
37  * IoAllocateWorkItem:
38  * @DeviceObject: Existing initialized #PDEVICE_OBJECT to bind with allocated #IO_WORKITEM.
39  * %NULL value is forbidden.
40  *
41  * Allocates and initializes the memory for #IO_WORKITEM.
42  * You may pass it to IoQueueWorkItem() later. At most one active IoQueueWorkItem()
43  * request may be pending for this returned #IO_WORKITEM.
44  *
45  * Returns: Allocated #IO_WORKITEM ready to be used by IoQueueWorkItem().
46  */
47 PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
48 {
49 IO_WORKITEM *r;
50
51         g_return_val_if_fail(DeviceObject!=NULL,NULL);
52         
53         captive_new(r);
54   r->DeviceObject=DeviceObject;
55         r->WorkerRoutine=NULL;
56
57         return r;
58 }
59
60
61 /**
62  * IoFreeWorkItem:
63  * @IoWorkItem: #IO_WORKITEM allocated by IoAllocateWorkItem().
64  * %NULL value is forbidden.
65  *
66  * Frees the resources allocated for @IoWorkItem.
67  * No request by IoQueueWorkItem() may be pending.
68  */
69 VOID IoFreeWorkItem(PIO_WORKITEM IoWorkItem)
70 {
71         g_return_if_fail(IoWorkItem!=NULL);
72         g_return_if_fail(IoWorkItem->WorkerRoutine==NULL);      /* no request should be pending */
73
74         g_free(IoWorkItem);
75 }
76
77
78 static gboolean IoQueueWorkItem_idlefunc(IO_WORKITEM *IoWorkItem /* data */)
79 {
80         g_return_val_if_fail(IoWorkItem!=NULL,FALSE);   /* false=>remove-me */
81         g_return_val_if_fail(IoWorkItem->DeviceObject!=NULL,FALSE);     /* false=>remove-me */
82         g_return_val_if_fail(IoWorkItem->WorkerRoutine!=NULL,FALSE);    /* false=>remove-me */
83
84         (*IoWorkItem->WorkerRoutine)(IoWorkItem->DeviceObject,IoWorkItem->Context);
85         ObDereferenceObject(IoWorkItem->DeviceObject);
86         IoWorkItem->WorkerRoutine=NULL; /* request is no longer pending */
87         return FALSE;   /* remove-me */
88 }
89
90 /**
91  * IoQueueWorkItem:
92  * @IoWorkItem: Allocated space of #IO_WORKITEM to be initialize.
93  * %NULL value is forbidden.
94  * @WorkerRoutine: Function address to call in the idle time.
95  * %NULL value is forbidden.
96  * @QueueType: Queue priority.
97  * @Context: Context pointer to pass to @WorkerRoutine during its invocation.
98  * %NULL value is permitted.
99  *
100  * Inserts a work item in a queue for one of the system worker threads to
101  * process. It will be processed through g_idle_add_full() with priority
102  * range %G_PRIORITY_DEFAULT+10 ... %G_PRIORITY_DEFAULT+30.
103  *
104  * At most one active IoQueueWorkItem() request per one @IoWorkItem may be pending.
105  */
106 VOID IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem,
107                 IN PIO_WORKITEM_ROUTINE WorkerRoutine,IN WORK_QUEUE_TYPE QueueType,IN PVOID Context)
108 {
109 gint priority;
110
111         g_return_if_fail(IoWorkItem!=NULL);
112         g_return_if_fail(IoWorkItem->DeviceObject!=NULL);
113         g_return_if_fail(IoWorkItem->WorkerRoutine==NULL);      /* no other request pending */
114         g_return_if_fail(WorkerRoutine!=NULL);
115
116         IoWorkItem->WorkerRoutine=WorkerRoutine;
117         IoWorkItem->Context=Context;
118         ObReferenceObjectByPointer(IoWorkItem->DeviceObject,FILE_ALL_ACCESS,NULL,KernelMode);
119
120         switch (QueueType) {
121                 case DelayedWorkQueue:
122                         priority=G_PRIORITY_DEFAULT+30; /* positive towards G_PRIORITY_HIGH_IDLE */
123                         break;
124                 case CriticalWorkQueue:
125                         priority=G_PRIORITY_DEFAULT+20; /* positive towards G_PRIORITY_HIGH_IDLE */
126                         break;
127                 case HyperCriticalWorkQueue:
128                         priority=G_PRIORITY_DEFAULT+10; /* positive towards G_PRIORITY_HIGH_IDLE */
129                         break;
130                 default:
131                         g_assert_not_reached();
132                         priority=G_PRIORITY_DEFAULT;
133                 }
134
135         g_idle_add_full(
136                         priority,       /* priority */
137                         (GSourceFunc)IoQueueWorkItem_idlefunc,  /* function */
138                         IoWorkItem,     /* data */
139                         NULL);  /* notify */
140 }