3 * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
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.
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.
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.
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/queue.c
23 * PURPOSE: Implements kernel queues
24 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
29 /* INCLUDES *****************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/ke.h>
33 #include <internal/id.h>
34 #include <internal/ps.h>
37 #include <internal/debug.h>
39 /* FUNCTIONS *****************************************************************/
42 KeInitializeQueue(IN PKQUEUE Queue,
43 IN ULONG Count OPTIONAL)
45 KeInitializeDispatcherHeader(&Queue->Header,
47 sizeof(KQUEUE)/sizeof(ULONG),
49 InitializeListHead(&Queue->EntryListHead);
50 InitializeListHead(&Queue->ThreadListHead);
51 Queue->RunningThreads = 0;
52 Queue->MaximumThreads = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
57 KeReadStateQueue(IN PKQUEUE Queue)
59 return(Queue->Header.SignalState);
72 DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
74 KeAcquireDispatcherDatabaseLock(FALSE);
76 InitialState = Queue->Header.SignalState;
77 Queue->Header.SignalState++;
81 InsertHeadList(&Queue->EntryListHead, Entry);
85 InsertTailList(&Queue->EntryListHead, Entry);
88 if (Queue->RunningThreads < Queue->MaximumThreads && InitialState == 0)
90 KeDispatcherObjectWake(&Queue->Header);
93 KeReleaseDispatcherDatabaseLock(FALSE);
100 KeInsertHeadQueue(IN PKQUEUE Queue,
101 IN PLIST_ENTRY Entry)
103 return KiInsertQueue(Queue,Entry,TRUE);
108 KeInsertQueue(IN PKQUEUE Queue,
109 IN PLIST_ENTRY Entry)
111 return KiInsertQueue(Queue,Entry,FALSE);
116 KeRemoveQueue(IN PKQUEUE Queue,
117 IN KPROCESSOR_MODE WaitMode,
118 IN PLARGE_INTEGER Timeout OPTIONAL)
120 PLIST_ENTRY ListEntry;
122 PKTHREAD Thread = KeGetCurrentThread();
124 KeAcquireDispatcherDatabaseLock(FALSE);
126 //assiciate new thread with queue?
127 if (Thread->Queue != Queue)
129 //remove association from other queue
130 if (!IsListEmpty(&Thread->QueueListEntry))
132 RemoveEntryList(&Thread->QueueListEntry);
135 //associate with this queue
136 InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
137 Queue->RunningThreads++;
138 Thread->Queue = Queue;
141 if (Queue->RunningThreads <= Queue->MaximumThreads && !IsListEmpty(&Queue->EntryListHead))
143 ListEntry = RemoveHeadList(&Queue->EntryListHead);
144 Queue->Header.SignalState--;
145 KeReleaseDispatcherDatabaseLock(FALSE);
149 //need to wait for it...
150 KeReleaseDispatcherDatabaseLock(FALSE);
152 Status = KeWaitForSingleObject(Queue,
158 if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
160 return (PVOID)Status;
164 KeAcquireDispatcherDatabaseLock(FALSE);
165 ListEntry = RemoveHeadList(&Queue->EntryListHead);
166 KeReleaseDispatcherDatabaseLock(FALSE);
174 KeRundownQueue(IN PKQUEUE Queue)
176 PLIST_ENTRY EnumEntry;
179 DPRINT("KeRundownQueue(Queue %x)\n", Queue);
181 //FIXME: should we wake thread waiting on a queue?
183 KeAcquireDispatcherDatabaseLock(FALSE);
185 // Clear Queue and QueueListEntry members of all threads associated with this queue
186 while (!IsListEmpty(&Queue->ThreadListHead))
188 EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
189 InitializeListHead(EnumEntry);
190 Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
191 Thread->Queue = NULL;
194 if (!IsListEmpty(&Queue->EntryListHead))
195 EnumEntry = Queue->EntryListHead.Flink;
199 KeReleaseDispatcherDatabaseLock(FALSE);