Fixed prototype for MmSetAddressRangeModified().
[reactos.git] / ntoskrnl / ke / queue.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
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; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * PROJECT:         ReactOS kernel
22  * FILE:            ntoskrnl/ke/queue.c
23  * PURPOSE:         Implements kernel queues
24  * PROGRAMMER:      Eric Kohl (ekohl@rz-online.de)
25  * UPDATE HISTORY:
26  *                  Created 04/01/2002
27  */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ddk/ntddk.h>
32 #include <ntos.h>
33 #include <internal/ke.h>
34 #include <internal/id.h>
35 #include <internal/ps.h>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* FUNCTIONS *****************************************************************/
41
42 /*
43  * @implemented
44  */
45 VOID STDCALL
46 KeInitializeQueue(IN PKQUEUE Queue,
47                   IN ULONG Count OPTIONAL)
48 {
49   KeInitializeDispatcherHeader(&Queue->Header,
50                                InternalQueueType,
51                                sizeof(KQUEUE)/sizeof(ULONG),
52                                0);
53   InitializeListHead(&Queue->EntryListHead);
54   InitializeListHead(&Queue->ThreadListHead);
55   Queue->CurrentCount = 0;
56   Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
57 }
58
59 #ifndef LIBCAPTIVE
60
61 /*
62  * @implemented
63  */
64 LONG STDCALL
65 KeReadStateQueue(IN PKQUEUE Queue)
66 {
67   return(Queue->Header.SignalState);
68 }
69
70
71 LONG STDCALL
72 KiInsertQueue(
73    IN PKQUEUE Queue,
74    IN PLIST_ENTRY Entry,
75    BOOLEAN Head
76    )
77 {
78    ULONG InitialState;
79   
80    DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
81    
82    KeAcquireDispatcherDatabaseLock(FALSE);
83    
84    InitialState = Queue->Header.SignalState;
85    Queue->Header.SignalState++;
86    
87    if (Head)
88    {
89       InsertHeadList(&Queue->EntryListHead, Entry);
90    }
91    else
92    {
93       InsertTailList(&Queue->EntryListHead, Entry);
94    }
95
96    if (Queue->CurrentCount < Queue->MaximumCount && InitialState == 0)
97    {
98       KeDispatcherObjectWake(&Queue->Header);
99    }
100
101    KeReleaseDispatcherDatabaseLock(FALSE);
102    return InitialState;
103 }
104
105
106
107 /*
108  * @implemented
109  */
110 LONG STDCALL
111 KeInsertHeadQueue(IN PKQUEUE Queue,
112                   IN PLIST_ENTRY Entry)
113 {
114    return KiInsertQueue(Queue,Entry,TRUE);
115 }
116
117
118 /*
119  * @implemented
120  */
121 LONG STDCALL
122 KeInsertQueue(IN PKQUEUE Queue,
123               IN PLIST_ENTRY Entry)
124 {
125    return KiInsertQueue(Queue,Entry,FALSE);
126 }
127
128
129 /*
130  * @implemented
131  */
132 PLIST_ENTRY STDCALL
133 KeRemoveQueue(IN PKQUEUE Queue,
134               IN KPROCESSOR_MODE WaitMode,
135               IN PLARGE_INTEGER Timeout OPTIONAL)
136 {
137    PLIST_ENTRY ListEntry;
138    NTSTATUS Status;
139    PKTHREAD Thread = KeGetCurrentThread();
140
141    KeAcquireDispatcherDatabaseLock(FALSE);
142
143    //assiciate new thread with queue?
144    if (Thread->Queue != Queue)
145    {
146       //remove association from other queue
147       if (!IsListEmpty(&Thread->QueueListEntry))
148       {
149          RemoveEntryList(&Thread->QueueListEntry);
150       }
151
152       //associate with this queue
153       InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
154       Queue->CurrentCount++;
155       Thread->Queue = Queue;
156    }
157    
158    if (Queue->CurrentCount <= Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
159    {
160       ListEntry = RemoveHeadList(&Queue->EntryListHead);
161       Queue->Header.SignalState--;
162       KeReleaseDispatcherDatabaseLock(FALSE);
163       return ListEntry;
164    }
165
166    //need to wait for it...
167    KeReleaseDispatcherDatabaseLock(FALSE);
168
169    Status = KeWaitForSingleObject(Queue,
170                                   WrQueue,
171                                   WaitMode,
172                                   TRUE,//Alertable,
173                                   Timeout);
174
175    if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
176    {
177       return (PVOID)Status;
178    }
179    else
180    {
181       KeAcquireDispatcherDatabaseLock(FALSE);
182       ListEntry = RemoveHeadList(&Queue->EntryListHead);
183       KeReleaseDispatcherDatabaseLock(FALSE);
184       return ListEntry;
185    }
186
187 }
188
189
190 /*
191  * @implemented
192  */
193 PLIST_ENTRY STDCALL
194 KeRundownQueue(IN PKQUEUE Queue)
195 {
196    PLIST_ENTRY EnumEntry;
197    PKTHREAD Thread;
198
199    DPRINT("KeRundownQueue(Queue %x)\n", Queue);
200
201    //FIXME: should we wake thread waiting on a queue? 
202
203    KeAcquireDispatcherDatabaseLock(FALSE);
204
205    // Clear Queue and QueueListEntry members of all threads associated with this queue
206    while (!IsListEmpty(&Queue->ThreadListHead))
207    {
208       EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
209       InitializeListHead(EnumEntry);
210       Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
211       Thread->Queue = NULL;
212    }
213
214    if (!IsListEmpty(&Queue->EntryListHead))
215       EnumEntry = Queue->EntryListHead.Flink;
216    else
217       EnumEntry = NULL;
218
219    KeReleaseDispatcherDatabaseLock(FALSE);
220
221    return EnumEntry;
222 }
223
224 #endif /* LIBCAPTIVE */
225
226 /* EOF */