2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/stackovf.c
5 * PURPOSE: Provides Stack Overflow support for File System Drivers
6 * PROGRAMMERS: Pierre Schweitzer (pierre@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 /* We have one queue for paging files, one queue for normal files
18 * Queue 0 is for non-paging files
19 * Queue 1 is for paging files
20 * Don't add new/change current queues unless you know what you do
21 * Most of the code relies on the fact that we have two queues in that order
23 #define FSRTLP_MAX_QUEUES 2
25 typedef struct _STACK_OVERFLOW_WORK_ITEM
28 WORK_QUEUE_ITEM WorkItem
;
29 PFSRTL_STACK_OVERFLOW_ROUTINE Routine
;
32 } STACK_OVERFLOW_WORK_ITEM
, *PSTACK_OVERFLOW_WORK_ITEM
;
34 KEVENT StackOverflowFallbackSerialEvent
;
35 STACK_OVERFLOW_WORK_ITEM StackOverflowFallback
;
36 KQUEUE FsRtlWorkerQueues
[FSRTLP_MAX_QUEUES
];
38 /* PRIVATE FUNCTIONS *********************************************************/
45 FsRtlStackOverflowRead(IN PVOID Context
)
47 PSTACK_OVERFLOW_WORK_ITEM WorkItem
;
49 WorkItem
= (PSTACK_OVERFLOW_WORK_ITEM
)Context
;
51 /* Put us as top IRP for current thread */
52 IoSetTopLevelIrp((PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
);
53 /* And call FsRtlSORoutine */
54 WorkItem
->Routine(WorkItem
->Context
, WorkItem
->Event
);
56 /* If we were using fallback workitem, don't free it, just reset event */
57 if (WorkItem
== &StackOverflowFallback
)
59 KeSetEvent(&StackOverflowFallbackSerialEvent
, 0, FALSE
);
61 /* Otherwise, free the work item */
64 ExFreePoolWithTag(WorkItem
, 'Fsrs');
68 IoSetTopLevelIrp(NULL
);
76 FsRtlpPostStackOverflow(IN PVOID Context
,
78 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine
,
81 PSTACK_OVERFLOW_WORK_ITEM WorkItem
;
83 /* Try to allocate a work item */
84 WorkItem
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(STACK_OVERFLOW_WORK_ITEM
), 'FSrs');
87 /* If we failed, and we are not a paging file, just raise an error */
90 RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES
);
93 /* Otherwise, wait for fallback workitem to be available and use it */
94 KeWaitForSingleObject(&StackOverflowFallbackSerialEvent
, Executive
, KernelMode
, FALSE
, NULL
);
95 WorkItem
= &StackOverflowFallback
;
98 /* Initialize work item */
99 WorkItem
->Context
= Context
;
100 WorkItem
->Event
= Event
;
101 WorkItem
->Routine
= StackOverflowRoutine
;
102 ExInitializeWorkItem(&WorkItem
->WorkItem
, FsRtlStackOverflowRead
, WorkItem
);
104 /* And queue it in the appropriate queue (paging or not?) */
105 KeInsertQueue(&FsRtlWorkerQueues
[IsPaging
], &WorkItem
->WorkItem
.List
);
113 FsRtlWorkerThread(IN PVOID StartContext
)
117 PWORK_QUEUE_ITEM WorkItem
;
118 ULONG QueueId
= (ULONG
)StartContext
;
120 /* Set our priority according to the queue we're dealing with */
121 KeSetPriorityThread(&PsGetCurrentThread()->Tcb
, LOW_REALTIME_PRIORITY
+ QueueId
);
123 /* Loop for events */
126 /* Look for next event */
127 Entry
= KeRemoveQueue(&FsRtlWorkerQueues
[QueueId
], KernelMode
, NULL
);
128 WorkItem
= CONTAINING_RECORD(Entry
, WORK_QUEUE_ITEM
, List
);
130 /* Call its routine (here: FsRtlStackOverflowRead) */
131 WorkItem
->WorkerRoutine(WorkItem
->Parameter
);
133 /* Check we're still at passive level or bugcheck */
134 Irql
= KeGetCurrentIrql();
135 if (Irql
!= PASSIVE_LEVEL
)
137 KeBugCheckEx(IRQL_NOT_LESS_OR_EQUAL
, (ULONG_PTR
)WorkItem
->WorkerRoutine
,
138 (ULONG_PTR
)Irql
, (ULONG_PTR
)WorkItem
->WorkerRoutine
,
139 (ULONG_PTR
)WorkItem
);
150 FsRtlInitializeWorkerThread(VOID
)
155 OBJECT_ATTRIBUTES ObjectAttributes
;
157 /* Initialize each queue we have */
158 for (i
= 0; i
< FSRTLP_MAX_QUEUES
; ++i
)
160 InitializeObjectAttributes(&ObjectAttributes
,
166 /* Initialize the queue and its associated thread and pass it the queue ID */
167 KeInitializeQueue(&FsRtlWorkerQueues
[i
], 0);
168 Status
= PsCreateSystemThread(&ThreadHandle
, THREAD_ALL_ACCESS
, &ObjectAttributes
,
169 0, 0, FsRtlWorkerThread
, (PVOID
)i
);
170 if (!NT_SUCCESS(Status
))
175 /* Don't leak handle */
176 ZwClose(ThreadHandle
);
179 /* Also initialize our fallback event, set it to ensure it's already usable */
180 KeInitializeEvent(&StackOverflowFallbackSerialEvent
, SynchronizationEvent
, TRUE
);
185 /* PUBLIC FUNCTIONS **********************************************************/
188 * @name FsRtlPostPagingFileStackOverflow
189 * @implemented NT 5.2
191 * The FsRtlPostPagingFileStackOverflow routine
197 * @param StackOverflowRoutine
206 FsRtlPostPagingFileStackOverflow(IN PVOID Context
,
208 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine
)
210 FsRtlpPostStackOverflow(Context
, Event
, StackOverflowRoutine
, TRUE
);
214 * @name FsRtlPostStackOverflow
215 * @implemented NT 5.2
217 * The FsRtlPostStackOverflow routine
223 * @param StackOverflowRoutine
232 FsRtlPostStackOverflow(IN PVOID Context
,
234 IN PFSRTL_STACK_OVERFLOW_ROUTINE StackOverflowRoutine
)
236 FsRtlpPostStackOverflow(Context
, Event
, StackOverflowRoutine
, FALSE
);