ReactOS 0.4.16-dev-329-g9223134
cmdelay.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmdelay.c
5 * PURPOSE: Routines for handling delay close and allocate.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS *******************************************************************/
16
18
28
35
36/* FUNCTIONS *****************************************************************/
37
38_Function_class_(KDEFERRED_ROUTINE)
39VOID
41CmpDelayCloseDpcRoutine(IN PKDPC Dpc,
45{
46 /* Sanity check */
48
49 /* Queue the work item */
51}
52
53_Function_class_(WORKER_THREAD_ROUTINE)
54VOID
56CmpDelayCloseWorker(IN PVOID Context)
57{
59 ULONG i, ConvKey;
60 PAGED_CODE();
61
62 /* Sanity check */
64
65 /* Lock the registry */
67
68 /* Acquire the delayed close table lock */
70
71 /* Iterate */
72 for (i = 0; i < (CmpDelayedCloseSize >> 2); i++)
73 {
74 /* Break out of the loop if there is nothing to process */
76
77 /* Sanity check */
79
80 /* Get the entry */
83 DelayedLRUList);
84
85 /* Save the ConvKey value of the KCB */
86 ConvKey = ListEntry->KeyControlBlock->ConvKey;
87
88 /* Release the delayed close table lock */
90
91 /* Acquire the KCB lock */
93
94 /* Reacquire the delayed close table lock */
96
97 /* Get the entry */
100 DelayedLRUList);
101
102 /* Is the entry we have still the first one? */
104 {
105 /* No, someone already inserted an entry there */
106 CmpReleaseKcbLockByKey(ConvKey);
107 break;
108 }
109
110 /* Is it a different entry? */
111 if (ConvKey != ListEntry->KeyControlBlock->ConvKey)
112 {
113 /* Release the delayed close table lock */
115
116 /* Release the KCB lock */
117 CmpReleaseKcbLockByKey(ConvKey);
118
119 /* Reacquire the delayed close table lock */
121
122 /* Iterate again */
123 continue;
124 }
125
126 /* Remove it from the end of the list */
127 ListEntry =
129
130 /* Get the containing entry */
131 ListEntry = CONTAINING_RECORD(ListEntry,
133 DelayedLRUList);
134
135 /* Process the entry */
136 if ((ListEntry->KeyControlBlock->RefCount) ||
138 {
139 /* Add it to the beginning of the list */
141
142 /* Release the delayed close table lock */
144 }
145 else
146 {
147 /* Release the delayed close table lock */
149
150 /* Zero out the DelayCloseEntry pointer */
152
153 /* Cleanup the KCB cache */
155
156 /* Free the delay item */
157 CmpFreeDelayItem(ListEntry);
158
159 /* Decrement delayed close elements count */
161 }
162
163 /* Release the KCB lock */
164 CmpReleaseKcbLockByKey(ConvKey);
165
166 /* Reacquire the delayed close table lock */
168 }
169
171 {
172 /* We're not active anymore */
174 }
175 else
176 {
177 /* We didn't process all things, so reschedule for the next time */
179 }
180
181 /* Release the delayed close table lock */
183
184 /* Unlock the registry */
186}
187
188CODE_SEG("INIT")
189VOID
190NTAPI
192{
193
194 /* Setup the delayed close lock */
196
197 /* Setup the work item */
198 ExInitializeWorkItem(&CmpDelayCloseWorkItem, CmpDelayCloseWorker, NULL);
199
200 /* Setup the list head */
202
203 /* Setup the DPC and its timer */
204 KeInitializeDpc(&CmpDelayCloseDpc, CmpDelayCloseDpcRoutine, NULL);
206}
207
208_Function_class_(KDEFERRED_ROUTINE)
209VOID
210NTAPI
211CmpDelayDerefKCBDpcRoutine(IN PKDPC Dpc,
215{
216 /* Sanity check */
218
219 /* Queue the work item */
221}
222
223_Function_class_(WORKER_THREAD_ROUTINE)
224VOID
225NTAPI
226CmpDelayDerefKCBWorker(IN PVOID Context)
227{
229 PAGED_CODE();
230
231 /* Sanity check */
233
234 /* Lock the registry and and list lock */
237
238 /* Check if the list is empty */
240 {
241 /* Grab an entry */
243
244 /* We can release the lock now */
246
247 /* Now grab the actual entry */
249 Entry->ListEntry.Flink = Entry->ListEntry.Blink = NULL;
250
251 /* Dereference and free */
254
255 /* Lock the list again */
257 }
258
259 /* We're done */
263}
264
265CODE_SEG("INIT")
266VOID
267NTAPI
269{
270 /* Initialize lock and list */
273
274 /* Setup the work item */
276 CmpDelayDerefKCBWorker,
277 NULL);
278
279 /* Setup the DPC and timer for it */
280 KeInitializeDpc(&CmpDelayDerefKCBDpc, CmpDelayDerefKCBDpcRoutine, NULL);
282}
283
284VOID
285NTAPI
287{
288 LONG OldRefCount, NewRefCount;
291 PAGED_CODE();
293 "%s - Dereferencing KCB: %p\n", __FUNCTION__, Kcb);
294
295 /* Get the previous reference count */
296 OldRefCount = *(PLONG)&Kcb->RefCount;
297 NewRefCount = OldRefCount - 1;
298 if (((NewRefCount & 0xFFFF) > 0) &&
299 (InterlockedCompareExchange((PLONG)&Kcb->RefCount,
300 NewRefCount,
301 OldRefCount) == OldRefCount))
302 {
303 /* KCB still had references, so we're done */
304 return;
305 }
306
307 /* Allocate a delay item */
309 if (!Entry) return;
310
311 /* Set the KCB */
312 Entry->Kcb = Kcb;
313
314 /* Acquire the delayed deref table lock */
316
317 /* Insert the entry into the list */
319
320 /* Check if we need to enable anything */
322 {
323 /* Yes, we have no work item, setup the interval */
325 Timeout.QuadPart = CmpDelayDerefKCBIntervalInSeconds * -10000000;
327 }
328
329 /* Release the table lock */
331}
332
333VOID
334NTAPI
336{
338 PAGED_CODE();
339
340 /* Set the worker active */
342
343 /* Setup the interval */
344 Timeout.QuadPart = CmpDelayCloseIntervalInSeconds * -10000000;
346}
347
348VOID
349NTAPI
351 IN BOOLEAN LockHeldExclusively)
352{
353 ULONG i;
354 ULONG OldRefCount, NewRefCount;
356 PAGED_CODE();
357
358 /* Sanity check */
360
361 /* Make sure it's valid */
362 if (Kcb->DelayedCloseIndex != CmpDelayedCloseSize) ASSERT(FALSE);
363
364 /* Sanity checks */
365 ASSERT(Kcb->RefCount == 0);
366 ASSERT(IsListEmpty(&Kcb->KeyBodyListHead) == TRUE);
367 for (i = 0; i < 4; i++) ASSERT(Kcb->KeyBodyArray[i] == NULL);
368
369 /* Allocate a delay item */
371 if (!Entry)
372 {
373 /* Cleanup immediately */
374 CmpCleanUpKcbCacheWithLock(Kcb, LockHeldExclusively);
375 return;
376 }
377
378 /* Sanity check */
379 if (Kcb->InDelayClose) ASSERT(FALSE);
380
381 /* Get the previous reference count */
382 OldRefCount = *(PLONG)&Kcb->InDelayClose;
383 ASSERT(OldRefCount == 0);
384
385 /* Write the new one */
386 NewRefCount = 1;
387 if (InterlockedCompareExchange((PLONG)&Kcb->InDelayClose,
388 NewRefCount,
389 OldRefCount) != OldRefCount)
390 {
391 /* Sanity check */
392 ASSERT(FALSE);
393 }
394
395 /* Reset the delayed close index */
396 Kcb->DelayedCloseIndex = 0;
397
398 /* Set up the close entry */
399 Kcb->DelayCloseEntry = Entry;
400 Entry->KeyControlBlock = Kcb;
401
402 /* Increase the number of elements */
404
405 /* Acquire the delayed close table lock */
407
408 /* Insert the entry into the list */
409 InsertHeadList(&CmpDelayedLRUListHead, &Entry->DelayedLRUList);
410
411 /* Check if we need to enable anything */
414 {
415 /* Yes, we have too many elements to close, and no work item */
417 }
418
419 /* Release the table lock */
421}
422
423VOID
424NTAPI
426{
428 ULONG NewRefCount, OldRefCount;
429 PAGED_CODE();
430
431 /* Sanity checks */
433 if (Kcb->DelayedCloseIndex == CmpDelayedCloseSize) ASSERT(FALSE);
434
435 /* Get the entry and lock the table */
436 Entry = Kcb->DelayCloseEntry;
437 ASSERT(Entry);
439
440 /* Remove the entry */
441 RemoveEntryList(&Entry->DelayedLRUList);
442
443 /* Release the lock */
445
446 /* Free the entry */
448
449 /* Reduce the number of elements */
451
452 /* Sanity check */
453 if (!Kcb->InDelayClose) ASSERT(FALSE);
454
455 /* Get the previous reference count */
456 OldRefCount = *(PLONG)&Kcb->InDelayClose;
457 ASSERT(OldRefCount == 1);
458
459 /* Write the new one */
460 NewRefCount = 0;
461 if (InterlockedCompareExchange((PLONG)&Kcb->InDelayClose,
462 NewRefCount,
463 OldRefCount) != OldRefCount)
464 {
465 /* Sanity check */
466 ASSERT(FALSE);
467 }
468
469 /* Remove the link to the entry */
470 Kcb->DelayCloseEntry = NULL;
471
472 /* Set new delay size and remove the delete flag */
473 Kcb->DelayedCloseIndex = CmpDelayedCloseSize;
474}
#define PAGED_CODE()
#define CODE_SEG(...)
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define CMTRACE(x, fmt,...)
Definition: cm.h:40
#define CM_REFERENCE_DEBUG
Definition: cm.h:26
struct _CM_DELAYED_CLOSE_ENTRY * PCM_DELAYED_CLOSE_ENTRY
FORCEINLINE VOID CmpAcquireKcbLockExclusiveByKey(IN ULONG ConvKey)
Definition: cm_x.h:143
FORCEINLINE VOID CmpReleaseKcbLockByKey(ULONG ConvKey)
Definition: cm_x.h:212
#define CMP_ASSERT_KCB_LOCK(k)
Definition: cm_x.h:278
PVOID NTAPI CmpAllocateDelayItem(VOID)
Definition: cmalloc.c:199
VOID NTAPI CmpFreeDelayItem(PVOID Entry)
Definition: cmalloc.c:267
KDPC CmpDelayCloseDpc
Definition: cmdelay.c:26
VOID NTAPI CmpAddToDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmdelay.c:350
VOID NTAPI CmpDelayDerefKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmdelay.c:286
KTIMER CmpDelayDerefKCBTimer
Definition: cmdelay.c:34
ULONG CmpDelayedCloseSize
Definition: cmdelay.c:19
WORK_QUEUE_ITEM CmpDelayDerefKCBWorkItem
Definition: cmdelay.c:17
WORK_QUEUE_ITEM CmpDelayCloseWorkItem
Definition: cmdelay.c:23
ULONG CmpDelayCloseIntervalInSeconds
Definition: cmdelay.c:25
KGUARDED_MUTEX CmpDelayDerefKCBLock
Definition: cmdelay.c:29
VOID NTAPI CmpArmDelayedCloseTimer(VOID)
Definition: cmdelay.c:335
ULONG CmpDelayDerefKCBIntervalInSeconds
Definition: cmdelay.c:32
LIST_ENTRY CmpDelayedLRUListHead
Definition: cmdelay.c:24
KGUARDED_MUTEX CmpDelayedCloseTableLock
Definition: cmdelay.c:21
VOID NTAPI CmpInitDelayDerefKCBEngine(VOID)
Definition: cmdelay.c:268
ULONG CmpDelayedCloseElements
Definition: cmdelay.c:20
BOOLEAN CmpDelayCloseWorkItemActive
Definition: cmdelay.c:22
BOOLEAN CmpDelayDerefKCBWorkItemActive
Definition: cmdelay.c:30
VOID NTAPI CmpRemoveFromDelayedClose(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmdelay.c:425
LIST_ENTRY CmpDelayDerefKCBListHead
Definition: cmdelay.c:31
KDPC CmpDelayDerefKCBDpc
Definition: cmdelay.c:33
VOID NTAPI CmpInitializeDelayedCloseTable(VOID)
Definition: cmdelay.c:191
KTIMER CmpDelayCloseTimer
Definition: cmdelay.c:27
VOID NTAPI CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively)
Definition: cmkcbncb.c:476
VOID NTAPI CmpDereferenceKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmkcbncb.c:571
VOID NTAPI CmpUnlockRegistry(VOID)
Definition: cmsysini.c:2056
VOID NTAPI CmpLockRegistry(VOID)
Definition: cmsysini.c:1970
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
#define __FUNCTION__
Definition: types.h:116
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define InterlockedCompareExchange
Definition: interlocked.h:104
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define _Function_class_(n)
Definition: no_sal2.h:398
long LONG
Definition: pedump.c:60
static ULONG Timeout
Definition: ping.c:61
base of all file and directory entries
Definition: entries.h:83
Definition: cm.h:369
LIST_ENTRY DelayedLRUList
Definition: cm.h:370
PCM_KEY_CONTROL_BLOCK KeyControlBlock
Definition: cm.h:371
ULONG DelayedCloseIndex
Definition: cm.h:278
ULONG RefCount
Definition: cm.h:272
PVOID DelayCloseEntry
Definition: cm.h:308
Definition: ketypes.h:699
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689