:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / ke / kqueue.c
1 /*
2  * COPYRIGHT:            See COPYING in the top level directory
3  * PURPOSE:              ReactOS kernel
4  * FILE:                 ntoskrnl/ke/kqueue.c
5  * PURPOSE:              Implement device queues
6  * PROGRAMMER:           David Welch (welch@mcmail.com)
7  * REVISION HISTORY:
8  *               08/07/98: Created
9  */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ddk/ntddk.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* FUNCTIONS *****************************************************************/
19
20 VOID 
21 InsertBeforeEntryInList(PLIST_ENTRY Head, PLIST_ENTRY After, PLIST_ENTRY Entry)
22 {
23    InsertHeadList(After, Entry);
24 }
25
26 BOOLEAN STDCALL
27 KeInsertByKeyDeviceQueue (PKDEVICE_QUEUE                DeviceQueue,
28                           PKDEVICE_QUEUE_ENTRY  DeviceQueueEntry,
29                           ULONG                 SortKey)
30 {
31    KIRQL oldlvl;
32    PLIST_ENTRY current;
33    PKDEVICE_QUEUE_ENTRY entry;
34    
35    DPRINT("KeInsertByKeyDeviceQueue()\n");
36    
37    DeviceQueueEntry->Key=SortKey;
38
39    KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl);
40    
41    if (!DeviceQueue->Busy)
42      {
43         DeviceQueue->Busy=TRUE;
44         KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
45         return(FALSE);
46      }
47       
48    current=DeviceQueue->ListHead.Flink;
49    while (current!=(&DeviceQueue->ListHead))
50      {
51         entry = CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,Entry);
52         if (entry->Key < SortKey)
53           {
54              InsertBeforeEntryInList(&DeviceQueue->ListHead,
55                                      &DeviceQueueEntry->Entry,
56                                      current);
57              KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
58              return(TRUE);
59           }
60         current = current->Flink;
61      }   
62    InsertTailList(&DeviceQueue->ListHead,&DeviceQueueEntry->Entry);
63    
64    KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
65    return(TRUE);
66 }
67
68 PKDEVICE_QUEUE_ENTRY
69 STDCALL
70 KeRemoveByKeyDeviceQueue (
71         PKDEVICE_QUEUE  DeviceQueue,
72         ULONG           SortKey
73         )
74 {
75    KIRQL oldlvl;
76    PLIST_ENTRY current;
77    PKDEVICE_QUEUE_ENTRY entry;   
78    
79    assert_irql(DISPATCH_LEVEL);
80    assert(DeviceQueue!=NULL);
81    assert(DeviceQueue->Busy);
82    
83    KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl);
84    
85    current = DeviceQueue->ListHead.Flink;
86    while (current != &DeviceQueue->ListHead)
87      {
88         entry = CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,Entry);
89         if (entry->Key < SortKey ||
90             current->Flink == &DeviceQueue->ListHead)
91           {
92              RemoveEntryList(current);
93              KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
94              return(entry);
95           }
96         current = current->Flink;
97      }
98    DeviceQueue->Busy = FALSE;
99    KeReleaseSpinLock(&DeviceQueue->Lock, oldlvl);
100    return(NULL);
101 }
102
103 PKDEVICE_QUEUE_ENTRY
104 STDCALL
105 KeRemoveDeviceQueue (
106         PKDEVICE_QUEUE  DeviceQueue
107         )
108 /*
109  * FUNCTION: Removes an entry from a device queue
110  * ARGUMENTS:
111  *        DeviceQueue = Queue to remove the entry
112  * RETURNS: The removed entry
113  */
114 {
115    KIRQL oldlvl;
116    PLIST_ENTRY list_entry;
117    PKDEVICE_QUEUE_ENTRY entry;
118    
119    DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n",DeviceQueue);
120    
121    assert_irql(DISPATCH_LEVEL);
122    assert(DeviceQueue!=NULL);
123    assert(DeviceQueue->Busy);
124    
125    KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl);
126    
127    list_entry = RemoveHeadList(&DeviceQueue->ListHead);
128    if (list_entry==(&DeviceQueue->ListHead))
129      {
130         DeviceQueue->Busy=FALSE;
131         KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
132         return(NULL);
133      }
134    KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
135    
136    entry = CONTAINING_RECORD(list_entry,KDEVICE_QUEUE_ENTRY,Entry);
137    return(entry);
138 }
139
140 VOID
141 STDCALL
142 KeInitializeDeviceQueue (
143         PKDEVICE_QUEUE  DeviceQueue
144         )
145 /*
146  * FUNCTION: Intializes a device queue
147  * ARGUMENTS:
148  *       DeviceQueue = Device queue to initialize
149  */
150 {
151    assert(DeviceQueue!=NULL);
152    InitializeListHead(&DeviceQueue->ListHead);
153    DeviceQueue->Busy=FALSE;
154    KeInitializeSpinLock(&DeviceQueue->Lock);
155 }
156
157 BOOLEAN
158 STDCALL
159 KeInsertDeviceQueue (
160         PKDEVICE_QUEUE          DeviceQueue,
161         PKDEVICE_QUEUE_ENTRY    DeviceQueueEntry
162         )
163 /*
164  * FUNCTION: Inserts an entry in a device queue
165  * ARGUMENTS:
166  *        DeviceQueue = Queue to insert the entry in
167  *        DeviceQueueEntry = Entry to insert
168  * RETURNS: False is the device queue wasn't busy
169  *          True otherwise
170  */
171 {
172    KIRQL oldlvl;
173    
174    KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl);
175    
176    if (!DeviceQueue->Busy)
177      {
178         DeviceQueue->Busy=TRUE;
179         KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
180         return(FALSE);
181      }
182    
183    InsertTailList(&DeviceQueue->ListHead,
184                   &DeviceQueueEntry->Entry);
185    DeviceQueueEntry->Key=0;
186    
187    KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl);
188    return(TRUE);
189 }
190
191
192 BOOLEAN STDCALL
193 KeRemoveEntryDeviceQueue(PKDEVICE_QUEUE DeviceQueue,
194                          PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
195 {
196   UNIMPLEMENTED;
197   return(FALSE);
198 }